import assert from "node:assert/strict"; import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import test from "node:test"; import { parseAllPages } from "../../services/drawio-parser/parser.js"; import { run } from "./action.js"; const VALID_SPEC = `version: 1 title: Login flow direction: horizontal nodes: - id: client label: Client - id: api label: API edges: - id: login source: client target: api label: HTTPS `; test("build converts a YAML Diagram IR into deterministic native Draw.io", () => { const dir = mkdtempSync(join(tmpdir(), "drawio-build-test-")); const input = join(dir, "login.yaml"); const output = join(dir, "login.drawio"); try { writeFileSync(input, VALID_SPEC, "utf8"); const result = run(input, 0, output); assert.equal(existsSync(output), true); assert.deepEqual(result.summary, { nodes: 2, edges: 1, pages: 1 }); const firstXml = readFileSync(output, "utf8"); run(input, 0, output); assert.equal(readFileSync(output, "utf8"), firstXml); const [page] = parseAllPages(output); assert.equal(page.pageName, "Login flow"); assert.deepEqual([...page.shapes.keys()].sort(), ["api", "client"]); assert.equal(page.edges[0].sourceId, "client"); assert.equal(page.edges[0].targetId, "api"); assert.equal(page.shapes.get("client")?.x, 40); assert.equal(page.shapes.get("api")?.x, 240); } finally { rmSync(dir, { recursive: true, force: true }); } }); test("build expands default page dimensions to fit generated content", () => { const dir = mkdtempSync(join(tmpdir(), "drawio-build-page-size-test-")); const input = join(dir, "wide.yaml"); const output = join(dir, "wide.drawio"); try { const nodes = Array.from({ length: 10 }, (_, index) => ` - { id: node-${index}, label: Node ${index} }`).join("\n"); writeFileSync(input, `version: 1\ndirection: horizontal\nnodes:\n${nodes}\n`, "utf8"); run(input, 0, output); const [page] = parseAllPages(output); const right = Math.max(...[...page.shapes.values()].map((shape) => shape.x2)); assert.ok(page.pageWidth >= right + 40); } finally { rmSync(dir, { recursive: true, force: true }); } }); test("build rejects duplicate IDs and unknown edge endpoints", () => { const dir = mkdtempSync(join(tmpdir(), "drawio-build-invalid-test-")); const input = join(dir, "invalid.yaml"); const output = join(dir, "invalid.drawio"); try { writeFileSync(input, `version: 1\nnodes:\n - { id: repeated, label: A }\n - { id: repeated, label: B }\nedges:\n - { id: edge, source: repeated, target: missing }\n`, "utf8"); assert.throws(() => run(input, 0, output), /duplicate node id.*unknown target/si); assert.equal(existsSync(output), false); } finally { rmSync(dir, { recursive: true, force: true }); } }); test("build serializes every v2 page and honors explicit geometry and waypoints", () => { const dir = mkdtempSync(join(tmpdir(), "drawio-build-v2-test-")); const input = join(dir, "platform.yaml"); const output = join(dir, "platform.drawio"); try { writeFileSync(input, `version: 2\ntitle: Platform\ntheme: zinc\nprovenance: { source: test }\nproperties: { audience: engineering }\nextensions: { owner: drawio-main }\npages:\n - id: system\n title: System\n properties: { view: logical }\n layout: { type: manual }\n nodes:\n - id: client\n label: Client\n kind: actor\n properties: { tier: edge }\n provenance: { source: inventory }\n extensions: { critical: true }\n geometry: { x: 40, y: 80, width: 120, height: 60 }\n - id: api\n label: API\n geometry: { x: 300, y: 80, width: 120, height: 60 }\n edges:\n - id: call\n source: client\n target: api\n kind: request\n properties: { protocol: HTTPS }\n waypoints: [{ x: 230, y: 110 }]\n - id: deployment\n title: Deployment\n nodes:\n - { id: server, label: Server }\n edges: []\n`, "utf8"); const result = run(input, 0, output); assert.deepEqual(result.summary, { nodes: 3, edges: 1, pages: 2 }); const xml = readFileSync(output, "utf8"); assert.match(xml, /data-theme="zinc"/); assert.match(xml, /data-provenance="\{"source":"test"\}"/); assert.match(xml, /data-properties="\{"audience":"engineering"\}"/); assert.match(xml, /data-kind="actor"/); assert.match(xml, /data-properties="\{"tier":"edge"\}"/); assert.match(xml, /data-kind="request"/); assert.match(xml, /data-properties="\{"protocol":"HTTPS"\}"/); const pages = parseAllPages(output); assert.deepEqual(pages.map((page) => page.pageName), ["System", "Deployment"]); assert.equal(pages[0].shapes.get("api")?.x, 300); assert.deepEqual(pages[0].edges[0].waypoints, [{ x: 230, y: 110 }]); } finally { rmSync(dir, { recursive: true, force: true }); } });