Files
ttstd-infinite-canvas/web/test/cloud-agent-plan.test.ts
T
AetherNo2332 6c92c3be7a chore(web): 前端格式 - 统一十个文件的 Prettier 格式 (#561)
Original-Commit: ade0049c0b80733dfea563bac2aae9260e373cf0
style(web): 前端格式 - 补 Prettier 格式(10 个文件)

这 10 个文件(3 个组件/样式与设置页、4 个 admin 主题与控件、1 个 lib、2 个测试)
用仓库自带 Prettier 检查会 warn,`bun scripts/check-changed-formatting.mjs` 在改动到它们时
会直接判红。本次只做格式化,不改任何行为:合并的 CSS 声明、去掉多余换行与括号、
统一链式调用换行。

验证:prettier --write 后 `check-changed-formatting.mjs` 通过、typecheck 通过、
1940 条前端测试全过、eslint 通过。
2026-09-21 09:37:19 +08:00

72 lines
3.5 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import { agentPlanVisible, latestAgentPlanItems, pendingAgentQuestion } from "@/lib/canvas/cloud-agent-plan";
const items = (...statuses: Array<"pending" | "doing" | "done">) => statuses.map((status, index) => ({ id: `${index + 1}`, title: `第 ${index + 1} 项`, status }));
/**
* 回归(2026-09-16):一个对话会跨多轮运行,每轮各有一条 `plan-${runId}` 清单消息,
* 都在同一个 messages 数组里。原来取的是**第一条**,于是清单永远钉在第 1 轮的初始状态 ——
* 后面怎么推进都不刷新、全部做完也不消失(实测反馈:plan 完成了不更新、全完成也不关闭)。
*/
describe("latestAgentPlanItems", () => {
test("跨轮取最新那份,而不是第一条", () => {
const messages = [
{ id: "plan-run-1", planItems: items("pending", "pending") },
{ id: "user-1", text: "..." },
{ id: "plan-run-2", planItems: items("done", "doing") },
];
expect(latestAgentPlanItems(messages).map((entry) => entry.status)).toEqual(["done", "doing"]);
});
test("最新那份全部完成 → 清单收起", () => {
const messages = [
{ id: "plan-run-1", planItems: items("pending") },
{ id: "plan-run-2", planItems: items("done", "done") },
];
const plan = latestAgentPlanItems(messages);
expect(plan.every((entry) => entry.status === "done")).toBe(true);
expect(agentPlanVisible(plan)).toBe(false);
});
test("最新那份还没做完 → 继续显示", () => {
expect(agentPlanVisible(latestAgentPlanItems([{ id: "plan-run-1", planItems: items("done", "doing") }]))).toBe(true);
});
test("没有任何清单(包括带空数组的)→ 空且不显示", () => {
expect(latestAgentPlanItems([])).toEqual([]);
expect(latestAgentPlanItems([{ id: "user-1" }, { id: "plan-run-1", planItems: [] }])).toEqual([]);
expect(agentPlanVisible([])).toBe(false);
});
});
/**
* 回归(2026-09-16):运行中输入框是禁用的,模型在正文里提问用户根本答不了
* (生产实测它连问 4 轮、白烧十几步)。`ask_user` 让本轮收尾并把问题结构化,
* 这个选择器决定「现在该不该把选项面板亮给用户」。
*/
describe("pendingAgentQuestion", () => {
const question = { question: "选哪个模型?", options: [{ label: "H3文生视频" }, { label: "Seedance 2.5" }] };
test("有未作答的提问 → 亮面板", () => {
const messages = [{ role: "user" }, { role: "assistant", question }];
expect(pendingAgentQuestion(messages)?.question).toBe("选哪个模型?");
});
test("提问之后用户已回复 → 收起面板", () => {
const messages = [{ role: "assistant", question }, { role: "user" }];
expect(pendingAgentQuestion(messages)).toBeUndefined();
});
test("多轮提问取最新那道;旧的那道不算数", () => {
const later = { question: "确认开始吗?", options: [{ label: "开始" }, { label: "再改改" }] };
const messages = [{ role: "assistant", question }, { role: "user" }, { role: "assistant", question }, { role: "assistant", question: later }];
expect(pendingAgentQuestion(messages)?.question).toBe("确认开始吗?");
});
test("没有提问 → 不亮面板", () => {
expect(pendingAgentQuestion([])).toBeUndefined();
expect(pendingAgentQuestion([{ role: "assistant" }, { role: "user" }])).toBeUndefined();
});
});