feat: WS checker,支持可达性检测和单次请求-响应交互验证
This commit is contained in:
215
tests/server/checker/runner/ws/validate.test.ts
Normal file
215
tests/server/checker/runner/ws/validate.test.ts
Normal file
@@ -0,0 +1,215 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
|
||||
import type { CheckerValidationInput } from "../../../../../src/server/checker/runner/types";
|
||||
|
||||
import { validateWsConfig } from "../../../../../src/server/checker/runner/ws/validate";
|
||||
|
||||
function makeInput(targets: unknown[]): CheckerValidationInput {
|
||||
return {
|
||||
targets: targets as CheckerValidationInput["targets"],
|
||||
};
|
||||
}
|
||||
|
||||
describe("validateWsConfig", () => {
|
||||
test("合法 ws target 无错误", () => {
|
||||
const issues = validateWsConfig(makeInput([{ id: "t1", type: "ws", ws: { url: "ws://example.com" } }]));
|
||||
expect(issues).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("合法 wss target 无错误", () => {
|
||||
const issues = validateWsConfig(makeInput([{ id: "t1", type: "ws", ws: { url: "wss://example.com/ws" } }]));
|
||||
expect(issues).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("缺少 ws 分组", () => {
|
||||
const issues = validateWsConfig(makeInput([{ id: "t1", type: "ws" }]));
|
||||
expect(issues.length).toBeGreaterThan(0);
|
||||
expect(issues.some((i) => i.message.includes("ws"))).toBe(true);
|
||||
});
|
||||
|
||||
test("缺少 url", () => {
|
||||
const issues = validateWsConfig(makeInput([{ id: "t1", type: "ws", ws: {} }]));
|
||||
expect(issues.some((i) => i.path.includes("url"))).toBe(true);
|
||||
});
|
||||
|
||||
test("url 非 ws/wss 协议报错", () => {
|
||||
const issues = validateWsConfig(makeInput([{ id: "t1", type: "ws", ws: { url: "http://example.com" } }]));
|
||||
expect(issues.some((i) => i.code === "invalid-url")).toBe(true);
|
||||
});
|
||||
|
||||
test("url 格式非法报错", () => {
|
||||
const issues = validateWsConfig(makeInput([{ id: "t1", type: "ws", ws: { url: "not-a-url" } }]));
|
||||
expect(issues.some((i) => i.code === "invalid-url")).toBe(true);
|
||||
});
|
||||
|
||||
test("subprotocols 非数组报错", () => {
|
||||
const issues = validateWsConfig(
|
||||
makeInput([{ id: "t1", type: "ws", ws: { subprotocols: "json", url: "ws://example.com" } }]),
|
||||
);
|
||||
expect(issues.some((i) => i.path.includes("subprotocols"))).toBe(true);
|
||||
});
|
||||
|
||||
test("subprotocols 元素为空字符串报错", () => {
|
||||
const issues = validateWsConfig(
|
||||
makeInput([{ id: "t1", type: "ws", ws: { subprotocols: [""], url: "ws://example.com" } }]),
|
||||
);
|
||||
expect(issues.some((i) => i.path.includes("subprotocols"))).toBe(true);
|
||||
});
|
||||
|
||||
test("subprotocols 合法无错误", () => {
|
||||
const issues = validateWsConfig(
|
||||
makeInput([{ id: "t1", type: "ws", ws: { subprotocols: ["json", "binary"], url: "ws://example.com" } }]),
|
||||
);
|
||||
expect(issues).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("ignoreSSL 非布尔值报错", () => {
|
||||
const issues = validateWsConfig(
|
||||
makeInput([{ id: "t1", type: "ws", ws: { ignoreSSL: "yes", url: "ws://example.com" } }]),
|
||||
);
|
||||
expect(issues.some((i) => i.path.includes("ignoreSSL"))).toBe(true);
|
||||
});
|
||||
|
||||
test("receiveTimeout 非数字报错", () => {
|
||||
const issues = validateWsConfig(
|
||||
makeInput([{ id: "t1", type: "ws", ws: { receiveTimeout: "slow", url: "ws://example.com" } }]),
|
||||
);
|
||||
expect(issues.some((i) => i.path.includes("receiveTimeout"))).toBe(true);
|
||||
});
|
||||
|
||||
test("receiveTimeout 为负数报错", () => {
|
||||
const issues = validateWsConfig(
|
||||
makeInput([{ id: "t1", type: "ws", ws: { receiveTimeout: -1, url: "ws://example.com" } }]),
|
||||
);
|
||||
expect(issues.some((i) => i.path.includes("receiveTimeout"))).toBe(true);
|
||||
});
|
||||
|
||||
test("maxMessageBytes 非法值报错", () => {
|
||||
const issues = validateWsConfig(
|
||||
makeInput([{ id: "t1", type: "ws", ws: { maxMessageBytes: -1, url: "ws://example.com" } }]),
|
||||
);
|
||||
expect(issues.some((i) => i.path.includes("maxMessageBytes"))).toBe(true);
|
||||
});
|
||||
|
||||
test("ws 分组未知字段", () => {
|
||||
const issues = validateWsConfig(makeInput([{ id: "t1", type: "ws", ws: { tls: true, url: "ws://example.com" } }]));
|
||||
expect(issues.some((i) => i.message.includes("未知字段"))).toBe(true);
|
||||
});
|
||||
|
||||
test("expect.message 未配置 ws.send 报错", () => {
|
||||
const issues = validateWsConfig(
|
||||
makeInput([
|
||||
{
|
||||
expect: { message: [{ contains: "pong" }] },
|
||||
id: "t1",
|
||||
type: "ws",
|
||||
ws: { url: "ws://example.com" },
|
||||
},
|
||||
]),
|
||||
);
|
||||
expect(issues.some((i) => i.message.includes("send"))).toBe(true);
|
||||
});
|
||||
|
||||
test("expect.message 配置 ws.send 无错误", () => {
|
||||
const issues = validateWsConfig(
|
||||
makeInput([
|
||||
{
|
||||
expect: { message: [{ contains: "pong" }] },
|
||||
id: "t1",
|
||||
type: "ws",
|
||||
ws: { send: "ping", url: "ws://example.com" },
|
||||
},
|
||||
]),
|
||||
);
|
||||
expect(issues).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("expect.connected 非布尔值报错", () => {
|
||||
const issues = validateWsConfig(
|
||||
makeInput([
|
||||
{
|
||||
expect: { connected: "yes" },
|
||||
id: "t1",
|
||||
type: "ws",
|
||||
ws: { url: "ws://example.com" },
|
||||
},
|
||||
]),
|
||||
);
|
||||
expect(issues.some((i) => i.path.includes("connected"))).toBe(true);
|
||||
});
|
||||
|
||||
test("expect.connected=false 时 expect.message 报错", () => {
|
||||
const issues = validateWsConfig(
|
||||
makeInput([
|
||||
{
|
||||
expect: { connected: false, message: [{ contains: "pong" }] },
|
||||
id: "t1",
|
||||
type: "ws",
|
||||
ws: { send: "ping", url: "ws://example.com" },
|
||||
},
|
||||
]),
|
||||
);
|
||||
expect(issues.some((i) => i.message.includes("connected"))).toBe(true);
|
||||
});
|
||||
|
||||
test("expect.connected=false 时 expect.handshakeHeaders 报错", () => {
|
||||
const issues = validateWsConfig(
|
||||
makeInput([
|
||||
{
|
||||
expect: { connected: false, handshakeHeaders: { "Sec-WebSocket-Protocol": { equals: "json" } } },
|
||||
id: "t1",
|
||||
type: "ws",
|
||||
ws: { url: "ws://example.com" },
|
||||
},
|
||||
]),
|
||||
);
|
||||
expect(issues.some((i) => i.message.includes("connected"))).toBe(true);
|
||||
});
|
||||
|
||||
test("expect.connected=false 时 expect.connectTimeMs 报错", () => {
|
||||
const issues = validateWsConfig(
|
||||
makeInput([
|
||||
{
|
||||
expect: { connected: false, connectTimeMs: { lte: 1000 } },
|
||||
id: "t1",
|
||||
type: "ws",
|
||||
ws: { url: "ws://example.com" },
|
||||
},
|
||||
]),
|
||||
);
|
||||
expect(issues.some((i) => i.message.includes("connected"))).toBe(true);
|
||||
});
|
||||
|
||||
test("expect.connected=false 单独配置合法", () => {
|
||||
const issues = validateWsConfig(
|
||||
makeInput([
|
||||
{
|
||||
expect: { connected: false },
|
||||
id: "t1",
|
||||
type: "ws",
|
||||
ws: { url: "ws://example.com" },
|
||||
},
|
||||
]),
|
||||
);
|
||||
expect(issues).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("expect 未知字段报错", () => {
|
||||
const issues = validateWsConfig(
|
||||
makeInput([
|
||||
{
|
||||
expect: { status: [200] },
|
||||
id: "t1",
|
||||
type: "ws",
|
||||
ws: { url: "ws://example.com" },
|
||||
},
|
||||
]),
|
||||
);
|
||||
expect(issues.some((i) => i.message.includes("未知字段"))).toBe(true);
|
||||
});
|
||||
|
||||
test("非 ws 类型 target 跳过", () => {
|
||||
const issues = validateWsConfig(makeInput([{ http: { url: "http://example.com" }, id: "t1", type: "http" }]));
|
||||
expect(issues).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user