import { NextRequest } from "next/server"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { InspectionInputError, InspectionResolutionError } from "@/lib/inspect/policy"; const { inspectMock } = vi.hoisted(() => ({ inspectMock: vi.fn() })); vi.mock("@/lib/inspect/inspect", () => ({ inspectHost: inspectMock })); import { classifyInspectionError, GET } from "./route"; function request(host = "example.com") { return new NextRequest("http://localhost/api/inspect?host=" + encodeURIComponent(host)); } describe("GET /api/inspect error classification", () => { beforeEach(() => inspectMock.mockReset()); it("returns a report with no-store caching on success", async () => { inspectMock.mockResolvedValue({ host: "example.com" }); const response = await GET(request()); expect(response.status).toBe(200); expect(response.headers.get("cache-control")).toBe("no-store"); expect(await response.json()).toEqual({ host: "example.com" }); }); it("maps user input and resolution policy errors to client errors", async () => { inspectMock.mockRejectedValueOnce(new InspectionInputError("invalid host")); expect((await GET(request("bad input"))).status).toBe(400); inspectMock.mockRejectedValueOnce(new InspectionResolutionError("not found")); expect((await GET(request("missing.example"))).status).toBe(422); }); it("classifies unexpected failures as a generic 500 without exposing details", () => { expect(classifyInspectionError(new Error("private upstream detail"))).toEqual({ status: 500, message: "Inspection service is temporarily unavailable. Try again shortly.", }); }); });