import { test, expect } from "@playwright/test"; import { gotoPage, openApp } from "./helpers"; // The Files library end to end, against the real app: the page opens on the whole library, and a // link — typed into its box, or pasted onto any page — opens the one download dialog on it. Nothing // is downloaded: the dialog is closed, so the run leaves the E2E account's library as it found it. test.describe("Files", () => { const LINK = "https://www.youtube.com/watch?v=jNQXAC9IVRw"; const dialog = (page: import("@playwright/test").Page) => page.getByRole("dialog", { name: "Download video" }); test("opens on the whole library, and its link box hands a link to the download dialog", async ({ page, }) => { await openApp(page); await gotoPage(page, "files"); await expect(page.getByRole("heading", { name: "All files" })).toBeVisible(); const box = page.getByRole("textbox", { name: "A link to download" }); await box.fill(LINK); await box.press("Enter"); await expect(dialog(page)).toBeVisible(); await expect(dialog(page)).toContainText("jNQXAC9IVRw"); await page.keyboard.press("Escape"); await expect(dialog(page)).toBeHidden(); }); // WebKit (every iPad browser) cannot resolve a percentage height against a box whose height comes // from aspect-ratio inside a table cell: the picture took its own full height and the 16:9 box // showed a native-size sliver of it, a blur of colour. The library is stubbed with one file whose // poster is a tall picture, the case that shows it most. test("a row's picture fits its box", async ({ page }) => { const file = { id: 990001, status: "done", progress: 100, created_at: "2026-11-14T10:00:00+00:00", source_kind: "youtube", source_ref: "e2e-thumb", source_url: null, poster_url: "/api/downloads/990001/poster.jpg", display_name: "A tall poster", display_uploader: null, extra_links: [], can_download: true, job_kind: "download", folder_id: null, kept: false, expires_at: null, shared: false, source_key: "youtube", asset: { media_kind: "video", duration_s: 60, size_bytes: 2048 }, }; await page.route(/\/api\/files(\?|$)/, (route) => route.fulfill({ json: [file] })); await page.route(/\/api\/downloads\/990001\/poster\.jpg/, (route) => route.fulfill({ contentType: "image/svg+xml", body: '', }), ); // Wide enough that the picture column shows beside a pinned rail (an iPad Pro in landscape). await page.setViewportSize({ width: 1366, height: 1024 }); await openApp(page); await gotoPage(page, "files"); const picture = page.getByRole("row", { name: /A tall poster/ }).locator("img"); await expect(picture).toBeVisible(); const fit = await picture.evaluate((img) => { const box = img.parentElement!.getBoundingClientRect(); return { img: img.getBoundingClientRect().height, box: box.height }; }); expect(fit.img).toBeLessThanOrEqual(fit.box); }); test("a link pasted onto a page (not into a field) opens the download dialog", async ({ page, }) => { await openApp(page); await page.evaluate((text) => { const e = new Event("paste", { bubbles: true, cancelable: true }); Object.defineProperty(e, "clipboardData", { value: { getData: (type: string) => (type === "text/plain" ? text : "") }, }); document.body.dispatchEvent(e); }, LINK); await expect(dialog(page)).toBeVisible(); await page.keyboard.press("Escape"); await expect(dialog(page)).toBeHidden(); }); });