- 新增 body 分组校验:contains、regex、json(JSONPath)、css(CSS选择器)、xpath - 新增操作符系统:equals、contains、match、empty、exists、gte、lte、gt、lt - 新增 headers 响应头校验 - 引入 cheerio、xpath、@xmldom/xmldom 依赖 - BREAKING: expect.bodyContains 迁移至 expect.body.contains
97 lines
3.1 KiB
TypeScript
97 lines
3.1 KiB
TypeScript
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
import { ProbeStore } from "../../../src/server/checker/store";
|
|
import { ProbeEngine } from "../../../src/server/checker/engine";
|
|
import type { ResolvedTarget } from "../../../src/server/checker/types";
|
|
import { mkdir, rm } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import { tmpdir } from "node:os";
|
|
|
|
describe("ProbeEngine", () => {
|
|
let tempDir: string;
|
|
let store: ProbeStore;
|
|
|
|
const target: ResolvedTarget = {
|
|
name: "httpbin",
|
|
url: "https://httpbin.org/get",
|
|
method: "GET",
|
|
headers: {},
|
|
intervalMs: 60000,
|
|
timeoutMs: 10000,
|
|
};
|
|
|
|
beforeAll(async () => {
|
|
tempDir = join(tmpdir(), `gc-engine-test-${Date.now()}`);
|
|
await mkdir(tempDir, { recursive: true });
|
|
store = new ProbeStore(join(tempDir, "test.db"));
|
|
store.syncTargets([target]);
|
|
});
|
|
|
|
afterAll(async () => {
|
|
store.close();
|
|
await rm(tempDir, { recursive: true, force: true });
|
|
});
|
|
|
|
test("groupByInterval 分组逻辑", () => {
|
|
const targets: ResolvedTarget[] = [
|
|
{ name: "a", url: "http://a.com", method: "GET", headers: {}, intervalMs: 30000, timeoutMs: 10000 },
|
|
{ name: "b", url: "http://b.com", method: "GET", headers: {}, intervalMs: 30000, timeoutMs: 10000 },
|
|
{ name: "c", url: "http://c.com", method: "GET", headers: {}, intervalMs: 60000, timeoutMs: 10000 },
|
|
];
|
|
|
|
const engine = new ProbeEngine(store, targets);
|
|
engine.start();
|
|
engine.stop();
|
|
|
|
// 只要能启动和停止不出错就行
|
|
expect(true).toBe(true);
|
|
});
|
|
|
|
test("engine start/stop 不抛错", () => {
|
|
const engine = new ProbeEngine(store, [target]);
|
|
engine.start();
|
|
engine.stop();
|
|
expect(true).toBe(true);
|
|
});
|
|
|
|
test("单次拨测写入数据库", async () => {
|
|
const engine = new ProbeEngine(store, [target]);
|
|
// 手动调用 probeGroup 不启动 timer
|
|
const probeGroup = (engine as unknown as { probeGroup: (t: ResolvedTarget[]) => Promise<void> }).probeGroup.bind(
|
|
engine,
|
|
);
|
|
await probeGroup([target]);
|
|
|
|
const dbTargets = store.getTargets();
|
|
const latest = store.getLatestCheck(dbTargets[0]!.id);
|
|
expect(latest).not.toBeNull();
|
|
expect(latest!.success === 1 || latest!.success === 0).toBe(true);
|
|
});
|
|
|
|
test("单目标失败隔离", async () => {
|
|
const badTarget: ResolvedTarget = {
|
|
name: "bad-target",
|
|
url: "http://127.0.0.1:1/impossible",
|
|
method: "GET",
|
|
headers: {},
|
|
intervalMs: 60000,
|
|
timeoutMs: 2000,
|
|
};
|
|
|
|
store.syncTargets([target, badTarget]);
|
|
|
|
const engine = new ProbeEngine(store, [target, badTarget]);
|
|
const probeGroup = (engine as unknown as { probeGroup: (t: ResolvedTarget[]) => Promise<void> }).probeGroup.bind(
|
|
engine,
|
|
);
|
|
await probeGroup([target, badTarget]);
|
|
|
|
const dbTargets = store.getTargets();
|
|
const goodResult = store.getLatestCheck(dbTargets.find((t) => t.name === "httpbin")!.id);
|
|
const badResult = store.getLatestCheck(dbTargets.find((t) => t.name === "bad-target")!.id);
|
|
|
|
expect(goodResult).not.toBeNull();
|
|
expect(badResult).not.toBeNull();
|
|
expect(badResult!.success).toBe(0);
|
|
});
|
|
});
|