1
0
Files
DiAL/tests/server/checker/fetcher.test.ts
lanyuanxiaoyao 548b44d28e feat: 重构 Dashboard 为卡片式分组布局
表格布局替换为按分组展示的卡片式布局,新增 group 字段配置和 TargetBoard/TargetCard 等组件。模态框详情页支持时间范围筛选和分页,SummaryCards 减为 3 个。API 端点变更:trend/history 改用 from/to 参数,history 支持分页。recentSampleCount 硬编码为 30。
2026-05-11 08:54:21 +08:00

260 lines
7.7 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 { afterAll, beforeAll, describe, expect, test } from "bun:test";
import { runHttpCheck } from "../../../src/server/checker/fetcher";
describe("runHttpCheck", () => {
test("checkExpect 已移除", async () => {
const mod = await import("../../../src/server/checker/fetcher");
expect((mod as Record<string, unknown>).checkExpect).toBeUndefined();
expect((mod as Record<string, unknown>).fetchTarget).toBeUndefined();
});
});
describe("runHttpCheck 集成", () => {
let server: ReturnType<typeof Bun.serve>;
let baseUrl: string;
beforeAll(() => {
server = Bun.serve({
port: 0,
fetch(req) {
const url = new URL(req.url);
switch (url.pathname) {
case "/ok":
return new Response("hello world", {
headers: { "content-type": "text/plain", "x-custom": "test-value" },
});
case "/json":
return new Response(JSON.stringify({ status: "ok" }), {
headers: { "content-type": "application/json" },
});
case "/echo":
return new Response(JSON.stringify({ method: req.method, body: req.body ? "present" : "empty" }), {
headers: { "content-type": "application/json" },
});
case "/large":
return new Response("x".repeat(2000));
case "/notfound":
return new Response("not found", { status: 404 });
case "/slow":
return new Response("slow", { status: 200 });
default:
return new Response("ok");
}
},
});
baseUrl = `http://localhost:${server.port}`;
});
afterAll(() => {
server.stop();
});
function makeTarget(overrides: {
url?: string;
method?: string;
body?: string;
headers?: Record<string, string>;
expect?: Record<string, unknown>;
maxBodyBytes?: number;
timeoutMs?: number;
}) {
return {
type: "http" as const,
name: "test-http",
group: "default",
http: {
url: overrides.url ?? `${baseUrl}/ok`,
method: overrides.method ?? "GET",
headers: overrides.headers ?? ({} as Record<string, string>),
body: overrides.body,
maxBodyBytes: overrides.maxBodyBytes ?? 1024 * 1024,
},
intervalMs: 60000,
timeoutMs: overrides.timeoutMs ?? 5000,
expect: overrides.expect as import("../../../src/server/checker/types").HttpExpectConfig | undefined,
};
}
test("成功请求 200", async () => {
const result = await runHttpCheck(makeTarget({ url: `${baseUrl}/ok` }));
expect(result.success).toBe(true);
expect(result.matched).toBe(true);
expect(result.statusDetail).toBe("HTTP 200");
expect(result.durationMs).not.toBeNull();
expect(result.failure).toBeNull();
});
test("404 不匹配默认 status [200]", async () => {
const result = await runHttpCheck(makeTarget({ url: `${baseUrl}/notfound` }));
expect(result.success).toBe(false);
expect(result.matched).toBe(false);
expect(result.statusDetail).toBe("HTTP 404");
expect(result.failure).not.toBeNull();
expect(result.failure!.phase).toBe("status");
});
test("404 匹配自定义 status [404]", async () => {
const result = await runHttpCheck(
makeTarget({
url: `${baseUrl}/notfound`,
expect: { status: [404] },
}),
);
expect(result.success).toBe(true);
expect(result.matched).toBe(true);
});
test("headers 检查通过", async () => {
const result = await runHttpCheck(
makeTarget({
url: `${baseUrl}/ok`,
expect: { headers: { "x-custom": "test-value" } },
}),
);
expect(result.success).toBe(true);
expect(result.matched).toBe(true);
});
test("headers 检查失败", async () => {
const result = await runHttpCheck(
makeTarget({
url: `${baseUrl}/ok`,
expect: { headers: { "x-custom": "wrong-value" } },
}),
);
expect(result.success).toBe(false);
expect(result.failure!.phase).toBe("headers");
});
test("body contains 检查", async () => {
const result = await runHttpCheck(
makeTarget({
url: `${baseUrl}/ok`,
expect: { body: [{ contains: "hello" }] },
}),
);
expect(result.success).toBe(true);
expect(result.matched).toBe(true);
});
test("body contains 失败", async () => {
const result = await runHttpCheck(
makeTarget({
url: `${baseUrl}/ok`,
expect: { body: [{ contains: "nonexistent" }] },
}),
);
expect(result.success).toBe(false);
expect(result.failure!.phase).toBe("body");
});
test("body json 检查", async () => {
const result = await runHttpCheck(
makeTarget({
url: `${baseUrl}/json`,
expect: { body: [{ json: { path: "$.status", equals: "ok" } }] },
}),
);
expect(result.success).toBe(true);
});
test("响应体超过 maxBodyBytes", async () => {
const result = await runHttpCheck(
makeTarget({
url: `${baseUrl}/large`,
maxBodyBytes: 100,
expect: { body: [{ contains: "x" }] },
}),
);
expect(result.success).toBe(false);
expect(result.failure).not.toBeNull();
expect(result.failure!.phase).toBe("body");
expect(result.failure!.message).toContain("超过限制");
});
test("请求超时", async () => {
const timeoutServer = Bun.serve({
port: 0,
async fetch() {
await new Promise((resolve) => setTimeout(resolve, 10000));
return new Response("late");
},
});
try {
const result = await runHttpCheck(
makeTarget({
url: `http://localhost:${timeoutServer.port}/`,
timeoutMs: 100,
}),
);
expect(result.success).toBe(false);
expect(result.failure).not.toBeNull();
expect(result.failure!.message).toContain("超时");
} finally {
timeoutServer.stop();
}
});
test("快速失败status 失败时不读取 body", async () => {
const result = await runHttpCheck(
makeTarget({
url: `${baseUrl}/notfound`,
expect: { status: [200], body: [{ contains: "something" }] },
}),
);
expect(result.success).toBe(false);
expect(result.failure!.phase).toBe("status");
});
test("快速失败headers 失败时不读取 body", async () => {
const result = await runHttpCheck(
makeTarget({
url: `${baseUrl}/ok`,
expect: { headers: { "x-missing": "value" }, body: [{ contains: "hello" }] },
}),
);
expect(result.success).toBe(false);
expect(result.failure!.phase).toBe("headers");
});
test("status 通过但 body 失败", async () => {
const result = await runHttpCheck(
makeTarget({
url: `${baseUrl}/ok`,
expect: { status: [200], body: [{ contains: "not-in-body" }] },
}),
);
expect(result.success).toBe(false);
expect(result.failure!.phase).toBe("body");
});
test("无 expect 时默认检查 status 200", async () => {
const result = await runHttpCheck(makeTarget({ url: `${baseUrl}/ok`, expect: undefined }));
expect(result.success).toBe(true);
});
test("POST 请求携带 body", async () => {
const result = await runHttpCheck(
makeTarget({
url: `${baseUrl}/echo`,
method: "POST",
body: "test-body",
headers: { "content-type": "text/plain" },
expect: { status: [200], body: [{ json: { path: "$.body", equals: "present" } }] },
}),
);
expect(result.success).toBe(true);
});
test("仅 contains 规则时不解析 JSON", async () => {
const result = await runHttpCheck(
makeTarget({
url: `${baseUrl}/ok`,
expect: { body: [{ contains: "hello world" }] },
}),
);
expect(result.success).toBe(true);
});
});