feat: 增强 expect 规则系统,支持多种 body 校验方法和操作符
- 新增 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
This commit is contained in:
@@ -1,33 +1,82 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { checkExpect } from "../../../src/server/checker/fetcher";
|
||||
|
||||
const emptyHeaders: Record<string, string> = {};
|
||||
|
||||
describe("checkExpect", () => {
|
||||
test("无 expect 配置时 matched 为 true", () => {
|
||||
expect(checkExpect(200, "ok", 100, undefined)).toBe(true);
|
||||
expect(checkExpect(200, "ok", 100, emptyHeaders, undefined)).toBe(true);
|
||||
});
|
||||
|
||||
test("status 匹配", () => {
|
||||
expect(checkExpect(200, "", 100, { status: [200, 201] })).toBe(true);
|
||||
expect(checkExpect(201, "", 100, { status: [200, 201] })).toBe(true);
|
||||
expect(checkExpect(404, "", 100, { status: [200, 201] })).toBe(false);
|
||||
expect(checkExpect(200, "", 100, emptyHeaders, { status: [200, 201] })).toBe(true);
|
||||
expect(checkExpect(201, "", 100, emptyHeaders, { status: [200, 201] })).toBe(true);
|
||||
expect(checkExpect(404, "", 100, emptyHeaders, { status: [200, 201] })).toBe(false);
|
||||
});
|
||||
|
||||
test("bodyContains 匹配", () => {
|
||||
expect(checkExpect(200, "hello world", 100, { bodyContains: "hello" })).toBe(true);
|
||||
expect(checkExpect(200, "hello world", 100, { bodyContains: "missing" })).toBe(false);
|
||||
test("headers 匹配", () => {
|
||||
const headers = { "content-type": "application/json", "x-custom": "test" };
|
||||
expect(checkExpect(200, "", 100, headers, { headers: { "Content-Type": "application/json" } })).toBe(true);
|
||||
expect(checkExpect(200, "", 100, headers, { headers: { "Content-Type": "text/html" } })).toBe(false);
|
||||
expect(checkExpect(200, "", 100, headers, { headers: { "X-Missing": "test" } })).toBe(false);
|
||||
});
|
||||
|
||||
test("body.contains 匹配", () => {
|
||||
expect(checkExpect(200, "hello world", 100, emptyHeaders, { body: { contains: "hello" } })).toBe(true);
|
||||
expect(checkExpect(200, "hello world", 100, emptyHeaders, { body: { contains: "missing" } })).toBe(false);
|
||||
});
|
||||
|
||||
test("body.regex 匹配", () => {
|
||||
expect(checkExpect(200, "status: ok", 100, emptyHeaders, { body: { regex: "status.*ok" } })).toBe(true);
|
||||
expect(checkExpect(200, "status: error", 100, emptyHeaders, { body: { regex: "status.*ok" } })).toBe(false);
|
||||
});
|
||||
|
||||
test("body.json 匹配", () => {
|
||||
expect(
|
||||
checkExpect(200, JSON.stringify({ status: "ok" }), 100, emptyHeaders, { body: { json: { "$.status": "ok" } } }),
|
||||
).toBe(true);
|
||||
expect(
|
||||
checkExpect(200, JSON.stringify({ status: "error" }), 100, emptyHeaders, {
|
||||
body: { json: { "$.status": "ok" } },
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test("body.json 解析失败", () => {
|
||||
expect(checkExpect(200, "not json", 100, emptyHeaders, { body: { json: { "$.status": "ok" } } })).toBe(false);
|
||||
});
|
||||
|
||||
test("body 多种方法 AND 组合", () => {
|
||||
expect(
|
||||
checkExpect(200, "healthy", 100, emptyHeaders, {
|
||||
body: {
|
||||
contains: "healthy",
|
||||
regex: "healthy",
|
||||
},
|
||||
}),
|
||||
).toBe(true);
|
||||
|
||||
expect(
|
||||
checkExpect(200, "healthy", 100, emptyHeaders, {
|
||||
body: {
|
||||
contains: "healthy",
|
||||
regex: "unhealthy",
|
||||
},
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test("maxLatencyMs 匹配", () => {
|
||||
expect(checkExpect(200, "", 100, { maxLatencyMs: 200 })).toBe(true);
|
||||
expect(checkExpect(200, "", 300, { maxLatencyMs: 200 })).toBe(false);
|
||||
expect(checkExpect(200, "", 200, { maxLatencyMs: 200 })).toBe(true);
|
||||
expect(checkExpect(200, "", 100, emptyHeaders, { maxLatencyMs: 200 })).toBe(true);
|
||||
expect(checkExpect(200, "", 300, emptyHeaders, { maxLatencyMs: 200 })).toBe(false);
|
||||
expect(checkExpect(200, "", 200, emptyHeaders, { maxLatencyMs: 200 })).toBe(true);
|
||||
});
|
||||
|
||||
test("多条 expect 全部通过", () => {
|
||||
expect(
|
||||
checkExpect(200, "healthy", 100, {
|
||||
checkExpect(200, "healthy", 100, emptyHeaders, {
|
||||
status: [200],
|
||||
bodyContains: "healthy",
|
||||
body: { contains: "healthy" },
|
||||
maxLatencyMs: 200,
|
||||
}),
|
||||
).toBe(true);
|
||||
@@ -35,9 +84,33 @@ describe("checkExpect", () => {
|
||||
|
||||
test("多条 expect 部分失败", () => {
|
||||
expect(
|
||||
checkExpect(200, "healthy", 500, {
|
||||
checkExpect(200, "healthy", 500, emptyHeaders, {
|
||||
status: [200],
|
||||
bodyContains: "healthy",
|
||||
body: { contains: "healthy" },
|
||||
maxLatencyMs: 200,
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test("status + headers + body + maxLatencyMs 全组合", () => {
|
||||
const headers = { "content-type": "application/json" };
|
||||
expect(
|
||||
checkExpect(200, JSON.stringify({ status: "ok" }), 100, headers, {
|
||||
status: [200],
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: { contains: "ok", json: { "$.status": "ok" } },
|
||||
maxLatencyMs: 200,
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test("全组合中 headers 失败", () => {
|
||||
const headers = { "content-type": "text/html" };
|
||||
expect(
|
||||
checkExpect(200, JSON.stringify({ status: "ok" }), 100, headers, {
|
||||
status: [200],
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: { contains: "ok", json: { "$.status": "ok" } },
|
||||
maxLatencyMs: 200,
|
||||
}),
|
||||
).toBe(false);
|
||||
|
||||
Reference in New Issue
Block a user