import { expect, test, type Page } from "@playwright/test"; import { Buffer } from "node:buffer"; import { readFile } from "node:fs/promises"; const ORIGIN = "http://127.0.0.1:4195"; async function watchLocalOnly(page: Page) { const external: string[] = []; await page.route("**/*", async (route) => { const url = new URL(route.request().url()); if (url.origin !== ORIGIN) { external.push(url.href); await route.abort(); } else await route.continue(); }); return external; } function errors(page: Page) { const values: string[] = []; page.on("pageerror", (error) => values.push(error.message)); page.on("console", (message) => { if (message.type() === "error") values.push(message.text()); }); return values; } test("runs from a nested path and keeps HTML preview local and inert", async ({ page, }) => { await page.setViewportSize({ width: 1800, height: 1000 }); const external = await watchLocalOnly(page); const failures = errors(page); await page.goto("/deep/nested/mail/"); await expect(page.getByRole("heading", { name: "Mail Tools" })).toBeVisible(); await expect(page.getByText(/Parsed 5 MIME parts/iu)).toBeVisible(); await page.getByRole("button", { name: "Bodies" }).click(); await page.getByLabel("Left body part").selectOption("1.2"); const frame = page.frameLocator( 'iframe[title="Sanitized HTML message body"]', ); await expect(frame.getByText("Hello review team.")).toBeVisible(); expect(await page.locator("iframe").getAttribute("sandbox")).toBe(""); expect(await page.locator("iframe").getAttribute("srcdoc")).not.toContain( "tracker.invalid", ); expect(external).toEqual([]); expect( failures.filter( (message) => !message.includes( "Blocked script execution in 'about:srcdoc' because the document's frame is sandboxed", ), ), ).toEqual([]); expect( await page .locator(".toolbox-shell__main") .evaluate((node) => getComputedStyle(node).width), ).toBe("1440px"); }); test("opens an EML and downloads decoded attachment bytes", async ({ page, }) => { await page.goto("/deep/nested/mail/"); const source = "From: Test \r\nDate: Tue, 01 Sep 2026 10:00:00 +0000\r\nContent-Type: multipart/mixed; boundary=x\r\n\r\n--x\r\nContent-Type: application/octet-stream\r\nContent-Disposition: attachment; filename=proof.bin\r\nContent-Transfer-Encoding: base64\r\n\r\nAAEC/w==\r\n--x--"; await page.getByTestId("mail-file-input").setInputFiles({ name: "fixture.eml", mimeType: "message/rfc822", buffer: Buffer.from(source), }); await expect(page.getByText(/Parsed 2 MIME parts/iu)).toBeVisible(); await page.getByRole("button", { name: "Attachments" }).click(); await expect(page.getByText("proof.bin", { exact: true })).toBeVisible(); const pending = page.waitForEvent("download"); await page.getByRole("button", { name: "Download" }).click(); const download = await pending; expect(download.suggestedFilename()).toBe("proof.bin"); const saved = await download.path(); expect(saved).not.toBeNull(); expect(await readFile(saved!)).toEqual(Buffer.from([0, 1, 2, 255])); }); test("retains the last model and creates canonical and redacted exports", async ({ page, }) => { await page.goto("/deep/nested/mail/"); await page.getByLabel("EML source").fill("not a header"); await page.getByRole("button", { name: "Inspect message" }).click(); await expect(page.getByRole("alert")).toContainText("last successful"); await page.getByRole("button", { name: "Export" }).click(); for (const [button, filename] of [ ["Download canonical EML", "canonical.eml"], ["Download redacted EML", "redacted.eml"], ["Download report", "redaction-report.json"], ] as const) { const pending = page.waitForEvent("download"); await page.getByRole("button", { name: button }).click(); expect((await pending).suggestedFilename()).toBe(filename); } }); test("integrates help, dark theme, PWA identity and hardened headers", async ({ page, request, }) => { await page.goto("/deep/nested/mail/"); await page.getByRole("button", { name: "Help" }).click(); await expect( page.getByRole("dialog", { name: "About Mail Tools" }), ).toContainText("opaque sandbox"); await page.keyboard.press("Escape"); await page.getByRole("button", { name: "Personalize" }).click(); await page.getByRole("button", { name: "Dark" }).click(); await expect(page.locator(".toolbox-shell").first()).toHaveAttribute( "data-toolbox-theme", "dark", ); const registration = await page.evaluate(async () => Boolean(await navigator.serviceWorker.ready), ); expect(registration).toBe(true); const index = await request.get("/deep/nested/mail/"); expect(index.headers()["content-security-policy"]).toContain( "connect-src 'self'", ); expect(await index.text()).not.toMatch(/\b(?:src|href)=["']\//u); const manifest = await request.get("/deep/nested/mail/toolbox-app.json"); await expect(manifest.json()).resolves.toMatchObject({ id: "de.add-ideas.mail-tools", version: "0.1.0", privacy: { processing: "local", telemetry: false }, }); });