import { expect, test, type Page } from "@playwright/test"; import { TextReader, Uint8ArrayReader, Uint8ArrayWriter, ZipWriter, } from "@zip.js/zip.js"; const ORIGIN = "http://127.0.0.1:4173"; async function localOnly(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; } async function epubFixture(): Promise { const writer = new ZipWriter(new Uint8ArrayWriter()); await writer.add("mimetype", new TextReader("application/epub+zip"), { level: 0, }); await writer.add( "META-INF/container.xml", new TextReader( ``, ), ); await writer.add( "EPUB/package.opf", new TextReader( `urn:browser:testBrowser FixtureenLocal Author`, ), ); await writer.add( "EPUB/nav.xhtml", new TextReader( ``, ), ); await writer.add( "EPUB/chapter.xhtml", new TextReader( `A safe chapter

Hello from EPUB

`, ), ); await writer.add( "EPUB/cover.png", new Uint8ArrayReader( Buffer.from( "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=", "base64", ), ), ); return Buffer.from(await writer.close()); } test("runs from a nested path without external requests", async ({ page }) => { const errors: string[] = []; page.on("pageerror", (error) => errors.push(error.message)); page.on("console", (message) => { if (message.type() === "error") errors.push(message.text()); }); const external = await localOnly(page); await page.goto("/deep/nested/epub/"); await expect(page.getByRole("heading", { name: "EPUB Tools" })).toBeVisible(); expect(external).toEqual([]); expect(errors).toEqual([]); }); test("serves the release identity and hardened headers", async ({ request, }) => { const index = await request.get("/deep/nested/epub/"); expect(index.ok()).toBe(true); expect(index.headers()["content-security-policy"]).toContain( "default-src 'self'", ); expect(await index.text()).not.toMatch(/\b(?:src|href)=["']\//u); const manifest = await request.get("/deep/nested/epub/toolbox-app.json"); await expect(manifest.json()).resolves.toMatchObject({ id: "de.add-ideas.epub-tools", version: "0.1.0", entry: "./", }); }); test("opens, sanitizes, edits, rebuilds, and reopens a real EPUB", async ({ page, }) => { const external = await localOnly(page); await page.goto("/deep/nested/epub/"); await page.getByLabel("Choose EPUB").setInputFiles({ name: "fixture.epub", mimeType: "application/epub+zip", buffer: await epubFixture(), }); await expect( page.getByText("Browser Fixture", { exact: true }).first(), ).toBeVisible({ timeout: 30_000 }); const reader = page.frameLocator("iframe[title^='Safe EPUB preview']"); await expect( reader.getByRole("heading", { name: "Hello from EPUB" }), ).toBeVisible(); await expect(reader.locator("script")).toHaveCount(0); await page.getByRole("tab", { name: "Metadata" }).click(); await page.getByLabel("Title").fill("Updated in browser"); await page.getByRole("tab", { name: "Export & rebuild" }).click(); const downloadPromise = page.waitForEvent("download"); await page.getByRole("button", { name: "Create updated EPUB" }).click(); const download = await downloadPromise; const path = await download.path(); expect(path).toBeTruthy(); await page.getByLabel("Open another").setInputFiles(path!); await expect( page.getByText("Updated in browser", { exact: true }).first(), ).toBeVisible({ timeout: 30_000 }); expect(external).toEqual([]); });