mirror of
https://github.com/mgeeky/decode-spam-headers.git
synced 2026-02-22 13:33:30 +01:00
156 lines
4.1 KiB
TypeScript
156 lines
4.1 KiB
TypeScript
import type { ReactElement } from "react";
|
|
import { act } from "react-dom/test-utils";
|
|
import { createRoot } from "react-dom/client";
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import Home from "../app/page";
|
|
import type { AnalysisProgress, AnalysisReport } from "../types/analysis";
|
|
|
|
const { submitSpy, cancelSpy, useAnalysisState } = vi.hoisted(() => {
|
|
const submitSpy = vi.fn().mockResolvedValue(undefined);
|
|
const cancelSpy = vi.fn();
|
|
|
|
return {
|
|
submitSpy,
|
|
cancelSpy,
|
|
useAnalysisState: {
|
|
status: "idle",
|
|
progress: null,
|
|
result: null,
|
|
error: null,
|
|
submit: submitSpy,
|
|
cancel: cancelSpy,
|
|
},
|
|
};
|
|
});
|
|
|
|
vi.mock("../hooks/useAnalysis", () => ({
|
|
__esModule: true,
|
|
default: () => useAnalysisState,
|
|
}));
|
|
|
|
type RenderResult = {
|
|
container: HTMLDivElement;
|
|
};
|
|
|
|
const cleanups: Array<() => void> = [];
|
|
|
|
const render = (ui: ReactElement): RenderResult => {
|
|
const container = document.createElement("div");
|
|
document.body.appendChild(container);
|
|
const root = createRoot(container);
|
|
|
|
act(() => {
|
|
root.render(ui);
|
|
});
|
|
|
|
cleanups.push(() => {
|
|
act(() => {
|
|
root.unmount();
|
|
});
|
|
container.remove();
|
|
});
|
|
|
|
return { container };
|
|
};
|
|
|
|
const getTextarea = (container: HTMLElement): HTMLTextAreaElement => {
|
|
const textarea = container.querySelector("textarea");
|
|
if (!textarea) {
|
|
throw new Error("Expected header textarea to be rendered.");
|
|
}
|
|
return textarea as HTMLTextAreaElement;
|
|
};
|
|
|
|
const getAnalyseButton = (container: HTMLElement): HTMLButtonElement => {
|
|
const buttons = Array.from(container.querySelectorAll("button"));
|
|
const button = buttons.find((candidate) =>
|
|
(candidate.textContent ?? "").toLowerCase().includes("analyse"),
|
|
);
|
|
if (!button) {
|
|
throw new Error("Expected analyse button to be rendered.");
|
|
}
|
|
return button as HTMLButtonElement;
|
|
};
|
|
|
|
const baseProgress: AnalysisProgress = {
|
|
currentIndex: 2,
|
|
totalTests: 4,
|
|
currentTest: "SpamAssassin Rule Hits",
|
|
elapsedMs: 29000,
|
|
percentage: 78,
|
|
};
|
|
|
|
const resetUseAnalysisState = (): void => {
|
|
useAnalysisState.status = "idle";
|
|
useAnalysisState.progress = null;
|
|
useAnalysisState.result = null;
|
|
useAnalysisState.error = null;
|
|
};
|
|
|
|
afterEach(() => {
|
|
while (cleanups.length > 0) {
|
|
const cleanup = cleanups.pop();
|
|
if (cleanup) {
|
|
cleanup();
|
|
}
|
|
}
|
|
submitSpy.mockClear();
|
|
cancelSpy.mockClear();
|
|
resetUseAnalysisState();
|
|
});
|
|
|
|
describe("Home page", () => {
|
|
it("submits analysis when analyse is clicked", () => {
|
|
const { container } = render(<Home />);
|
|
const textarea = getTextarea(container);
|
|
|
|
act(() => {
|
|
textarea.value = "Received: from mail.example.com";
|
|
textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
});
|
|
|
|
const button = getAnalyseButton(container);
|
|
act(() => {
|
|
button.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
});
|
|
|
|
expect(submitSpy).toHaveBeenCalledTimes(1);
|
|
expect(submitSpy).toHaveBeenCalledWith({
|
|
headers: "Received: from mail.example.com",
|
|
config: { testIds: [], resolve: false, decodeAll: false },
|
|
});
|
|
});
|
|
|
|
it("shows timeout notification with incomplete tests and partial results", () => {
|
|
const timeoutReport: AnalysisReport = {
|
|
results: [],
|
|
hopChain: [],
|
|
securityAppliances: [],
|
|
metadata: {
|
|
totalTests: 4,
|
|
passedTests: 1,
|
|
failedTests: 0,
|
|
skippedTests: 0,
|
|
elapsedMs: 30000,
|
|
timedOut: true,
|
|
incompleteTests: ["Mimecast Fingerprint", "Proofpoint TAP"],
|
|
},
|
|
};
|
|
|
|
useAnalysisState.status = "timeout";
|
|
useAnalysisState.progress = baseProgress;
|
|
useAnalysisState.result = timeoutReport;
|
|
|
|
const { container } = render(<Home />);
|
|
const alert = container.querySelector('[role="alert"]');
|
|
expect(alert).not.toBeNull();
|
|
const timeoutTests = container.querySelector('[data-testid="timeout-tests"]');
|
|
expect(timeoutTests?.textContent ?? "").toMatch(/Mimecast Fingerprint/);
|
|
expect(timeoutTests?.textContent ?? "").toMatch(/Proofpoint TAP/);
|
|
|
|
const results = container.querySelector('[data-testid="analysis-results"]');
|
|
expect(results).not.toBeNull();
|
|
});
|
|
});
|