refactor: 引入 Checker 统一接口与 Runner 抽象机制
定义 Checker 接口(resolve/execute/serialize)和 CheckerRegistry 注册中心,消除 engine/config-loader/store 中硬编码类型分支。 按 checker 类型分子包(runner/http/、runner/command/),提取 共享 expect 到 runner/shared/。超时控制通过引擎注入 AbortSignal。 CheckFailure.phase 从联合类型改为 string。配置校验下沉到各 Checker.resolve() 内部。 新增 checker-runner-abstraction spec,更新 DEVELOPMENT.md。
This commit is contained in:
79
tests/server/checker/runner/shared/failure.test.ts
Normal file
79
tests/server/checker/runner/shared/failure.test.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { truncateActual, mismatchFailure, errorFailure } from "../../../../../src/server/checker/runner/shared/failure";
|
||||
|
||||
describe("truncateActual", () => {
|
||||
test("短字符串不截断", () => {
|
||||
expect(truncateActual("hello")).toBe("hello");
|
||||
});
|
||||
|
||||
test("恰好等于限制长度不截断", () => {
|
||||
const str = "a".repeat(200);
|
||||
expect(truncateActual(str)).toBe(str);
|
||||
});
|
||||
|
||||
test("超过限制长度截断并加省略号", () => {
|
||||
const str = "a".repeat(300);
|
||||
const result = truncateActual(str) as string;
|
||||
expect(result.length).toBe(203);
|
||||
expect(result.endsWith("...")).toBe(true);
|
||||
expect(result.startsWith("a".repeat(200))).toBe(true);
|
||||
});
|
||||
|
||||
test("自定义最大长度", () => {
|
||||
const str = "abcdefghij";
|
||||
const result = truncateActual(str, 5) as string;
|
||||
expect(result).toBe("abcde...");
|
||||
});
|
||||
|
||||
test("null 不截断", () => {
|
||||
expect(truncateActual(null)).toBe(null);
|
||||
});
|
||||
|
||||
test("undefined 不截断", () => {
|
||||
expect(truncateActual(undefined)).toBe(undefined);
|
||||
});
|
||||
|
||||
test("数字转换为字符串后判断", () => {
|
||||
expect(truncateActual(42)).toBe(42);
|
||||
expect(truncateActual(123456789, 3) as string).toBe("123...");
|
||||
});
|
||||
});
|
||||
|
||||
describe("mismatchFailure", () => {
|
||||
test("返回正确的 mismatch 结构", () => {
|
||||
const f = mismatchFailure("status", "status", [200], 500, "status mismatch");
|
||||
expect(f).toEqual({
|
||||
kind: "mismatch",
|
||||
phase: "status",
|
||||
path: "status",
|
||||
expected: [200],
|
||||
actual: 500,
|
||||
message: "status mismatch",
|
||||
});
|
||||
});
|
||||
|
||||
test("自动截断过长的 actual", () => {
|
||||
const longStr = "x".repeat(300);
|
||||
const f = mismatchFailure("body", "body[0]", "short", longStr, "too long");
|
||||
expect((f.actual as string).endsWith("...")).toBe(true);
|
||||
expect((f.actual as string).length).toBe(203);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errorFailure", () => {
|
||||
test("返回正确的 error 结构", () => {
|
||||
const f = errorFailure("body", "body[0].json($.x)", "body is not valid JSON");
|
||||
expect(f).toEqual({
|
||||
kind: "error",
|
||||
phase: "body",
|
||||
path: "body[0].json($.x)",
|
||||
message: "body is not valid JSON",
|
||||
});
|
||||
});
|
||||
|
||||
test("不含 expected 和 actual 字段", () => {
|
||||
const f = errorFailure("headers", "headers.x", "header missing");
|
||||
expect(f).not.toHaveProperty("expected");
|
||||
expect(f).not.toHaveProperty("actual");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user