1
0

feat: WS checker,支持可达性检测和单次请求-响应交互验证

This commit is contained in:
2026-05-25 14:13:43 +08:00
parent 714b635aef
commit c1db793073
20 changed files with 2339 additions and 4 deletions

View File

@@ -0,0 +1,95 @@
import { describe, expect, test } from "bun:test";
import type { ResolveContext } from "../../../../../src/server/checker/runner/types";
import type { ResolvedWsTarget } from "../../../../../src/server/checker/runner/ws/types";
import type { RawTargetConfig } from "../../../../../src/server/checker/types";
import { checkerRegistry } from "../../../../../src/server/checker/runner";
function asWs(resolved: ReturnType<ReturnType<typeof checkerRegistry.get>["resolve"]>): ResolvedWsTarget {
return resolved as ResolvedWsTarget;
}
function makeRawTarget(overrides?: Partial<RawTargetConfig>): RawTargetConfig {
return {
id: "test-ws",
type: "ws",
ws: { url: "ws://example.com/ws" },
...overrides,
};
}
function makeResolveContext(overrides?: Partial<ResolveContext>): ResolveContext {
return {
configDir: "/tmp",
defaultIntervalMs: 30000,
defaultTimeoutMs: 10000,
...overrides,
};
}
describe("WsChecker resolve", () => {
const checker = checkerRegistry.tryGet("ws")!;
test("最简 target 填充默认值", () => {
const resolved = asWs(checker.resolve(makeRawTarget(), makeResolveContext()));
expect(resolved.type).toBe("ws");
expect(resolved.ws.url).toBe("ws://example.com/ws");
expect(resolved.ws.headers).toEqual({});
expect(resolved.ws.ignoreSSL).toBe(false);
expect(resolved.ws.maxMessageBytes).toBe(4096);
expect(resolved.ws.receiveTimeout).toBe(5000);
expect(resolved.ws.send).toBeUndefined();
expect(resolved.ws.subprotocols).toEqual([]);
expect(resolved.expect).toEqual({ connected: true });
expect(resolved.group).toBe("default");
expect(resolved.intervalMs).toBe(30000);
expect(resolved.timeoutMs).toBe(10000);
});
test("完整配置正确 resolve", () => {
const raw = makeRawTarget({
expect: { connected: true, durationMs: { lte: 5000 } },
ws: {
headers: { Authorization: "Bearer token" },
ignoreSSL: true,
maxMessageBytes: "8KB",
receiveTimeout: 3000,
send: "ping",
subprotocols: ["json"],
url: "wss://api.example.com/ws",
},
});
const resolved = asWs(checker.resolve(raw, makeResolveContext()));
expect(resolved.ws.url).toBe("wss://api.example.com/ws");
expect(resolved.ws.headers).toEqual({ Authorization: "Bearer token" });
expect(resolved.ws.ignoreSSL).toBe(true);
expect(resolved.ws.maxMessageBytes).toBe(8192);
expect(resolved.ws.receiveTimeout).toBe(3000);
expect(resolved.ws.send).toBe("ping");
expect(resolved.ws.subprotocols).toEqual(["json"]);
expect(resolved.expect?.connected).toBe(true);
});
test("expect 默认 connected=true", () => {
const raw = makeRawTarget({ expect: { durationMs: { lte: 1000 } } });
const resolved = asWs(checker.resolve(raw, makeResolveContext()));
expect(resolved.expect?.connected).toBe(true);
});
test("expect.connected=false 保留", () => {
const raw = makeRawTarget({ expect: { connected: false } });
const resolved = asWs(checker.resolve(raw, makeResolveContext()));
expect(resolved.expect?.connected).toBe(false);
});
test("serialize 返回正确格式", () => {
const resolved = asWs(checker.resolve(makeRawTarget(), makeResolveContext()));
const serialized = checker.serialize(resolved);
expect(serialized.target).toBe("ws://example.com/ws");
const config = JSON.parse(serialized.config) as Record<string, unknown>;
expect(config["url"]).toBe("ws://example.com/ws");
expect(config["ignoreSSL"]).toBe(false);
expect(config["receiveTimeout"]).toBe(5000);
});
});