import assert from "node:assert/strict"; import test from "node:test"; import { normalizeDiagramIR, validateDiagramIR } from "./diagram-ir.js"; test("IR v2 supports pages, containers, geometry, semantics, and waypoints", () => { const ir = validateDiagramIR({ version: 2, title: "Platform", pages: [{ id: "system", title: "System", layout: { type: "layered", direction: "horizontal", gridSize: 10 }, nodes: [ { id: "zone", label: "Application zone", kind: "container", geometry: { x: 20, y: 20, width: 520, height: 240 } }, { id: "web", label: "Web", kind: "service", parentId: "zone", properties: { tier: "edge" } }, { id: "api", label: "API", kind: "service", parentId: "zone" }, ], edges: [{ id: "request", source: "web", target: "api", kind: "request", waypoints: [{ x: 200, y: 100 }] }], }], provenance: { source: "test" }, }); const normalized = normalizeDiagramIR(ir); assert.equal(normalized.version, 2); assert.equal(normalized.pages.length, 1); assert.equal(normalized.pages[0].nodes[0].kind, "container"); assert.deepEqual(normalized.pages[0].edges[0].waypoints, [{ x: 200, y: 100 }]); }); test("IR v2 rejects unknown parents, parent cycles, unsupported fields, and reserved IDs", () => { assert.throws(() => validateDiagramIR({ version: 2, pages: [{ id: "page", title: "Page", nodes: [{ id: "0", label: "Reserved", parentId: "missing" }], edges: [], }], }), /reserved id.*unknown parent/si); assert.throws(() => validateDiagramIR({ version: 2, pages: [{ id: "page", title: "Page", nodes: [ { id: "a", label: "A", parentId: "b" }, { id: "b", label: "B", parentId: "a" }, ], edges: [], }], }), /parent cycle/i); assert.throws(() => validateDiagramIR({ version: 2, pages: [{ id: "page", title: "Page", nodes: [ { id: "parent", label: "Not a container" }, { id: "child", label: "Child", parentId: "parent" }, ], edges: [], }], }), /parent.*not a container/i); assert.throws(() => validateDiagramIR({ version: 2, unexpected: true, pages: [{ id: "page", title: "Page", nodes: [{ id: "a", label: "A", typo: true }], edges: [] }], }), /unsupported field/i); }); test("IR v1 normalizes into a single v2 page without changing stable IDs", () => { const v1 = validateDiagramIR({ version: 1, title: "Legacy", direction: "horizontal", nodes: [{ id: "client", label: "Client" }, { id: "api", label: "API" }], edges: [{ id: "call", source: "client", target: "api" }], }); const normalized = normalizeDiagramIR(v1); assert.equal(normalized.pages[0].title, "Legacy"); assert.deepEqual(normalized.pages[0].nodes.map((node) => node.id), ["client", "api"]); assert.equal(normalized.pages[0].edges[0].id, "call"); assert.throws(() => validateDiagramIR({ version: 1, title: 42, nodes: [{ id: "node", label: "Node" }] }), /title must be a string/i); });