diff --git a/frontend/src/components/Playlists.dom.test.tsx b/frontend/src/components/Playlists.dom.test.tsx index db537359..e835fc1a 100644 --- a/frontend/src/components/Playlists.dom.test.tsx +++ b/frontend/src/components/Playlists.dom.test.tsx @@ -124,8 +124,15 @@ describe("Playlists — the row the player is launched with", () => { await waitFor(() => expect(h.player?.video.position_seconds).toBe(748)); act(() => h.player!.onClose()); h.player = null; - // What the player's cleanup does with the position the server confirmed. - act(() => patchCachedProgress(qc, new Map([["V", 830]]))); + // What the player's cleanup does with the position the server confirmed. react-query hands a + // cache write to its observers on a setTimeout(0); outside act, the re-render it triggers is + // scheduled by React on its own and raced the click below under the gate's parallel load (the + // reopen read 748). The write is SYNCHRONOUS, so its notify timer is registered before ours and + // fires first — and inside act, the render it causes is flushed before act returns. + await act(async () => { + patchCachedProgress(qc, new Map([["V", 830]])); + await new Promise((r) => setTimeout(r, 0)); + }); await play("Video V"); await waitFor(() => expect(h.player?.video.position_seconds).toBe(830)); });