import { describe, expect, it } from "vitest"; import { layout } from "./layout"; import type { Topology } from "./api"; const TOPO: Topology = { trees: [ { id: "core", label: "Core", root: true }, { id: "sdlc", label: "SDLC", root: false }, ], nodes: [ { id: "intake", label: "Intake", agent: "coordinator", tree: "core", kind: "phase", gated: false }, { id: "clarify", label: "Clarify", agent: "Claude", tree: "sdlc", kind: "gate", gated: false }, { id: "plan", label: "Plan", agent: "Claude", tree: "sdlc", kind: "phase", gated: false }, { id: "review", label: "Review", agent: "GPT-4.1", tree: "sdlc", kind: "phase", gated: false }, ], edges: [ { from: "intake", to: "clarify", kind: "spine" }, { from: "clarify", to: "plan", kind: "spine" }, { from: "plan", to: "review", kind: "spine" }, { from: "review", to: "plan", kind: "loopback" }, ], }; describe("layout", () => { it("produces a laid-out node per topology node", () => { const { nodes, edges } = layout(TOPO, {}, null); expect(nodes).toHaveLength(4); expect(edges).toHaveLength(4); // every node has a numeric position assigned by dagre for (const n of nodes) { expect(typeof n.position.x).toBe("number"); expect(typeof n.position.y).toBe("number"); } }); it("applies live state + count to the matching node", () => { const { nodes } = layout(TOPO, { clarify: { state: "awaiting_human", count: 2 } }, null); const clarify = nodes.find((n) => n.id === "clarify")!; expect(clarify.data.state).toBe("awaiting_human"); expect(clarify.data.count).toBe(2); const plan = nodes.find((n) => n.id === "plan")!; expect(plan.data.state).toBe("idle"); }); it("marks the selected task's path and dims the rest", () => { const path = new Set(["intake", "clarify"]); const { nodes } = layout(TOPO, {}, path); expect(nodes.find((n) => n.id === "intake")!.data.onPath).toBe(true); expect(nodes.find((n) => n.id === "intake")!.data.dimmed).toBe(false); expect(nodes.find((n) => n.id === "review")!.data.onPath).toBe(false); expect(nodes.find((n) => n.id === "review")!.data.dimmed).toBe(true); }); it("styles loopback edges distinctly (dashed)", () => { const { edges } = layout(TOPO, {}, null); const loop = edges.find((e) => e.id === "review->plan")!; expect(loop.style?.strokeDasharray).toBeTruthy(); }); });