mirror of
https://github.com/mgeeky/decode-spam-headers.git
synced 2026-02-22 13:33:30 +01:00
173 lines
4.4 KiB
TypeScript
173 lines
4.4 KiB
TypeScript
import type { ReactElement } from "react";
|
|
import { act } from "react-dom/test-utils";
|
|
import { createRoot } from "react-dom/client";
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import Home from "../app/page";
|
|
import type { AnalysisConfig, 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,
|
|
captchaChallenge: null,
|
|
submit: submitSpy,
|
|
cancel: cancelSpy,
|
|
clearCaptchaChallenge: vi.fn(),
|
|
},
|
|
};
|
|
});
|
|
|
|
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 getClearCacheButton = (container: HTMLElement): HTMLButtonElement => {
|
|
const buttons = Array.from(container.querySelectorAll("button"));
|
|
const button = buttons.find((candidate) =>
|
|
(candidate.textContent ?? "").toLowerCase().includes("clear cache"),
|
|
);
|
|
if (!button) {
|
|
throw new Error("Expected clear cache button to be rendered.");
|
|
}
|
|
return button as HTMLButtonElement;
|
|
};
|
|
|
|
const cachedConfig: AnalysisConfig = {
|
|
testIds: [101, 202],
|
|
resolve: false,
|
|
decodeAll: false,
|
|
};
|
|
|
|
const cachedReport: AnalysisReport = {
|
|
results: [
|
|
{
|
|
testId: 101,
|
|
testName: "SpamAssassin Rule Hits",
|
|
headerName: "X-Spam-Status",
|
|
headerValue: "Yes",
|
|
analysis: "Hits: 6.2",
|
|
description: "Spam scoring summary.",
|
|
severity: "spam",
|
|
status: "success",
|
|
error: null,
|
|
},
|
|
],
|
|
hopChain: [],
|
|
securityAppliances: [],
|
|
metadata: {
|
|
totalTests: 1,
|
|
passedTests: 1,
|
|
failedTests: 0,
|
|
skippedTests: 0,
|
|
elapsedMs: 1200,
|
|
timedOut: false,
|
|
incompleteTests: [],
|
|
},
|
|
};
|
|
|
|
const seedCache = (headers: string) => {
|
|
localStorage.setItem("wha:headers", headers);
|
|
localStorage.setItem("wha:config", JSON.stringify(cachedConfig));
|
|
localStorage.setItem("wha:result", JSON.stringify(cachedReport));
|
|
localStorage.setItem("wha:timestamp", "1700000000000");
|
|
};
|
|
|
|
const resetUseAnalysisState = (): void => {
|
|
useAnalysisState.status = "idle";
|
|
useAnalysisState.progress = null;
|
|
useAnalysisState.result = null;
|
|
useAnalysisState.error = null;
|
|
useAnalysisState.captchaChallenge = null;
|
|
};
|
|
|
|
beforeEach(() => {
|
|
localStorage.clear();
|
|
resetUseAnalysisState();
|
|
});
|
|
|
|
afterEach(() => {
|
|
while (cleanups.length > 0) {
|
|
const cleanup = cleanups.pop();
|
|
if (cleanup) {
|
|
cleanup();
|
|
}
|
|
}
|
|
submitSpy.mockClear();
|
|
cancelSpy.mockClear();
|
|
localStorage.clear();
|
|
});
|
|
|
|
describe("Home page cache", () => {
|
|
it("restores cached analysis on mount", () => {
|
|
seedCache("Received: from mail.example.com");
|
|
|
|
const { container } = render(<Home />);
|
|
const textarea = getTextarea(container);
|
|
|
|
expect(textarea.value).toBe("Received: from mail.example.com");
|
|
const report = container.querySelector('[data-testid="report-container"]');
|
|
expect(report).not.toBeNull();
|
|
});
|
|
|
|
it("clears cached data and resets the view", () => {
|
|
seedCache("Received: from mail.example.com");
|
|
|
|
const { container } = render(<Home />);
|
|
const button = getClearCacheButton(container);
|
|
|
|
act(() => {
|
|
button.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
});
|
|
|
|
expect(localStorage.getItem("wha:headers")).toBeNull();
|
|
expect(localStorage.getItem("wha:config")).toBeNull();
|
|
expect(localStorage.getItem("wha:result")).toBeNull();
|
|
expect(localStorage.getItem("wha:timestamp")).toBeNull();
|
|
expect(getTextarea(container).value).toBe("");
|
|
expect(container.querySelector('[data-testid="report-container"]')).toBeNull();
|
|
});
|
|
});
|