diff --git a/e2e/helpers/webkit.ts b/e2e/helpers/webkit.ts new file mode 100644 index 0000000..9c98cd6 --- /dev/null +++ b/e2e/helpers/webkit.ts @@ -0,0 +1,29 @@ +import { test } from '@playwright/test'; + +/** + * Skip a test that depends on persisting a Blob/File in IndexedDB when running on + * Playwright's WebKit. + * + * The client upload queue (`frontend/src/lib/upload-queue.ts`) stores the file itself in + * IndexedDB so a backgrounded or reloaded phone can resume the upload. Playwright's Linux + * WebKit build cannot store Blobs in IndexedDB at all — `put()` fails with + * "UnknownError: Error preparing Blob/File data to be stored in object store". Verified to + * be the harness, not the app: a Blob constructed in-page with `new Blob([bytes])` fails + * exactly the same way, while Chromium stores both that and a `setInputFiles` File fine. + * Real iOS Safari supports Blobs in IndexedDB, so this is NOT evidence of a bug on the + * platform these tests exist to protect. + * + * Any test that drives the composer (FAB → UploadSheet → /upload → submit) hits this, + * because `handleSubmit` awaits `addToQueue`, which throws before it can navigate. + * + * This is deliberately narrow. WebKit still runs every API-driven upload test, the whole of + * 01-auth, 03-feed and 06-export — including the keepsake download, which only WebKit can + * meaningfully verify. If Playwright's WebKit ever gains IndexedDB Blob support, delete this + * helper and the four call sites. + */ +export function skipIfNoIdbBlobs(browserName: string) { + test.skip( + browserName === 'webkit', + "Playwright's Linux WebKit cannot store Blobs in IndexedDB (harness limitation, not an iOS one) — the client upload queue can't be exercised there" + ); +} diff --git a/e2e/specs/02-upload/burst-queue.spec.ts b/e2e/specs/02-upload/burst-queue.spec.ts index 8b538d5..fb9762f 100644 --- a/e2e/specs/02-upload/burst-queue.spec.ts +++ b/e2e/specs/02-upload/burst-queue.spec.ts @@ -26,6 +26,7 @@ * large fixture files. */ import { test, expect } from '../../fixtures/test'; +import { skipIfNoIdbBlobs } from '../../helpers/webkit'; import { FeedPage, UploadSheet } from '../../page-objects'; import { mkdtempSync, copyFileSync, rmSync } from 'node:fs'; import { join } from 'node:path'; @@ -100,7 +101,9 @@ test.describe('Upload — client queue under a burst', () => { guest, signIn, db, + browserName, }) => { + skipIfNoIdbBlobs(browserName); const g = await guest('BurstSerial'); await signIn(page, g); await warmUploadChunk(page); @@ -163,7 +166,9 @@ test.describe('Upload — client queue under a burst', () => { guest, signIn, db, + browserName, }) => { + skipIfNoIdbBlobs(browserName); const g = await guest('BurstResume'); await signIn(page, g); await warmUploadChunk(page); diff --git a/e2e/specs/02-upload/gallery-path.spec.ts b/e2e/specs/02-upload/gallery-path.spec.ts index 3eaa5d8..6c9b3a6 100644 --- a/e2e/specs/02-upload/gallery-path.spec.ts +++ b/e2e/specs/02-upload/gallery-path.spec.ts @@ -4,6 +4,7 @@ * IndexedDB queue resumption after refresh, and SSE `upload-processed`. */ import { test, expect } from '../../fixtures/test'; +import { skipIfNoIdbBlobs } from '../../helpers/webkit'; import { FeedPage, UploadSheet } from '../../page-objects'; import { SseListener } from '../../helpers/sse-listener'; import { join } from 'node:path'; @@ -49,7 +50,9 @@ test.describe('Upload — gallery path', () => { guest, signIn, db, + browserName, }) => { + skipIfNoIdbBlobs(browserName); // Previously fixme'd: the UI queue never fired a POST. Root cause was NOT a // navigation/blob timing quirk but an IndexedDB upgrade bug — the v1→v2 // `upgrade` callback opened a *new* transaction, which throws during a diff --git a/e2e/specs/02-upload/rejection-visible.spec.ts b/e2e/specs/02-upload/rejection-visible.spec.ts index 0ecc2d9..39a51ac 100644 --- a/e2e/specs/02-upload/rejection-visible.spec.ts +++ b/e2e/specs/02-upload/rejection-visible.spec.ts @@ -13,6 +13,7 @@ * queue row, no error text, and it never appeared in the feed. */ import { test, expect } from '../../fixtures/test'; +import { skipIfNoIdbBlobs } from '../../helpers/webkit'; import { FeedPage, UploadSheet } from '../../page-objects'; import { join } from 'node:path'; @@ -25,7 +26,9 @@ test.describe('Upload — a rejected upload is surfaced', () => { host, guest, signIn, + browserName, }) => { + skipIfNoIdbBlobs(browserName); const g = await guest('RejectedUploader'); await signIn(page, g);