import { expect, test } from "bun:test"; import { renderToStaticMarkup } from "react-dom/server"; import { AgentChatMessage, rewriteAgentNodeLinks, type CloudAgentChatMessage } from "@/components/canvas/canvas-cloud-agent-chat-ui"; import { canvasThemes } from "@/lib/canvas-theme"; const videoReference = { id: "video-1790385749473-q4157", nodeId: "video-1790385749473-q4157", kind: "video" as const, label: "片头镜头", title: "片头镜头", sourceType: "video" as const, previewUrl: "data:image/png;base64,preview", }; function assistantMessage(text: string): CloudAgentChatMessage { return { id: "assistant-1", role: "assistant", text }; } test("rewrites generated node IDs into semantic Markdown links", () => { const text = rewriteAgentNodeLinks("新节点 ID:video-1790385749473-q4157", [videoReference]); expect(text).toContain("新节点:[视频节点 · 片头镜头](#agent-node:video-1790385749473-q4157)"); expect(text).not.toContain("新节点 ID"); expect(text).not.toContain("video-1790385749473-q4157"); }); test("does not mistake Agent task IDs for canvas nodes", () => { const text = "任务 ag293f6d7-55b6-4a25-8c4f-8c6b2c4d9b10 已创建"; expect(rewriteAgentNodeLinks(text)).toBe(text); }); test("falls back to a node type label and URL-encodes exact reference IDs", () => { const nodeId = "video-custom:take-1"; const text = rewriteAgentNodeLinks(nodeId, [{ ...videoReference, id: nodeId, nodeId, title: "自定义镜头", label: "自定义镜头" }]); expect(text).toContain("[视频节点 · 自定义镜头](#agent-node:video-custom%3Atake-1)"); expect(rewriteAgentNodeLinks("video-123")).toContain("[视频节点](#agent-node:video-123)"); }); test("leaves fenced code blocks untouched", () => { const text = "```text\nvideo-1790385749473-q4157\n```\nvideo-1790385749473-q4157"; const rewritten = rewriteAgentNodeLinks(text, [videoReference]); expect(rewritten).toContain("```text\nvideo-1790385749473-q4157\n```"); expect(rewritten).toContain("[视频节点 · 片头镜头](#agent-node:video-1790385749473-q4157)"); }); test("renders an agent node link as a titled inline node card", () => { const html = renderToStaticMarkup( {}} />, ); const visibleText = html.replace(/<[^>]+>/gu, ""); expect(html).toContain('class="agent-message-node-link"'); expect(html).toContain('data-agent-node-id="video-1790385749473-q4157"'); expect(html).toContain("视频节点"); expect(html).toContain("片头镜头"); expect(visibleText).not.toContain("video-1790385749473-q4157"); }); test("renders the image-to-previs user request with the existing canvas node card", () => { const imageReference = { ...videoReference, kind: "image" as const, sourceType: "image" as const, label: "道姑", title: "道姑" }; const html = renderToStaticMarkup( {}} />, ); expect(html).toContain('class="agent-message-node-link"'); expect(html).toContain('class="agent-message-node-link-preview"'); expect(html).toContain("道姑"); expect(html).toContain("3D 预演台"); }); test("labels character cards by resource kind instead of the underlying text type", () => { const nodeId = "text-1790385749473-char1"; const reference = { id: nodeId, nodeId, kind: "character" as const, label: "李莫愁", title: "李莫愁", sourceType: "text" as const }; expect(rewriteAgentNodeLinks(nodeId, [reference])).toContain(`[角色卡 · 李莫愁](#agent-node:${nodeId})`); });