- 新增顶层 variables 段支持 string/number/boolean 字面量
- target 字符串字段支持 、、{...} 转义语法
- 变量解析优先级: variables -> process.env -> 默认值 -> 报错
- 完整引用保留原始类型,部分引用拼接为字符串
- 变量替换在 YAML 解析后、AJV 校验前执行
- 替换仅作用于 targets,跳过 id/type 字段
- target 新增必填 id 字段作为唯一标识,name 改为可选展示名称
- 数据库存储/API/前端全面迁移到 id 标识
- 统一 checker 运行时类型检查为 es-toolkit predicates
- 同步 delta specs 到主 specs,归档 config-variables 变更
126 lines
3.9 KiB
TypeScript
126 lines
3.9 KiB
TypeScript
import type { PrimaryTableCellParams, PrimaryTableCol } from "tdesign-react";
|
|
|
|
import { describe, expect, test } from "bun:test";
|
|
|
|
import type { TargetStatus } from "../../../src/shared/api";
|
|
|
|
import { createTargetTableColumns } from "../../../src/web/constants/target-table-columns";
|
|
|
|
interface TableFilter {
|
|
list?: Array<{ label: string; value: string }>;
|
|
type?: string;
|
|
}
|
|
|
|
function getColumn(columns: Array<PrimaryTableCol<TargetStatus>>, colKey: string): PrimaryTableCol<TargetStatus> {
|
|
const column = columns.find((item) => item.colKey === colKey);
|
|
expect(column).toBeDefined();
|
|
return column!;
|
|
}
|
|
|
|
function makeTarget(overrides: Partial<TargetStatus> = {}): TargetStatus {
|
|
return {
|
|
currentStreak: null,
|
|
group: "default",
|
|
id: "1",
|
|
interval: "5s",
|
|
latestCheck: null,
|
|
name: "test",
|
|
recentSamples: [],
|
|
stats: { availability: 100, downChecks: 0, totalChecks: 0, upChecks: 0 },
|
|
target: "https://example.com",
|
|
type: "http",
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("createTargetTableColumns", () => {
|
|
test("生成 7 个目标表格列", () => {
|
|
const columns = createTargetTableColumns(["http", "cmd"]);
|
|
|
|
expect(columns.map((column) => column.colKey)).toEqual([
|
|
"latestCheck.matched",
|
|
"name",
|
|
"type",
|
|
"stats.availability",
|
|
"recentSamples",
|
|
"currentStreak",
|
|
"latestCheck.durationMs",
|
|
]);
|
|
});
|
|
|
|
test("根据 checkerTypes 生成类型筛选器", () => {
|
|
const typeColumn = getColumn(createTargetTableColumns(["http", "cmd", "tcp"]), "type");
|
|
const filter = typeColumn.filter as TableFilter;
|
|
|
|
expect(filter.type).toBe("single");
|
|
expect(filter.list).toEqual([
|
|
{ label: "全部", value: "" },
|
|
{ label: "http", value: "http" },
|
|
{ label: "cmd", value: "cmd" },
|
|
{ label: "tcp", value: "tcp" },
|
|
]);
|
|
});
|
|
|
|
test("checkerTypes 为空时只保留全部选项", () => {
|
|
const typeColumn = getColumn(createTargetTableColumns([]), "type");
|
|
const filter = typeColumn.filter as TableFilter;
|
|
|
|
expect(filter.list).toEqual([{ label: "全部", value: "" }]);
|
|
});
|
|
|
|
test("类型列直接渲染原始 type 文本", () => {
|
|
const typeColumn = getColumn(createTargetTableColumns(["tcp"]), "type");
|
|
const renderCell = typeColumn.cell as (params: PrimaryTableCellParams<TargetStatus>) => {
|
|
props: { children: unknown };
|
|
};
|
|
const element = renderCell({
|
|
col: typeColumn,
|
|
colIndex: 2,
|
|
row: makeTarget({ type: "tcp" }),
|
|
rowIndex: 0,
|
|
});
|
|
|
|
expect(element.props.children).toBe("tcp");
|
|
});
|
|
|
|
test("连续状态列渲染 capped 标记", () => {
|
|
const streakColumn = getColumn(createTargetTableColumns(["http"]), "currentStreak");
|
|
const renderCell = streakColumn.cell as (params: PrimaryTableCellParams<TargetStatus>) => {
|
|
props: { children: unknown[] };
|
|
};
|
|
const element = renderCell({
|
|
col: streakColumn,
|
|
colIndex: 5,
|
|
row: makeTarget({ currentStreak: { capped: true, count: 30, up: false } }),
|
|
rowIndex: 0,
|
|
});
|
|
|
|
expect(streakColumn.title).toBe("连续(次)");
|
|
expect(element.props.children.join("")).toBe("▼ 30+");
|
|
});
|
|
|
|
test("延迟列超过 9999ms 时显示上限文案", () => {
|
|
const latencyColumn = getColumn(createTargetTableColumns(["http"]), "latestCheck.durationMs");
|
|
const renderCell = latencyColumn.cell as (params: PrimaryTableCellParams<TargetStatus>) => {
|
|
props: { children: string; className: string };
|
|
};
|
|
const element = renderCell({
|
|
col: latencyColumn,
|
|
colIndex: 6,
|
|
row: makeTarget({
|
|
latestCheck: {
|
|
durationMs: 12000,
|
|
failure: null,
|
|
matched: true,
|
|
statusDetail: "200",
|
|
timestamp: "2026-01-01T00:00:00.000Z",
|
|
},
|
|
}),
|
|
rowIndex: 0,
|
|
});
|
|
|
|
expect(element.props.children).toBe("9999+ms");
|
|
expect(element.props.className).toContain("latency-value");
|
|
});
|
|
});
|