import { describe, expect, test } from "vitest"; import { BRANCH_X_GAP, BRANCH_Y_GAP, NODE_WIDTH, buildCanvasEdge, createCanvasNodeFromGeneration, getBranchPosition, normalizeStoredCanvas } from "./canvas-model"; const generation = { id: "node_123", title: "Learning AMD GPUs visually", imageUrl: "http://localhost:8000/outputs/node_123.png", imagePrompt: "A luminous visual research board about AMD GPUs", summary: "A one-paragraph public summary grounded in the retrieved sources.", query: "teach me AMD GPUs", visualFacts: [ { label: "ROCm stack", detail: "AMD's software stack for accelerated AI workloads." } ], sources: [ { title: "AMD Developer Cloud", url: "https://www.amd.com/en/developer-cloud.html", snippet: "Cloud access to AMD GPUs." } ], suggestedBranches: ["compare clouds", "show model options"] }; describe("canvas model", () => { test("creates a root image node at the canvas center", () => { const node = createCanvasNodeFromGeneration(generation, { x: 0, y: 0 }); expect(node.id).toBe("node_123"); expect(node.type).toBe("veniceImage"); expect(node.position).toEqual({ x: 0, y: 0 }); expect(node.data.summary).toBe("A one-paragraph public summary grounded in the retrieved sources."); expect(node.data.visualFacts).toEqual([ { label: "ROCm stack", detail: "AMD's software stack for accelerated AI workloads." } ]); expect(node.data.sources).toHaveLength(1); expect(node.data.parentId).toBeUndefined(); }); test("uses a readable visual-page node size instead of a thumbnail", () => { expect(NODE_WIDTH).toBeGreaterThanOrEqual(700); }); test("places branch nodes to the right and staggered by sibling index", () => { expect(getBranchPosition({ x: 40, y: 80 }, 0)).toEqual({ x: 40 + BRANCH_X_GAP, y: 80 }); expect(getBranchPosition({ x: 40, y: 80 }, 2)).toEqual({ x: 40 + BRANCH_X_GAP, y: 80 + BRANCH_Y_GAP * 2, }); }); test("creates an animated edge from parent to child", () => { const edge = buildCanvasEdge("parent", "child"); expect(edge).toMatchObject({ id: "parent-child", source: "parent", target: "child", animated: true }); }); test("normalizes legacy stored nodes that do not have summary or visual facts", () => { const legacyCanvas = { nodes: [ { id: "legacy", type: "veniceImage", position: { x: 12, y: 34 }, data: { title: "Legacy node", imageUrl: "/api/outputs/legacy.png", imagePrompt: "old prompt", query: "old query", sources: [], suggestedBranches: [] } } ], edges: [] }; const normalized = normalizeStoredCanvas(legacyCanvas); expect(normalized.nodes[0].data.summary).toBe("Generated visual search node for old query."); expect(normalized.nodes[0].data.visualFacts).toEqual([]); expect(normalized.nodes[0].data.sources).toEqual([]); expect(normalized.nodes[0].data.suggestedBranches).toEqual([]); }); });