aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorGravatar dave caruso <me@paperdave.net> 2023-08-17 20:56:52 -0700
committerGravatar GitHub <noreply@github.com> 2023-08-17 20:56:52 -0700
commit6fd0043f6bf766cc488a88339059e8879fa07161 (patch)
treed5289bcaf0880a3bf1e2f0b1c681aff93188fe51 /test
parent0424fd8f6e7549ed779788006acdc97a8467e287 (diff)
downloadbun-6fd0043f6bf766cc488a88339059e8879fa07161.tar.gz
bun-6fd0043f6bf766cc488a88339059e8879fa07161.tar.zst
bun-6fd0043f6bf766cc488a88339059e8879fa07161.zip
Add `util.inspect.custom` support to `util.inspect/Bun.inspect/console.log` (#4194)
* start work on util.inspect.custom * asdf * finish util inspect custom inspect * inspect * fix tests * revert * tidy * revert * oops * test * fix issues
Diffstat (limited to 'test')
-rw-r--r--test/js/bun/util/inspect.test.js44
-rw-r--r--test/js/node/util/bun-inspect.test.ts23
-rw-r--r--test/js/node/util/custom-inspect.test.js155
3 files changed, 199 insertions, 23 deletions
diff --git a/test/js/bun/util/inspect.test.js b/test/js/bun/util/inspect.test.js
index 4d5165543..6ae9e9816 100644
--- a/test/js/bun/util/inspect.test.js
+++ b/test/js/bun/util/inspect.test.js
@@ -94,12 +94,12 @@ it("utf16 property name", () => {
});
it("latin1", () => {
- expect(Bun.inspect("English")).toBe("English");
- expect(Bun.inspect("Français")).toBe("Français");
- expect(Bun.inspect("Ελληνική")).toBe("Ελληνική");
- expect(Bun.inspect("日本語")).toBe("日本語");
- expect(Bun.inspect("Emoji😎")).toBe("Emoji😎");
- expect(Bun.inspect("Français / Ελληνική")).toBe("Français / Ελληνική");
+ expect(Bun.inspect("English")).toBe('"English"');
+ expect(Bun.inspect("Français")).toBe('"Français"');
+ expect(Bun.inspect("Ελληνική")).toBe('"Ελληνική"');
+ expect(Bun.inspect("日本語")).toBe('"日本語"');
+ expect(Bun.inspect("Emoji😎")).toBe('"Emoji😎"');
+ expect(Bun.inspect("Français / Ελληνική")).toBe('"Français / Ελληνική"');
});
it("Request object", () => {
@@ -213,12 +213,11 @@ it("jsx with fragment", () => {
it("inspect", () => {
expect(Bun.inspect(new TypeError("what")).includes("TypeError: what")).toBe(true);
- expect("hi").toBe("hi");
+ expect(Bun.inspect("hi")).toBe('"hi"');
expect(Bun.inspect(1)).toBe("1");
expect(Bun.inspect(NaN)).toBe("NaN");
expect(Bun.inspect(Infinity)).toBe("Infinity");
expect(Bun.inspect(-Infinity)).toBe("-Infinity");
- expect(Bun.inspect(1, "hi")).toBe("1 hi");
expect(Bun.inspect([])).toBe("[]");
expect(Bun.inspect({})).toBe("{}");
expect(Bun.inspect({ hello: 1 })).toBe("{\n hello: 1\n}");
@@ -229,7 +228,7 @@ it("inspect", () => {
while (str.length < 4096) {
str += "123";
}
- expect(Bun.inspect(str)).toBe(str);
+ expect(Bun.inspect(str)).toBe('"' + str + '"');
// expect(Bun.inspect(new Headers())).toBe("Headers (0 KB) {}");
expect(Bun.inspect(new Response()).length > 0).toBe(true);
// expect(
@@ -277,18 +276,15 @@ describe("latin1 supplemental", () => {
it(`latin1 (input) \"${input}\" ${output}`, () => {
expect(Bun.inspect(input)).toBe(output);
});
- it(`latin1 (output) \"${output}\"`, () => {
- expect(Bun.inspect(output)).toBe(output);
- });
- // this test is failing:
- // it(`latin1 (property key)`, () => {
- // expect(
- // Object.keys({
- // ä: 1,
- // })[0].codePointAt(0),
- // ).toBe(228);
- // });
}
+ // this test is failing:
+ it(`latin1 (property key)`, () => {
+ expect(
+ Object.keys({
+ ä: 1,
+ })[0].codePointAt(0),
+ ).toBe(228);
+ });
});
const fixture = [
@@ -329,7 +325,9 @@ describe("crash testing", () => {
for (let input of fixture) {
it(`inspecting "${input.toString().slice(0, 20).replaceAll("\n", "\\n")}" doesn't crash`, async () => {
try {
+ console.log("asked" + input.toString().slice(0, 20).replaceAll("\n", "\\n"));
Bun.inspect(await input());
+ console.log("who");
} catch (e) {
// this can throw its fine
}
@@ -338,7 +336,7 @@ describe("crash testing", () => {
});
it("possibly formatted emojis log", () => {
- expect(Bun.inspect("✔", "hey")).toBe("✔ hey");
+ expect(Bun.inspect("✔")).toBe('"✔"');
});
it("new Date(..)", () => {
@@ -352,8 +350,8 @@ it("new Date(..)", () => {
}
expect(Bun.inspect(new Date("March 27, 2023 " + hour + ":54:00"))).toBe("2023-03-27T09:54:00.000Z");
expect(Bun.inspect(new Date("2023-03-27T" + hour + ":54:00"))).toBe("2023-03-27T09:54:00.000Z");
- expect(Bun.inspect(new Date(2023, 02, 27, -offset))).toBe("2023-03-27T00:00:00.000Z");
- expect(Bun.inspect(new Date(2023, 02, 27, 09 - offset, 54, 0))).toBe("2023-03-27T09:54:00.000Z");
+ expect(Bun.inspect(new Date(2023, 2, 27, -offset))).toBe("2023-03-27T00:00:00.000Z");
+ expect(Bun.inspect(new Date(2023, 2, 27, 9 - offset, 54, 0))).toBe("2023-03-27T09:54:00.000Z");
expect(Bun.inspect(new Date("1679911059000"))).toBe("Invalid Date");
expect(Bun.inspect(new Date("hello world"))).toBe("Invalid Date");
diff --git a/test/js/node/util/bun-inspect.test.ts b/test/js/node/util/bun-inspect.test.ts
new file mode 100644
index 000000000..308f275b9
--- /dev/null
+++ b/test/js/node/util/bun-inspect.test.ts
@@ -0,0 +1,23 @@
+import { describe, it, expect } from "bun:test";
+
+describe("Bun.inspect", () => {
+ it("depth < 0 throws", () => {
+ expect(() => Bun.inspect({}, { depth: -1 })).toThrow();
+ expect(() => Bun.inspect({}, { depth: -13210 })).toThrow();
+ });
+ it("depth = Infinity works", () => {
+ function createRecursiveObject(n: number): any {
+ if (n === 0) return { hi: true };
+ return { a: createRecursiveObject(n - 1) };
+ }
+
+ const obj = createRecursiveObject(1000);
+
+ expect(Bun.inspect(obj, { depth: Infinity })).toContain("hi");
+ // this gets converted to u16, which if just truncating, will turn into 0
+ expect(Bun.inspect(obj, { depth: 0x0fff0000 })).toContain("hi");
+ });
+ it("depth = 0", () => {
+ expect(Bun.inspect({ a: { b: { c: { d: 1 } } } }, { depth: 0 })).toEqual("{\n a: [Object ...]\n}");
+ });
+});
diff --git a/test/js/node/util/custom-inspect.test.js b/test/js/node/util/custom-inspect.test.js
new file mode 100644
index 000000000..06cad262a
--- /dev/null
+++ b/test/js/node/util/custom-inspect.test.js
@@ -0,0 +1,155 @@
+// this file is compatible with jest to test node.js' util.inspect as well as bun's
+
+const util = require("util");
+
+test("util.inspect.custom exists", () => {
+ expect(util.inspect.custom).toEqual(Symbol.for("nodejs.util.inspect.custom"));
+});
+
+const customSymbol = util.inspect.custom;
+
+for (const [name, inspect] of process.versions.bun
+ ? [
+ ["util.inspect", util.inspect],
+ ["Bun.inspect", Bun.inspect],
+ ]
+ : [["util.inspect", util.inspect]]) {
+ test(name + " calls inspect.custom", () => {
+ const obj = {
+ [customSymbol]() {
+ return "42";
+ },
+ };
+
+ expect(inspect(obj)).toBe("42");
+ });
+
+ test(name + " calls inspect.custom recursivly", () => {
+ const obj = {
+ [customSymbol]() {
+ return {
+ [customSymbol]() {
+ return "42";
+ },
+ };
+ },
+ };
+
+ expect(inspect(obj)).toBe("42");
+ });
+
+ test(name + " calls inspect.custom recursivly nested", () => {
+ const obj = {
+ [customSymbol]() {
+ return {
+ prop: {
+ [customSymbol]() {
+ return "42";
+ },
+ },
+ };
+ },
+ };
+
+ expect(inspect(obj).replace(/\s/g, "")).toBe("{prop:42}");
+ });
+
+ test(name + " calls inspect.custom recursivly nested 2", () => {
+ const obj = {
+ prop: {
+ [customSymbol]() {
+ return {
+ [customSymbol]() {
+ return "42";
+ },
+ };
+ },
+ },
+ };
+
+ expect(inspect(obj).replace(/\s/g, "")).toBe("{prop:42}");
+ });
+
+ test(name + " calls inspect.custom with valid options", () => {
+ const obj = {
+ [customSymbol](depth, options, inspect) {
+ expect(this === obj).toBe(true);
+ expect(inspect).toBe(util.inspect);
+ expect(options.stylize).toBeDefined();
+ expect(depth).toBeDefined(2);
+ return "good";
+ },
+ };
+
+ expect(inspect(obj).replace(/\s/g, "")).toBe("good");
+ });
+
+ test(name + " stylize function works without color", () => {
+ const obj = {
+ [customSymbol](depth, options, inspect) {
+ expect(options.stylize).toBeDefined();
+ expect(options.stylize("foo", "whatever")).toBe("foo");
+ expect(options.stylize("hello", "string")).toBe("hello");
+ return "good";
+ },
+ };
+
+ expect(inspect(obj).replace(/\s/g, "")).toBe("good");
+ });
+
+ test(name + " stylize function works with color", () => {
+ const obj = {
+ [customSymbol](depth, options, inspect) {
+ expect(options.stylize).toBeDefined();
+ expect(options.stylize("foo", "invalid")).toBe("foo");
+ expect(options.stylize("foo", "boolean")).toBe("\u001b[33mfoo\u001b[39m");
+ expect(options.stylize("hello", "string")).toBe("\u001b[32mhello\u001b[39m");
+ return "good";
+ },
+ };
+
+ expect(inspect(obj, { colors: true }).replace(/\s/g, "")).toBe("good");
+ });
+
+ test(name + " stylize function gives correct depth", () => {
+ const obj = {
+ [customSymbol](depth, options, inspect) {
+ return [depth, options.depth];
+ },
+ };
+ expect(inspect(obj, { depth: 3 }).replace(/\s/g, "")).toBe("[3,3]");
+ });
+ test(name + " stylize function gives correct depth", () => {
+ const obj = {
+ prop: {
+ [customSymbol](depth, options, inspect) {
+ return [depth, options.depth];
+ },
+ },
+ };
+ expect(inspect(obj, { depth: 3 }).replace(/\s/g, "")).toBe("{prop:[2,3]}");
+ });
+ test(name + " non-callable does not get called", () => {
+ const obj = {
+ [customSymbol]: 512,
+ };
+ expect(inspect(obj, { depth: 3 }).replace(/\s/g, "")).toBe("{[Symbol(nodejs.util.inspect.custom)]:512}");
+ });
+
+ const exceptions = [new Error("don't crash!"), 42];
+
+ test.each(exceptions)(name + " handles exceptions %s", err => {
+ const obj = {
+ [customSymbol]() {
+ throw err;
+ },
+ };
+
+ if (Bun.inspect === inspect) {
+ // make sure this doesnt crash
+ expect(inspect(obj)).toBeString();
+ } else {
+ expect(() => inspect(obj)).toThrow();
+ }
+ });
+}