99 lines
3.3 KiB
TypeScript
99 lines
3.3 KiB
TypeScript
import { describe, expect, it } from "@suaveplan/testing/runner";
|
||
import { encode } from "../encoder/encoder.js";
|
||
import { Tagged } from "../tags/tagged.js";
|
||
import { bytesToDiagnostic, toDiagnostic } from "./diagnostic.js";
|
||
|
||
describe("toDiagnostic — primitives", () => {
|
||
it.each([
|
||
[null, "null"],
|
||
[undefined, "undefined"],
|
||
[true, "true"],
|
||
[false, "false"],
|
||
[0, "0"],
|
||
[-0, "-0"],
|
||
[1, "1"],
|
||
[-1, "-1"],
|
||
[1.5, "1.5"],
|
||
[Number.NaN, "NaN"],
|
||
[Number.POSITIVE_INFINITY, "Infinity"],
|
||
[Number.NEGATIVE_INFINITY, "-Infinity"],
|
||
[42n, "42"],
|
||
[-42n, "-42"],
|
||
])("%p → %s", { timeout: 5000 }, (input, expected) => {
|
||
expect(toDiagnostic(input)).toBe(expected);
|
||
});
|
||
|
||
it("strings are quoted + escapes applied", { timeout: 5000 }, () => {
|
||
expect(toDiagnostic("hello")).toBe('"hello"');
|
||
expect(toDiagnostic('he said "hi"')).toBe('"he said \\"hi\\""');
|
||
expect(toDiagnostic("a\\b")).toBe('"a\\\\b"');
|
||
expect(toDiagnostic("line1\nline2")).toBe('"line1\\nline2"');
|
||
expect(toDiagnostic("\t")).toBe('"\\t"');
|
||
expect(toDiagnostic("\r")).toBe('"\\r"');
|
||
expect(toDiagnostic("")).toBe('"\\u0001"');
|
||
});
|
||
|
||
it("byte strings → h'<hex>'", { timeout: 5000 }, () => {
|
||
expect(toDiagnostic(new Uint8Array([0xde, 0xad, 0xbe, 0xef]))).toBe(
|
||
"h'deadbeef'"
|
||
);
|
||
expect(toDiagnostic(new Uint8Array())).toBe("h''");
|
||
});
|
||
});
|
||
|
||
describe("toDiagnostic — composite", () => {
|
||
it("array", { timeout: 5000 }, () => {
|
||
expect(toDiagnostic([1, 2, 3])).toBe("[1, 2, 3]");
|
||
});
|
||
|
||
it("nested array", { timeout: 5000 }, () => {
|
||
expect(toDiagnostic([1, [2, 3]])).toBe("[1, [2, 3]]");
|
||
});
|
||
|
||
it("Map renders keys and values via diagnostic", { timeout: 5000 }, () => {
|
||
const m = new Map<unknown, unknown>([
|
||
[1, "a"],
|
||
["b", 2],
|
||
]);
|
||
expect(toDiagnostic(m)).toBe('{1: "a", "b": 2}');
|
||
});
|
||
|
||
it("plain object renders keys as quoted strings", { timeout: 5000 }, () => {
|
||
expect(toDiagnostic({ a: 1, b: "two" })).toBe('{"a": 1, "b": "two"}');
|
||
});
|
||
|
||
it("Tagged renders as tag(inner)", { timeout: 5000 }, () => {
|
||
expect(toDiagnostic(new Tagged(0, "2026-05-10T12:00:00Z"))).toBe(
|
||
'0("2026-05-10T12:00:00Z")'
|
||
);
|
||
});
|
||
|
||
it("Date renders as tag-0", { timeout: 5000 }, () => {
|
||
const d = new Date("2026-05-10T12:00:00Z");
|
||
expect(toDiagnostic(d)).toBe('0("2026-05-10T12:00:00.000Z")');
|
||
});
|
||
});
|
||
|
||
describe("toDiagnostic — non-CBOR-encodable fallback", () => {
|
||
it("function → <function>", { timeout: 5000 }, () => {
|
||
expect(toDiagnostic(() => 1)).toBe("<function>");
|
||
});
|
||
it("symbol → <symbol>", { timeout: 5000 }, () => {
|
||
expect(toDiagnostic(Symbol("x"))).toBe("<symbol>");
|
||
});
|
||
});
|
||
|
||
describe("bytesToDiagnostic", () => {
|
||
it("decodes + formats raw tags", { timeout: 5000 }, () => {
|
||
const wire = encode([new Tagged(99, 42), { x: true }]);
|
||
expect(bytesToDiagnostic(wire)).toBe('[99(42), {"x": true}]');
|
||
});
|
||
|
||
it("byte strings round-trip through diagnostic notation", {
|
||
timeout: 5000,
|
||
}, () => {
|
||
const wire = encode(new Uint8Array([0x01, 0x02]));
|
||
expect(bytesToDiagnostic(wire)).toBe("h'0102'");
|
||
});
|
||
});
|