import { afterAll, beforeAll, describe, expect, test } from "bun:test"; import type { CheckerContext } from "../../../../../src/server/checker/runner/types"; import type { ResolvedWsTarget } from "../../../../../src/server/checker/runner/ws/types"; import { WsChecker } from "../../../../../src/server/checker/runner/ws/execute"; function createEchoServer() { return Bun.serve({ fetch(req, server) { const success = server.upgrade(req); if (!success) return new Response("Upgrade failed", { status: 500 }); return undefined; }, port: 0, websocket: { close() { /* ws close */ }, message(ws, message) { ws.send(message); }, open() { /* ws open */ }, }, }); } function createNoReplyServer() { return Bun.serve({ fetch(req, server) { const success = server.upgrade(req); if (!success) return new Response("Upgrade failed", { status: 500 }); return undefined; }, port: 0, websocket: { close() { /* ws close */ }, message() { /* no reply */ }, open() { /* ws open */ }, }, }); } function createRejectServer() { return Bun.serve({ fetch() { return new Response("Forbidden", { status: 403 }); }, port: 0, }); } function makeContext(overrides?: Partial): CheckerContext { return { signal: AbortSignal.timeout(15000), ...overrides, }; } function makeWsTarget(overrides?: Partial): ResolvedWsTarget { return { description: null, expect: { connected: true }, group: "default", id: "test-ws", intervalMs: 30000, name: null, timeoutMs: 10000, type: "ws", ws: { headers: {}, ignoreSSL: false, maxMessageBytes: 4096, receiveTimeout: 5000, subprotocols: [], url: "ws://127.0.0.1:19999/ws", }, ...overrides, }; } let echoServer: ReturnType; let noReplyServer: ReturnType; let rejectServer: ReturnType; beforeAll(() => { echoServer = createEchoServer(); noReplyServer = createNoReplyServer(); rejectServer = createRejectServer(); }); afterAll(async () => { await echoServer.stop(); await noReplyServer.stop(); await rejectServer.stop(); }); describe("WsChecker execute", () => { const checker = new WsChecker(); test("可达性检查 - 连接成功", async () => { const target = makeWsTarget({ ws: { ...makeWsTarget().ws, url: `ws://127.0.0.1:${echoServer.port}` } }); const result = await checker.execute(target, makeContext()); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); expect(result.observation!["connected"]).toBe(true); }); test("可达性检查 - 连接失败", async () => { const target = makeWsTarget({ ws: { ...makeWsTarget().ws, url: "ws://127.0.0.1:1" } }); const result = await checker.execute(target, makeContext()); expect(result.matched).toBe(false); expect(result.failure).not.toBeNull(); expect(result.observation!["connected"]).toBe(false); }); test("可达性检查 - 连接失败但 expect.connected=false", async () => { const target = makeWsTarget({ expect: { connected: false }, ws: { ...makeWsTarget().ws, url: "ws://127.0.0.1:1" }, }); const result = await checker.execute(target, makeContext()); expect(result.matched).toBe(true); expect(result.failure).toBeNull(); }); test("交互模式 - 发送消息并收到响应", async () => { const target = makeWsTarget({ expect: { connected: true, message: [{ kind: "value" as const, matcher: { equals: "ping" } }], }, ws: { ...makeWsTarget().ws, send: "ping", url: `ws://127.0.0.1:${echoServer.port}`, }, }); const result = await checker.execute(target, makeContext()); expect(result.matched).toBe(true); expect(result.observation!["message"]).toBe("ping"); expect(result.observation!["messageSize"]).toBe(4); }); test("交互模式 - 消息不匹配", async () => { const target = makeWsTarget({ expect: { connected: true, message: [{ kind: "value" as const, matcher: { equals: "pong" } }], }, ws: { ...makeWsTarget().ws, send: "ping", url: `ws://127.0.0.1:${echoServer.port}`, }, }); const result = await checker.execute(target, makeContext()); expect(result.matched).toBe(false); expect(result.failure).not.toBeNull(); }); test("交互模式 - receiveTimeout 超时", async () => { const target = makeWsTarget({ ws: { ...makeWsTarget().ws, receiveTimeout: 500, send: "ping", url: `ws://127.0.0.1:${noReplyServer.port}`, }, }); const result = await checker.execute(target, makeContext()); expect(result.matched).toBe(false); expect(result.failure?.phase).toBe("message"); }); test("HTTP 403 握手失败", async () => { const target = makeWsTarget({ ws: { ...makeWsTarget().ws, url: `ws://127.0.0.1:${rejectServer.port}` } }); const result = await checker.execute(target, makeContext()); expect(result.matched).toBe(false); expect(result.observation!["connected"]).toBe(false); }); test("buildDetail 连接成功", () => { const detail = checker.buildDetail({ connected: true, connectTimeMs: 50, message: "hello" }); expect(detail).toContain("connected"); expect(detail).toContain("hello"); }); test("buildDetail 连接失败", () => { const detail = checker.buildDetail({ connected: false, error: "connection refused" }); expect(detail).toContain("connection failed"); }); });