1
0
Files
DiAL/tests/server/checker/runner/db/expect.test.ts
lanyuanxiaoyao 146cef982e feat: 新增 DB checker — 支持 PostgreSQL/MySQL/SQLite 连接测试与 SQL 查询断言
- 实现 db 类型 checker,使用 Bun 内置 SQL 类
- 支持 db.url 连接字符串和可选 db.query 查询语句
- expect 支持 maxDurationMs、rowCount、rows 逐列校验
- 凭据屏蔽序列化输出
- SQLite 内存数据库测试覆盖
2026-05-16 09:00:15 +08:00

135 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, test } from "bun:test";
import { checkRowCount, checkRows } from "../../../../../src/server/checker/runner/db/expect";
describe("checkRowCount", () => {
test("空数组通过 rowCount gte 0", () => {
const result = checkRowCount([], { gte: 0 });
expect(result.matched).toBe(true);
expect(result.failure).toBeNull();
});
test("非数组视为 0 行", () => {
const result = checkRowCount(null, { gte: 0 });
expect(result.matched).toBe(true);
});
test("rowCount gte 通过", () => {
const result = checkRowCount([1, 2, 3], { gte: 3 });
expect(result.matched).toBe(true);
});
test("rowCount gte 失败", () => {
const result = checkRowCount([1, 2], { gte: 3 });
expect(result.matched).toBe(false);
expect(result.failure!.phase).toBe("rowCount");
expect(result.failure!.path).toBe("rowCount");
});
test("rowCount equals 通过", () => {
const result = checkRowCount([1, 2, 3], { equals: 3 });
expect(result.matched).toBe(true);
});
test("rowCount equals 失败", () => {
const result = checkRowCount([1, 2, 3], { equals: 5 });
expect(result.matched).toBe(false);
});
});
describe("checkRows", () => {
test("非数组返回失败", () => {
const result = checkRows(null, [{ col: 1 }]);
expect(result.matched).toBe(false);
expect(result.failure!.phase).toBe("row");
expect(result.failure!.path).toBe("rows");
});
test("空规则通过", () => {
const result = checkRows([], []);
expect(result.matched).toBe(true);
});
test("单行单列匹配(字面量)", () => {
const result = checkRows([{ col: "value" }], [{ col: "value" }]);
expect(result.matched).toBe(true);
});
test("单行单列匹配operator", () => {
const result = checkRows([{ col: 100 }], [{ col: { gte: 50 } }]);
expect(result.matched).toBe(true);
});
test("单行单列不匹配", () => {
const result = checkRows([{ col: 10 }], [{ col: { gte: 50 } }]);
expect(result.matched).toBe(false);
expect(result.failure!.phase).toBe("row");
expect(result.failure!.path).toBe("rows[0].col");
});
test("多行多列全部匹配", () => {
const result = checkRows(
[
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
],
[{ id: { gte: 1 } }, { name: "Bob" }],
);
expect(result.matched).toBe(true);
});
test("多行中有一行不匹配", () => {
const result = checkRows([{ col: 1 }, { col: 2 }], [{ col: { gte: 2 } }, { col: { gte: 3 } }]);
expect(result.matched).toBe(false);
// 第一行 { col: 1 } 不满足 { gte: 2 },所以失败在第一行
expect(result.failure!.path).toBe("rows[0].col");
});
test("结果行数不足", () => {
const result = checkRows([{ col: 1 }], [{ col: 1 }, { col: 2 }]);
expect(result.matched).toBe(false);
expect(result.failure!.message).toContain("行数不足");
});
test("只检查声明的列", () => {
const result = checkRows([{ col: 1, other: "ignored" }], [{ col: { gte: 0 } }]);
expect(result.matched).toBe(true);
});
test("行不是对象返回失败", () => {
const result = checkRows(["not-an-object"] as unknown[], [{ col: 1 }]);
expect(result.matched).toBe(false);
expect(result.failure!.path).toBe("rows[0]");
});
test("列不存在视为 undefined", () => {
const result = checkRows([{}], [{ col: { exists: false } }]);
expect(result.matched).toBe(true);
});
test("列存在且值为 null", () => {
const result = checkRows([{ col: null }], [{ col: { empty: true } }]);
expect(result.matched).toBe(true);
});
test("contains 匹配字符串", () => {
const result = checkRows([{ text: "hello world" }], [{ text: { contains: "hello" } }]);
expect(result.matched).toBe(true);
});
test("match 正则匹配", () => {
const result = checkRows([{ code: "ABC-123" }], [{ code: { match: "^ABC-" } }]);
expect(result.matched).toBe(true);
});
test("多个断言同时满足", () => {
const result = checkRows([{ val: 50 }], [{ val: { gte: 10, lte: 100 } }]);
expect(result.matched).toBe(true);
});
test("多个断言中有一个不满足", () => {
const result = checkRows([{ val: 50 }], [{ val: { gte: 10, lte: 30 } }]);
expect(result.matched).toBe(false);
});
});