import { expect, test } from "bun:test"; import { DIAGRAM_FIXTURES } from "../src/fixtures"; import { DIAGRAM_ALIASES, DIAGRAM_TYPES, renderDiagram } from "../src/render"; test("every registered renderer has one resolved fixture with valid geometry and motion", () => { let types = Object.keys(DIAGRAM_TYPES).sort(); let fixtures = DIAGRAM_FIXTURES.map((entry) => entry.type).sort(); expect(fixtures).toEqual(types); for (let { type, spec } of DIAGRAM_FIXTURES) { let result = renderDiagram(spec); expect(result.ok, `${type}: ${JSON.stringify(result.ok ? [] : result.problems)}`).toBe(true); if (!result.ok) continue; expect(result.type).toBe(type); expect(result.body).not.toBe(""); expect(result.viewBox.every(Number.isFinite)).toBe(true); expect(result.viewBox[2]).toBeGreaterThan(0); expect(result.viewBox[3]).toBeGreaterThan(0); expect(result.diagnostics.filter((issue) => issue.code.startsWith("E_"))).toEqual([]); } }); test("all aliases normalize and render with their required data shape", () => { expect(Object.keys(DIAGRAM_ALIASES).length).toBeGreaterThan(0); for (let [alias, base] of Object.entries(DIAGRAM_ALIASES)) { let fixture = DIAGRAM_FIXTURES.find((entry) => entry.type === base); expect(fixture).toBeDefined(); let spec = alias === "marimekko" ? { type: alias, columns: [{ label: "A", segments: [["one", 2], ["two", 3]] }] } : alias === "dumbbell" ? { type: alias, data: [["A", 2, 3], ["B", 4, 5]] } : { ...fixture?.spec, type: alias }; let result = renderDiagram(spec); expect(result.ok, `${alias}: ${JSON.stringify(result.ok ? [] : result.problems)}`).toBe(true); if (result.ok) expect(result.type).toBe(base); } }); test("item based structures reject duplicate node IDs before rendering", () => { for ( let [type, field] of [ ["process", "steps"], ["pyramid", "levels"], ["layers", "layers"], ["loop", "steps"], ] as const ) { let fixture = DIAGRAM_FIXTURES.find((entry) => entry.type === type); expect(fixture).toBeDefined(); let original = fixture?.spec[field] as Array>; let items = original.map((value, index) => index < 2 ? { ...(typeof value === "string" ? { label: value } : value), id: "repeated" } : value ); let result = renderDiagram({ ...fixture?.spec, type, [field]: items }); expect(result.ok, type).toBe(false); if (result.ok) continue; expect(result.problems[0]).toMatchObject({ code: "E_DUP_ID", at: `${field}[1].id`, }); expect("body" in result).toBe(false); } let generatedCollision = renderDiagram({ type: "process", steps: ["First", { id: "s0", label: "Second" }], }); expect(generatedCollision.ok).toBe(false); if (!generatedCollision.ok) { expect(generatedCollision.problems[0]).toMatchObject({ code: "E_DUP_ID", at: "steps[1].id", }); } }); test("text and attribute payloads remain escaped", () => { let result = renderDiagram({ type: "architecture", nodes: [ { id: "a", label: "", row: 0, col: 0 }, { id: "b", label: "A & B", row: 0, col: 1 }, ], edges: [["a", "b", '" onload="alert(1)']], }); expect(result.ok).toBe(true); if (!result.ok) return; expect(result.body).not.toContain("