import { beforeEach, describe, expect, it, vi } from "vitest"; import { GET as listAlerts } from "@/app/api/alerts/route"; import { POST as resolveAlert } from "@/app/api/alerts/[id]/resolve/route"; vi.mock("@/lib/prisma", () => ({ prisma: { alertLog: { count: vi.fn(), findMany: vi.fn(), findUnique: vi.fn(), update: vi.fn(), }, }, })); import { prisma } from "@/lib/prisma"; const ADMIN_HEADERS = { "x-auth-type": "admin", "x-user-id": "U_admin_demo", "x-user-role": "admin", }; const SERVICE_HEADERS = { "x-auth-type": "service", "x-customer-id": "CUST_001", "x-permissions": "", }; const SAMPLE_ALERT = { id: BigInt(1), alertType: "RPA_FAILED", quoteId: "QTE_001", cargoHash: "abc123", detailJson: { reason: "timeout" }, status: "open", resolverId: null, resolvedAt: null, createdAt: new Date("2026-06-16T08:00:00Z"), }; beforeEach(() => { vi.clearAllMocks(); }); describe("GET /api/alerts", () => { it("admin + type 筛选 → 200", async () => { vi.mocked(prisma.alertLog.count).mockResolvedValue(1); vi.mocked(prisma.alertLog.findMany).mockResolvedValue([SAMPLE_ALERT as never]); const response = await listAlerts( new Request( "http://localhost/api/alerts?page=1&size=20&type=RPA_FAILED&status=open", { headers: ADMIN_HEADERS }, ), ); const json = await response.json(); expect(response.status).toBe(200); expect(json.code).toBe(0); expect(json.data.list).toHaveLength(1); expect(json.data.list[0].alert_type).toBe("RPA_FAILED"); expect(prisma.alertLog.findMany).toHaveBeenCalledWith( expect.objectContaining({ where: { alertType: "RPA_FAILED", status: "open" }, }), ); }); it("缺分页 → 400", async () => { const response = await listAlerts( new Request("http://localhost/api/alerts", { headers: ADMIN_HEADERS }), ); expect(response.status).toBe(400); }); it("宿主 token → 403", async () => { const response = await listAlerts( new Request("http://localhost/api/alerts?page=1&size=20", { headers: SERVICE_HEADERS, }), ); expect(response.status).toBe(403); }); }); describe("POST /api/alerts/{id}/resolve", () => { it("admin 处理 → 200 + resolved", async () => { vi.mocked(prisma.alertLog.findUnique).mockResolvedValue( SAMPLE_ALERT as never, ); vi.mocked(prisma.alertLog.update).mockResolvedValue({ ...SAMPLE_ALERT, status: "resolved", resolverId: "U_admin_demo", resolvedAt: new Date("2026-06-16T09:00:00Z"), } as never); const response = await resolveAlert( new Request("http://localhost/api/alerts/1/resolve", { method: "POST", headers: { ...ADMIN_HEADERS, "Content-Type": "application/json" }, body: JSON.stringify({ resolver_id: "U_admin_demo" }), }), { params: Promise.resolve({ id: "1" }) }, ); const json = await response.json(); expect(response.status).toBe(200); expect(json.data.status).toBe("resolved"); expect(json.data.resolver_id).toBe("U_admin_demo"); }); it("不存在 id → 404", async () => { vi.mocked(prisma.alertLog.findUnique).mockResolvedValue(null); const response = await resolveAlert( new Request("http://localhost/api/alerts/999/resolve", { method: "POST", headers: ADMIN_HEADERS, }), { params: Promise.resolve({ id: "999" }) }, ); expect(response.status).toBe(404); }); it("非 admin → 403", async () => { const response = await resolveAlert( new Request("http://localhost/api/alerts/1/resolve", { method: "POST", headers: SERVICE_HEADERS, }), { params: Promise.resolve({ id: "1" }) }, ); expect(response.status).toBe(403); }); });