test(desktop): 前端单元 + 关键组件测试(Vitest + RTL,31 例)
测试基建:vite.config.ts 加 test 配置(jsdom + setup),package.json 加 test/test:watch 脚本,src/test/setup.ts 引 jest-dom;tsconfig 把测试文件 exclude, 使 CI 现有 tsc --noEmit 不检查测试文件(仍绿),测试由 Vitest 自跑(先不接 CI)。 覆盖(31 例 / 4 文件): - dsl:exportDsl 节点/边映射 + config 兜底 + branch 真假边 sourceHandle 条件; validate 空画布/孤立节点/必填项缺失。 - version:isNewer 版本比较矩阵;checkUpdate 有更新/同版/旧版/404限流/离线异常; openExternal Wails / 浏览器双路径。 - run:deriveNodes start→running、end→done+耗时、error、error 不被 start 覆盖、 info 累计 notes、首现顺序、label 更新。 - UpdateBanner(RTL):无更新不渲染、有更新显版本+点下载调 openExternal、点忽略消失。 小改:version.ts 导出 isNewer(原私有)以便直接测版本判定矩阵。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import type { Node, Edge } from "@xyflow/react";
|
||||
import { exportDsl, validate } from "./dsl";
|
||||
|
||||
// 构造画布节点的小工具(只填导出/校验关心的字段)。
|
||||
function node(id: string, kind: string, config?: unknown, label?: string): Node {
|
||||
return { id, position: { x: 0, y: 0 }, data: { kind, label, config } } as unknown as Node;
|
||||
}
|
||||
function edge(source: string, target: string, sourceHandle?: string): Edge {
|
||||
return { id: `${source}-${target}`, source, target, sourceHandle } as unknown as Edge;
|
||||
}
|
||||
|
||||
describe("exportDsl", () => {
|
||||
it("把节点映射为 {id,kind,label,config}", () => {
|
||||
const dsl = exportDsl([node("in", "input", { text: "hi" }, "输入")], []);
|
||||
expect(dsl.version).toBe("1");
|
||||
expect(dsl.nodes).toEqual([{ id: "in", kind: "input", label: "输入", config: { text: "hi" } }]);
|
||||
});
|
||||
|
||||
it("缺失 config 时回退为空对象", () => {
|
||||
const dsl = exportDsl([node("in", "input")], []);
|
||||
expect(dsl.nodes[0].config).toEqual({});
|
||||
});
|
||||
|
||||
it("仅在存在 sourceHandle 时才带上该字段(branch 真/假边)", () => {
|
||||
const dsl = exportDsl(
|
||||
[node("b", "branch"), node("t", "agent"), node("f", "agent")],
|
||||
[edge("b", "t", "true"), edge("b", "f")],
|
||||
);
|
||||
expect(dsl.edges[0]).toEqual({ source: "b", target: "t", sourceHandle: "true" });
|
||||
expect(dsl.edges[1]).toEqual({ source: "b", target: "f" });
|
||||
expect("sourceHandle" in dsl.edges[1]).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("validate", () => {
|
||||
it("空画布报 error", () => {
|
||||
const issues = validate([], []);
|
||||
expect(issues).toHaveLength(1);
|
||||
expect(issues[0].level).toBe("error");
|
||||
});
|
||||
|
||||
it("单节点不报孤立警告(length>1 才校验连线)", () => {
|
||||
const issues = validate([node("in", "input", { text: "hi" })], []);
|
||||
expect(issues.some((i) => i.msg.includes("孤立"))).toBe(false);
|
||||
});
|
||||
|
||||
it("多节点中未连线的节点报孤立 warn", () => {
|
||||
const issues = validate(
|
||||
[node("a", "input", { text: "hi" }), node("b", "agent", { system: "x" })],
|
||||
[], // 都没连
|
||||
);
|
||||
expect(issues.filter((i) => i.msg.includes("孤立"))).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("必填项缺失报 warn(input.text 为必填)", () => {
|
||||
const issues = validate([node("in", "input", { text: "" })], []);
|
||||
expect(issues.some((i) => i.level === "warn" && i.msg.includes("缺必填项"))).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user