172 lines
5.8 KiB
TypeScript
172 lines
5.8 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
||
|
||
import {
|
||
validateDashboardWindow,
|
||
validateMetricsBucket,
|
||
validatePagination,
|
||
validateRecentLimit,
|
||
validateTargetId,
|
||
validateTimeRange,
|
||
} from "../../src/server/middleware";
|
||
|
||
describe("validateTargetId", () => {
|
||
test("有效的 target ID 返回字符串", () => {
|
||
const result = validateTargetId("api-health_01", "production");
|
||
expect(result).not.toHaveProperty("status");
|
||
expect((result as { id: string }).id).toBe("api-health_01");
|
||
});
|
||
|
||
test("无效的 target ID 返回 400", () => {
|
||
const invalid = ["-1", "_abc", "has space", "1.5", ""];
|
||
|
||
for (const id of invalid) {
|
||
const result = validateTargetId(id, "production");
|
||
expect(result).toHaveProperty("status", 400);
|
||
}
|
||
});
|
||
});
|
||
|
||
describe("validateTimeRange", () => {
|
||
test("有效的 from/to 返回 ISO 字符串", () => {
|
||
const result = validateTimeRange("2024-01-01T00:00:00.000Z", "2024-01-02T00:00:00.000Z", "production");
|
||
expect(result).not.toHaveProperty("status");
|
||
expect((result as { from: string; to: string }).from).toBe("2024-01-01T00:00:00.000Z");
|
||
expect((result as { from: string; to: string }).to).toBe("2024-01-02T00:00:00.000Z");
|
||
});
|
||
|
||
test("缺失 from 或 to 返回 400", () => {
|
||
const missingFrom = validateTimeRange(null, "2024-01-02T00:00:00.000Z", "production");
|
||
const missingTo = validateTimeRange("2024-01-01T00:00:00.000Z", null, "production");
|
||
const missingBoth = validateTimeRange(null, null, "production");
|
||
|
||
expect(missingFrom).toHaveProperty("status", 400);
|
||
expect(missingTo).toHaveProperty("status", 400);
|
||
expect(missingBoth).toHaveProperty("status", 400);
|
||
});
|
||
|
||
test("空字符串 from 或 to 返回 400", () => {
|
||
const emptyFrom = validateTimeRange("", "2024-01-02T00:00:00.000Z", "production");
|
||
const emptyTo = validateTimeRange("2024-01-01T00:00:00.000Z", "", "production");
|
||
|
||
expect(emptyFrom).toHaveProperty("status", 400);
|
||
expect(emptyTo).toHaveProperty("status", 400);
|
||
});
|
||
|
||
test("无效的日期格式返回 400", () => {
|
||
const result = validateTimeRange("invalid-date", "2024-01-02T00:00:00.000Z", "production");
|
||
expect(result).toHaveProperty("status", 400);
|
||
});
|
||
|
||
test("from 晚于 to 返回 400", () => {
|
||
const result = validateTimeRange("2024-01-02T00:00:00.000Z", "2024-01-01T00:00:00.000Z", "production");
|
||
expect(result).toHaveProperty("status", 400);
|
||
});
|
||
});
|
||
|
||
describe("validatePagination", () => {
|
||
test("默认值:page=1, pageSize=20", () => {
|
||
const result = validatePagination(null, null, "production");
|
||
expect(result).toEqual({ page: 1, pageSize: 20 });
|
||
});
|
||
|
||
test("有效的 page 和 pageSize 参数", () => {
|
||
const result = validatePagination("2", "50", "production");
|
||
expect(result).toEqual({ page: 2, pageSize: 50 });
|
||
});
|
||
|
||
test("无效的 page 参数返回 400", () => {
|
||
const invalidPage = ["0", "-1", "abc", "1.5"];
|
||
|
||
for (const page of invalidPage) {
|
||
const result = validatePagination(page, "20", "production");
|
||
expect(result).toHaveProperty("status", 400);
|
||
}
|
||
});
|
||
|
||
test("无效的 pageSize 参数返回 400", () => {
|
||
const invalidPageSize = ["0", "-1", "abc", "1.5"];
|
||
|
||
for (const pageSize of invalidPageSize) {
|
||
const result = validatePagination("1", pageSize, "production");
|
||
expect(result).toHaveProperty("status", 400);
|
||
}
|
||
});
|
||
|
||
test("pageSize 超过上限返回 400", () => {
|
||
const result = validatePagination("1", "201", "production");
|
||
expect(result).toHaveProperty("status", 400);
|
||
});
|
||
|
||
test("pageSize 等于上限 200 返回成功", () => {
|
||
const result = validatePagination("1", "200", "production");
|
||
expect(result).toEqual({ page: 1, pageSize: 200 });
|
||
});
|
||
});
|
||
|
||
describe("validateRecentLimit", () => {
|
||
test("默认值:recentLimit=30", () => {
|
||
const result = validateRecentLimit(null, "production");
|
||
expect(result).toEqual({ recentLimit: 30 });
|
||
});
|
||
|
||
test("有效的 recentLimit 参数", () => {
|
||
const result = validateRecentLimit("50", "production");
|
||
expect(result).toEqual({ recentLimit: 50 });
|
||
});
|
||
|
||
test("无效的 recentLimit 参数返回 400", () => {
|
||
const invalid = ["0", "-1", "abc", "1.5"];
|
||
|
||
for (const limit of invalid) {
|
||
const result = validateRecentLimit(limit, "production");
|
||
expect(result).toHaveProperty("status", 400);
|
||
}
|
||
});
|
||
|
||
test("recentLimit 超过上限返回 400", () => {
|
||
const result = validateRecentLimit("201", "production");
|
||
expect(result).toHaveProperty("status", 400);
|
||
});
|
||
|
||
test("recentLimit 等于上限 200 返回成功", () => {
|
||
const result = validateRecentLimit("200", "production");
|
||
expect(result).toEqual({ recentLimit: 200 });
|
||
});
|
||
});
|
||
|
||
describe("validateDashboardWindow", () => {
|
||
test("默认值:window=24h", () => {
|
||
const result = validateDashboardWindow(null, "production");
|
||
expect(result).not.toHaveProperty("status");
|
||
expect((result as { label: string }).label).toBe("24h");
|
||
});
|
||
|
||
test("window=24h 返回成功", () => {
|
||
const result = validateDashboardWindow("24h", "production");
|
||
expect(result).not.toHaveProperty("status");
|
||
expect((result as { label: string }).label).toBe("24h");
|
||
});
|
||
|
||
test("不支持的 window 参数返回 400", () => {
|
||
const result = validateDashboardWindow("7d", "production");
|
||
expect(result).toHaveProperty("status", 400);
|
||
});
|
||
});
|
||
|
||
describe("validateMetricsBucket", () => {
|
||
test("默认值:bucket=auto", () => {
|
||
const result = validateMetricsBucket(null, "production");
|
||
expect(result).toEqual({ bucket: "auto" });
|
||
});
|
||
|
||
test("bucket=1h 返回成功", () => {
|
||
const result = validateMetricsBucket("1h", "production");
|
||
expect(result).toEqual({ bucket: "1h" });
|
||
});
|
||
|
||
test("不支持的 bucket 参数返回 400", () => {
|
||
const result = validateMetricsBucket("invalid", "production");
|
||
expect(result).toHaveProperty("status", 400);
|
||
});
|
||
});
|