表格布局替换为按分组展示的卡片式布局,新增 group 字段配置和 TargetBoard/TargetCard 等组件。模态框详情页支持时间范围筛选和分页,SummaryCards 减为 3 个。API 端点变更:trend/history 改用 from/to 参数,history 支持分页。recentSampleCount 硬编码为 30。
133 lines
4.6 KiB
TypeScript
133 lines
4.6 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
||
import { runCommandCheck } from "../../../src/server/checker/command-runner";
|
||
import type { ResolvedCommandTarget } from "../../../src/server/checker/types";
|
||
|
||
function makeTarget(
|
||
command: Partial<ResolvedCommandTarget["command"]>,
|
||
overrides?: Partial<ResolvedCommandTarget>,
|
||
): ResolvedCommandTarget {
|
||
return {
|
||
type: "command",
|
||
name: "test-cmd",
|
||
group: "default",
|
||
command: {
|
||
exec: "echo",
|
||
args: ["hello"],
|
||
cwd: "/tmp",
|
||
env: {},
|
||
maxOutputBytes: 1024 * 1024,
|
||
...command,
|
||
},
|
||
intervalMs: 60000,
|
||
timeoutMs: 5000,
|
||
...overrides,
|
||
};
|
||
}
|
||
|
||
describe("runCommandCheck", () => {
|
||
test("exitCode=0 成功", async () => {
|
||
const result = await runCommandCheck(makeTarget({ exec: "true", args: [] }));
|
||
expect(result.success).toBe(true);
|
||
expect(result.matched).toBe(true);
|
||
expect(result.statusDetail).toBe("exitCode=0");
|
||
expect(result.failure).toBeNull();
|
||
});
|
||
|
||
test("exitCode=1 不匹配默认 [0]", async () => {
|
||
const result = await runCommandCheck(makeTarget({ exec: "false", args: [] }));
|
||
expect(result.success).toBe(false);
|
||
expect(result.matched).toBe(false);
|
||
expect(result.statusDetail).toBe("exitCode=1");
|
||
expect(result.failure).not.toBeNull();
|
||
expect(result.failure!.phase).toBe("exitCode");
|
||
});
|
||
|
||
test("exitCode=1 匹配自定义 [1]", async () => {
|
||
const result = await runCommandCheck(makeTarget({ exec: "false", args: [] }, { expect: { exitCode: [1] } }));
|
||
expect(result.success).toBe(true);
|
||
expect(result.matched).toBe(true);
|
||
expect(result.statusDetail).toBe("exitCode=1");
|
||
});
|
||
|
||
test("命令不存在返回 spawn 错误", async () => {
|
||
const result = await runCommandCheck(makeTarget({ exec: "/nonexistent/command/xyz" }));
|
||
expect(result.success).toBe(false);
|
||
expect(result.failure).not.toBeNull();
|
||
expect(result.failure!.phase).toBe("exitCode");
|
||
expect(result.failure!.message).toBeTruthy();
|
||
});
|
||
|
||
test("超时返回错误", async () => {
|
||
const result = await runCommandCheck(makeTarget({ exec: "sleep", args: ["10"] }, { timeoutMs: 100 }));
|
||
expect(result.success).toBe(false);
|
||
expect(result.failure).not.toBeNull();
|
||
expect(result.failure!.message).toContain("超时");
|
||
});
|
||
|
||
test("stdout 输出捕获", async () => {
|
||
const result = await runCommandCheck(makeTarget({ exec: "echo", args: ["hello world"] }));
|
||
expect(result.success).toBe(true);
|
||
});
|
||
|
||
test("stdout 匹配 expect", async () => {
|
||
const result = await runCommandCheck(
|
||
makeTarget({ exec: "echo", args: ["hello"] }, { expect: { stdout: [{ contains: "hello" }] } }),
|
||
);
|
||
expect(result.success).toBe(true);
|
||
expect(result.matched).toBe(true);
|
||
});
|
||
|
||
test("stdout 不匹配 expect", async () => {
|
||
const result = await runCommandCheck(
|
||
makeTarget({ exec: "echo", args: ["hello"] }, { expect: { stdout: [{ contains: "nonexistent" }] } }),
|
||
);
|
||
expect(result.success).toBe(false);
|
||
expect(result.failure!.phase).toBe("stdout");
|
||
});
|
||
|
||
test("stderr 匹配 expect", async () => {
|
||
const result = await runCommandCheck(
|
||
makeTarget({ exec: "bash", args: ["-c", "echo error >&2"] }, { expect: { stderr: [{ contains: "error" }] } }),
|
||
);
|
||
expect(result.success).toBe(true);
|
||
expect(result.matched).toBe(true);
|
||
});
|
||
|
||
test("输出超过 maxOutputBytes", async () => {
|
||
const result = await runCommandCheck(
|
||
makeTarget({
|
||
exec: "bash",
|
||
args: ["-c", "yes | head -1000"],
|
||
maxOutputBytes: 10,
|
||
}),
|
||
);
|
||
expect(result.success).toBe(false);
|
||
expect(result.failure).not.toBeNull();
|
||
expect(result.failure!.message).toContain("超过限制");
|
||
});
|
||
|
||
test("durationMs 非空", async () => {
|
||
const result = await runCommandCheck(makeTarget({ exec: "true", args: [] }));
|
||
expect(result.durationMs).not.toBeNull();
|
||
expect(result.durationMs!).toBeGreaterThanOrEqual(0);
|
||
});
|
||
|
||
test("ls 命令执行成功", async () => {
|
||
const result = await runCommandCheck(makeTarget({ exec: "ls", args: ["/tmp"] }));
|
||
expect(result.success).toBe(true);
|
||
expect(result.statusDetail).toBe("exitCode=0");
|
||
});
|
||
|
||
test("不使用 shell,通配符不被展开", async () => {
|
||
const result = await runCommandCheck(
|
||
makeTarget({ exec: "echo", args: ["*"] }, { expect: { stdout: [{ contains: "*" }] } }),
|
||
);
|
||
expect(result.success).toBe(true);
|
||
});
|
||
|
||
test("不提供 stdin,等待输入的命令会阻塞超时", async () => {
|
||
const result = await runCommandCheck(makeTarget({ exec: "bash", args: ["-c", "read line"] }, { timeoutMs: 500 }));
|
||
expect(result.success).toBe(false);
|
||
});
|
||
});
|