import { afterEach, describe, expect, it, vi } from "vitest"; import { downloadScanZip, getErrorMessage, permissionFormFields, } from "./helper"; vi.mock("@/actions/scans", () => ({ getComplianceCsv: vi.fn(), getCompliancePdfReport: vi.fn(), })); vi.mock("@/actions/task", () => ({ getTask: vi.fn(), })); vi.mock("@/auth.config", () => ({ auth: vi.fn(), })); const createToast = () => vi.fn(); const getAnchor = () => { const anchor = document.createElement("a"); const clickMock = vi.spyOn(anchor, "click").mockImplementation(() => {}); vi.spyOn(document, "createElement").mockReturnValue(anchor); return { anchor, clickMock }; }; describe("downloadScanZip", () => { afterEach(() => { vi.restoreAllMocks(); vi.unstubAllGlobals(); document.body.replaceChildren(); }); it("preflights the report and starts a browser-native download when ready", async () => { vi.stubGlobal( "fetch", vi.fn().mockResolvedValue(new Response(null, { status: 204 })), ); const { anchor, clickMock } = getAnchor(); const toast = createToast(); await downloadScanZip("scan-123", toast); expect(fetch).toHaveBeenCalledWith( "/api/scans/scan-123/report?preflight=1", { cache: "no-store", }, ); expect(anchor.href).toContain("/api/scans/scan-123/report"); expect(anchor.download).toBe("scan-scan-123-report.zip"); expect(clickMock).toHaveBeenCalledTimes(1); expect(toast).toHaveBeenCalledWith({ title: "Download Started", description: "Your browser is downloading the scan report.", }); }); it("shows the pending report message without starting a download", async () => { vi.stubGlobal( "fetch", vi.fn().mockResolvedValue(new Response("{}", { status: 202 })), ); const { clickMock } = getAnchor(); const toast = createToast(); await downloadScanZip("scan-123", toast); expect(clickMock).not.toHaveBeenCalled(); expect(toast).toHaveBeenCalledWith({ title: "The report is still being generated", description: "Please try again in a few minutes.", }); }); it("shows an error without starting a download when preflight fails", async () => { vi.stubGlobal( "fetch", vi.fn().mockResolvedValue(new Response("not found", { status: 404 })), ); const { clickMock } = getAnchor(); const toast = createToast(); await downloadScanZip("scan-123", toast); expect(clickMock).not.toHaveBeenCalled(); expect(toast).toHaveBeenCalledWith({ variant: "destructive", title: "Download Failed", description: "not found", }); }); it("shows a generic error when preflight fails with an HTML gateway page", async () => { vi.stubGlobal( "fetch", vi.fn().mockResolvedValue( new Response( "

504 Gateway Time-out

", { status: 504, headers: { "content-type": "text/html" }, }, ), ), ); const { clickMock } = getAnchor(); const toast = createToast(); await downloadScanZip("scan-123", toast); expect(clickMock).not.toHaveBeenCalled(); expect(toast).toHaveBeenCalledWith({ variant: "destructive", title: "Download Failed", description: "Unable to prepare the scan report. Please try again in a few minutes.", }); }); }); describe("getErrorMessage", () => { it("does not expose HTML gateway pages", () => { // Given const error = new Error( "502 Bad Gateway

502 Bad Gateway

", ); // When const message = getErrorMessage(error); // Then expect(message).toBe( "Server is temporarily unavailable. Please try again in a few minutes.", ); }); }); describe("permissionFormFields", () => { it("describes Unlimited Visibility as organization-wide", () => { // Given const field = permissionFormFields.find( ({ field }) => field === "unlimited_visibility", ); // When const description = field?.description; // Then expect(description).toContain("organization-wide visibility"); expect(description).not.toContain("tenant-wide"); }); });