From a3d8ae72e3c6bcebe0f4284e312989b483213ee7 Mon Sep 17 00:00:00 2001 From: fabi Date: Wed, 29 Jul 2026 20:10:54 +0200 Subject: [PATCH] fix(e2e): stop the video poster assertion racing the ffmpeg thumbnail Pre-existing, and it fired for real during the full-suite run on a cold stack. The lightbox binds `poster={upload.thumbnail_url ?? undefined}`, so the attribute is absent until compression produces the thumbnail. This test asserted on it immediately after seeding, never waiting for the worker -- unlike the Range test further down the same file, which does poll. Against a warm stack the worker usually wins; against a freshly rebuilt one (`stack:down -v`, cold ffmpeg) it doesn't. That is the worst possible time for a false failure: the first run after a rebuild is exactly when you are trying to establish whether a change broke something. Poll for `compression_status = 'done'` before the poster assertion. The `src` assertion needs no wait and keeps none. Verified with --repeat-each=3. Co-Authored-By: Claude Opus 5 --- e2e/specs/03-feed/video-playback.spec.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/e2e/specs/03-feed/video-playback.spec.ts b/e2e/specs/03-feed/video-playback.spec.ts index dbbd6a4..1fb8bc4 100644 --- a/e2e/specs/03-feed/video-playback.spec.ts +++ b/e2e/specs/03-feed/video-playback.spec.ts @@ -40,10 +40,19 @@ test.describe('Video — the lightbox plays it', () => { page, guest, signIn, + db, }) => { const g = await guest('VideoWatcher'); const id = await seedVideo(g.jwt); + // The poster assertion below needs the ffmpeg thumbnail to EXIST — the lightbox binds + // `poster={upload.thumbnail_url ?? undefined}`, so the attribute is simply absent until + // compression finishes. Without this wait the test races the worker and fails against a + // cold stack (first run after `stack:down -v`, cold ffmpeg), which is exactly when a suite + // is least likely to be believed. The `src` assertion is unconditional; only the poster + // needs the wait. + await expect.poll(() => db.compressionStatus(id), { timeout: 60_000 }).toBe('done'); + await signIn(page, g); await page.goto('/feed');