import { expect, test } from "bun:test";
import { renderToStaticMarkup } from "react-dom/server";
import { AgentToolCard } from "@/components/canvas/canvas-cloud-agent-chat-ui";
import { canvasThemes } from "@/lib/canvas-theme";
test("automatic correction is neutral and collapsed, with recovery and exhaustion history", () => {
for (const theme of [canvasThemes.dark, canvasThemes.light]) {
for (const status of ["retrying", "recovered", "exhausted"]) {
const html = renderToStaticMarkup();
expect(html).toContain("data-agent-tool-retry");
expect(html).toContain(" {
const html = renderToStaticMarkup();
expect(html).toContain("已获取可用模型");
expect(html).toContain('class="sr-only">已完成');
expect(html).not.toContain("agent-tool-label");
});
test("empty read and operation events stay flat instead of rendering empty cards", () => {
const readHtml = renderToStaticMarkup();
const operationHtml = renderToStaticMarkup();
expect(readHtml).toContain("agent-tool-row--plain");
expect(operationHtml).toContain("agent-tool-row--plain");
});
test("canvas reads show one node by default and expose the collapsed count", () => {
const html = renderToStaticMarkup( {}} />);
// 清单档的 chip 必须是"存在式":它只说明画布上有这个节点,没看过它的画面
expect(html).toContain("画布上有图片节点《第一个节点》");
expect(html).not.toContain("读取了图片节点《第一个节点》");
expect(html).not.toContain("画布上有文本节点《第二个节点》");
expect(html).toContain("另有 2 个节点只是清单(未查看画面),展开查看");
expect(html).toContain("已读取画布清单(未查看画面)");
});
test("the vision card points at the image it actually sent", () => {
const html = renderToStaticMarkup( {}} />);
expect(html).toContain("查看画面");
expect(html).toContain("agent-tool-row--vision");
expect(html).toContain("已附上 2 张画面");
expect(html).toContain("查看了图片节点《封面.png》");
expect(html).toContain("查看了图片节点《剧照.png》");
expect(html).not.toContain("操作画布");
expect(html).not.toContain("操作已完成");
});
test("a reused observation is not reported as a fresh look at the picture", () => {
const html = renderToStaticMarkup( {}} />);
expect(html).toContain("复用已记录的观察,未重复看图");
expect(html).toContain("复用观察:图片节点《封面.png》");
expect(html).not.toContain("查看了");
});
test("failed tools retain a visible failure label", () => {
const html = renderToStaticMarkup();
expect(html).toContain("agent-tool-label");
expect(html).toContain("执行失败");
});
test("long skill references wrap rather than truncate", () => {
const html = renderToStaticMarkup();
expect(html).toContain("references/storyboard-pass.md");
expect(html).toContain("break-words");
expect(html).not.toContain("truncate");
});
test("failed media shows its error and task identifier without hovering", () => {
const html = renderToStaticMarkup();
expect(html).toContain(">上游拒绝该生成规格");
expect(html).toContain("任务 ID:task-123");
});
test("canvas action trace is accessible and links to persisted node identities", () => {
const html = renderToStaticMarkup( {}} />);
expect(html).toContain('data-agent-node-id="video-1"');
expect(html).toContain('aria-label="在画布中定位满月动画"');
expect(html).toContain("创建了视频节点《满月动画》");
expect(html).toContain("引用了图片节点《满月照片》");
expect(html).not.toContain('disabled=""');
});
test("failed media trace retains node title and collapsible upstream details", () => {
const text = "上游拒绝规格:" + "错误详情".repeat(80);
const html = renderToStaticMarkup( {}} />);
expect(html).toContain("生成未完成:视频节点《满月动画》");
expect(html).toContain("查看完整错误详情");
expect(html).toContain("任务 ID:task-failed");
expect(html).toContain("