// vibed import { deepStrictEqual, equal, ok, strictEqual, throws, } from "node:assert/strict"; import { FjsonError, parse, stringify } from "./mod.ts"; Deno.test("pretty output uses fjson keys and balanced nested indentation", () => { const value = { name: "fJSON", options: { enabled: true, targets: ["linux", "macos"] }, "@scope/pkg": { $valid_key2: 'šŸ˜€\nquoted "text"' }, }; const printed = stringify(value); strictEqual( printed, `name: "fJSON" options: { enabled: true targets: ["linux", "macos"] } "@scope/pkg": { $valid_key2: "šŸ˜€\\nquoted \\"text\\"" }`, ); deepStrictEqual(parse(printed), value); }); Deno.test("long arrays expand and printing is stable", () => { const value = { records: [{ x: [1, 2] }, { x: [null, false] }], long: Array.from({ length: 40 }, (_, i) => i), }; const text = stringify(value); ok(text.includes("long: [\n"), text); for (const line of text.split("\n")) { ok([...line].length <= 80, line); } ok(text.includes(" x: [1, 2]\n }"), text); deepStrictEqual(parse(text), value); strictEqual(stringify(parse(text)), text); }); Deno.test("parser and printer accept the same nesting depths", () => { for (const leaf of [null, [], {}]) { let value: unknown = leaf; for (let depth = 0; depth < 132; depth += 1) { for (const candidate of [value, { root: value }]) { const encoded = JSON.stringify(candidate); let parseKind: string | undefined; try { parse(encoded); } catch (error) { ok(error instanceof FjsonError); parseKind = error.kind; } let printed: string | undefined; let printKind: string | undefined; try { printed = stringify(candidate); } catch (error) { ok(error instanceof FjsonError); printKind = error.kind; } strictEqual(printKind === undefined, parseKind === undefined, encoded); if (printed !== undefined) { deepStrictEqual(parse(printed), candidate); } else { strictEqual(printKind, "nesting"); strictEqual(parseKind, printKind); } } value = [value]; } } }); Deno.test("arbitrary json values round trip including escaped keys", () => { const values: unknown[] = [ null, true, 42, -0.125, " \tšŸ˜€", [], {}, [{}, [], null], JSON.parse( '{"0": 1, "": 2, "true": 3, "some-key": 4, "ę—„ęœ¬čŖž": "\\r\\n", "__proto__": {"ok": true}}', ), ]; for (const value of values) { const text = stringify(value); deepStrictEqual(parse(text), JSON.parse(JSON.stringify(value)), text); } }); Deno.test("roots print without a final newline", () => { strictEqual(stringify(null), "null"); strictEqual(stringify(false), "false"); strictEqual(stringify(42), "42"); strictEqual(stringify("šŸ˜€"), '"šŸ˜€"'); strictEqual(stringify([]), "[]"); strictEqual(stringify({}), "{}"); strictEqual(stringify({ a: 1 }), "a: 1"); strictEqual(stringify([1, true]), "[1, true]"); strictEqual(stringify({ nested: {} }), "nested: {}"); }); Deno.test("non-finite numbers print as null like JSON", () => { strictEqual(stringify(NaN), "null"); strictEqual(stringify(Infinity), "null"); strictEqual(stringify([NaN]), "[null]"); }); Deno.test("unserializable values throw TypeError", () => { for ( const value of [ undefined, () => {}, Symbol("x"), 10n, (() => { const circular: Record = {}; circular["self"] = circular; return circular; })(), ] ) { throws(() => stringify(value), TypeError); } }); Deno.test("custom limits control printing", () => { let value: unknown = null; for (let i = 0; i < 6; i += 1) value = [value]; const text = stringify(value, { maxDepth: 6 }); deepStrictEqual(parse(text, { maxDepth: 6 }), value); const error = (() => { try { stringify(value, { maxDepth: 4 }); } catch (caught) { ok(caught instanceof FjsonError); return caught; } throw new Error("expected nesting error"); })(); strictEqual(error.kind, "nesting"); ok(error.message.includes("4 levels"), error.message); ok(parse(text, { maxDepth: 6 })); throws(() => parse(text, { maxDepth: 4 }), FjsonError); equal(stringify({ a: [0] }, { maxDepth: 1 }), "a: [0]"); throws(() => stringify({ a: [[0]] }, { maxDepth: 1 }), FjsonError); });