Skip to content

Commit 3e6efe8

Browse files
committed
👍 Add inspect function to inspect value
1 parent 9a9a081 commit 3e6efe8

File tree

3 files changed

+154
-0
lines changed

3 files changed

+154
-0
lines changed

__snapshots__/inspect_test.ts.snap

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
export const snapshot = {};
2+
3+
snapshot[`inspect > string 1`] = `'"hello world"'`;
4+
5+
snapshot[`inspect > number 1`] = `"100"`;
6+
7+
snapshot[`inspect > bigint 1`] = `"100n"`;
8+
9+
snapshot[`inspect > boolean 1`] = `"true"`;
10+
11+
snapshot[`inspect > array 1`] = `"[]"`;
12+
13+
snapshot[`inspect > array 2`] = `"[0, 1, 2]"`;
14+
15+
snapshot[`inspect > array 3`] = `'[0, "a", true]'`;
16+
17+
snapshot[`inspect > array 4`] = `"[0, [1, [2]]]"`;
18+
19+
snapshot[`inspect > record 1`] = `"{}"`;
20+
21+
snapshot[`inspect > record 2`] = `"{a: 0, b: 1, c: 2}"`;
22+
23+
snapshot[`inspect > record 3`] = `
24+
'{
25+
a: "a",
26+
b: 1,
27+
c: true
28+
}'
29+
`;
30+
31+
snapshot[`inspect > record 4`] = `"{a: {b: {c: 0}}}"`;
32+
33+
snapshot[`inspect > function 1`] = `"inspect"`;
34+
35+
snapshot[`inspect > function 2`] = `"(anonymous)"`;
36+
37+
snapshot[`inspect > null 1`] = `"null"`;
38+
39+
snapshot[`inspect > undefined 1`] = `"undefined"`;
40+
41+
snapshot[`inspect > symbol 1`] = `"Symbol(a)"`;
42+
43+
snapshot[`inspect > date 1`] = `"Date"`;
44+
45+
snapshot[`inspect > promise 1`] = `"Promise"`;

inspect.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
const defaultThreshold = 20;
2+
3+
export type InspectOptions = {
4+
// The maximum number of characters of a single attribute
5+
threshold?: number;
6+
};
7+
8+
/**
9+
* Inspect a value
10+
*/
11+
export function inspect(value: unknown, options: InspectOptions = {}): string {
12+
if (value === null) {
13+
return "null";
14+
} else if (Array.isArray(value)) {
15+
return inspectArray(value, options);
16+
}
17+
switch (typeof value) {
18+
case "string":
19+
return JSON.stringify(value);
20+
case "bigint":
21+
return `${value}n`;
22+
case "object":
23+
if (value.constructor?.name !== "Object") {
24+
return value.constructor?.name;
25+
}
26+
return inspectRecord(value as Record<PropertyKey, unknown>, options);
27+
case "function":
28+
return value.name || "(anonymous)";
29+
}
30+
return value?.toString() ?? "undefined";
31+
}
32+
33+
function inspectArray(value: unknown[], options: InspectOptions): string {
34+
const { threshold = defaultThreshold } = options;
35+
const vs = value.map((v) => inspect(v, options));
36+
const s = vs.join(", ");
37+
if (s.length <= threshold) return `[${s}]`;
38+
const m = vs.join(",\n");
39+
return `[\n${indent(2, m)}\n]`;
40+
}
41+
42+
function inspectRecord(
43+
value: Record<PropertyKey, unknown>,
44+
options: InspectOptions,
45+
): string {
46+
const { threshold = defaultThreshold } = options;
47+
const vs = Object.entries(value).map(([k, v]) =>
48+
`${k}: ${inspect(v, options)}`
49+
);
50+
const s = vs.join(", ");
51+
if (s.length <= threshold) return `{${s}}`;
52+
const m = vs.join(",\n");
53+
return `{\n${indent(2, m)}\n}`;
54+
}
55+
56+
function indent(level: number, text: string): string {
57+
const prefix = " ".repeat(level);
58+
return text.split("\n").map((line) => `${prefix}${line}`).join("\n");
59+
}

inspect_test.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import {
2+
assertSnapshot,
3+
} from "https://deno.land/[email protected]/testing/snapshot.ts";
4+
import { inspect } from "./inspect.ts";
5+
6+
Deno.test("inspect", async (t) => {
7+
await t.step("string", async (t) => {
8+
await assertSnapshot(t, inspect("hello world"));
9+
});
10+
await t.step("number", async (t) => {
11+
await assertSnapshot(t, inspect(100));
12+
});
13+
await t.step("bigint", async (t) => {
14+
await assertSnapshot(t, inspect(100n));
15+
});
16+
await t.step("boolean", async (t) => {
17+
await assertSnapshot(t, inspect(true));
18+
});
19+
await t.step("array", async (t) => {
20+
await assertSnapshot(t, inspect([]));
21+
await assertSnapshot(t, inspect([0, 1, 2]));
22+
await assertSnapshot(t, inspect([0, "a", true]));
23+
await assertSnapshot(t, inspect([0, [1, [2]]]));
24+
});
25+
await t.step("record", async (t) => {
26+
await assertSnapshot(t, inspect({}));
27+
await assertSnapshot(t, inspect({ a: 0, b: 1, c: 2 }));
28+
await assertSnapshot(t, inspect({ a: "a", b: 1, c: true }));
29+
await assertSnapshot(t, inspect({ a: { b: { c: 0 } } }));
30+
});
31+
await t.step("function", async (t) => {
32+
await assertSnapshot(t, inspect(inspect));
33+
await assertSnapshot(t, inspect(() => {}));
34+
});
35+
await t.step("null", async (t) => {
36+
await assertSnapshot(t, inspect(null));
37+
});
38+
await t.step("undefined", async (t) => {
39+
await assertSnapshot(t, inspect(undefined));
40+
});
41+
await t.step("symbol", async (t) => {
42+
await assertSnapshot(t, inspect(Symbol("a")));
43+
});
44+
await t.step("date", async (t) => {
45+
await assertSnapshot(t, inspect(new Date()));
46+
});
47+
await t.step("promise", async (t) => {
48+
await assertSnapshot(t, inspect(new Promise(() => {})));
49+
});
50+
});

0 commit comments

Comments
 (0)