diff --git a/frontend/e2e/files.spec.ts b/frontend/e2e/files.spec.ts index 525e066f..a61625a3 100644 --- a/frontend/e2e/files.spec.ts +++ b/frontend/e2e/files.spec.ts @@ -24,6 +24,52 @@ test.describe("Files", () => { 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, }) => { diff --git a/frontend/src/modules/files/Files.tsx b/frontend/src/modules/files/Files.tsx index ffa54259..a06b3044 100644 --- a/frontend/src/modules/files/Files.tsx +++ b/frontend/src/modules/files/Files.tsx @@ -465,10 +465,13 @@ export default function Files() { // A narrow table (a pinned rail beside it) gives its fixed columns' room to the name: with the // picture and the date in, the name had none left. narrowHidden: true, + // A fixed height, not aspect-video: in a table cell WebKit (every iPad browser) resolves the + // picture's h-full against an aspect-ratio height as its own natural height, and the box then + // shows a native-size sliver of the poster. 20 × 11.25 is the same 16:9. render: (f) => ( ), },