89 lines
3.0 KiB
TypeScript
89 lines
3.0 KiB
TypeScript
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);
|
|
});
|