Files
prowler/ui/lib/helper.test.ts

138 lines
3.7 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from "vitest";
import { downloadScanZip, getErrorMessage } 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(
"<html><body><h1>504 Gateway Time-out</h1></body></html>",
{
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(
"<html><head><title>502 Bad Gateway</title></head><body><h1>502 Bad Gateway</h1></body></html>",
);
// When
const message = getErrorMessage(error);
// Then
expect(message).toBe(
"Server is temporarily unavailable. Please try again in a few minutes.",
);
});
});