Files
sundynix-agentix/sundynix-desktop/frontend/src/lib/dsl.test.ts
T
Blizzard f37d046f2c 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>
2026-06-24 11:53:54 +08:00

61 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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("必填项缺失报 warninput.text 为必填)", () => {
const issues = validate([node("in", "input", { text: "" })], []);
expect(issues.some((i) => i.level === "warn" && i.msg.includes("缺必填项"))).toBe(true);
});
});