tests/hooks/useTimelineMode.test.ts > live poll suspends in Timeline mode > does not probe the signature endpoint while in Timeline mode, and resumes on exit fails intermittently on main.
AssertionError: expected "fetch" to be called at least once
tests/hooks/useTimelineMode.test.ts:361:22
Twice in three weeks, both on main, both the same assertion:
Not reproducible on demand: 12/12 passes running the file alone, and the full suite with coverage passes 2153/2153 locally. It needs CI-level scheduling pressure.
Cause
TIMELINE_MODE never restarts the poll timer. setupLiveUpdates starts one interval and tick() early-returns while Timeline is on (app/src/hooks/useManifestSource.ts:286):
if (inFlight) return;
if (TIMELINE_MODE.peek()) return;
if (SCAN_PROGRESS.peek() !== null) return; // <- this one
So the resume assertion needs a tick to land in a 1000ms window and clear all three guards. SCAN_PROGRESS is module-level, and an earlier test in the same file leaks a load that writes it.
exitTimelineMode (line 297) starts a live-HEAD reload and only asserts the stream opened:
exitTimelineMode(); // -> void loadSource(...), never awaited
await flush();
expect(StubEventSource.instances.length).toBeGreaterThan(0);
That loadSource outlives the test. pumpManifestStream writes SCAN_PROGRESS.value = {...} per stream event (useManifestSource.ts:100) and clears it only in finally (line 214). The flaky test's beforeEach nulls SCAN_PROGRESS, but the leaked stream writes it non-null again — and if that lands inside advanceTimersByTimeAsync, the guard fires and no fetch happens.
Load-dependent, which is why it survives isolation and only shows under a loaded CI run.
Fix
Make exitTimelineMode's test finish what it starts — drive the stub stream to completion and await it — so no async work outlives the test. Not a retry wrapper, and not a wider timer window: both just lower the odds without removing the leak.
Worth checking the other void-dispatched loads in the file for the same shape while in there.
tests/hooks/useTimelineMode.test.ts > live poll suspends in Timeline mode > does not probe the signature endpoint while in Timeline mode, and resumes on exitfails intermittently onmain.Twice in three weeks, both on
main, both the same assertion:bb586d33, which touches noapp/orapi/file)Not reproducible on demand: 12/12 passes running the file alone, and the full suite with coverage passes 2153/2153 locally. It needs CI-level scheduling pressure.
Cause
TIMELINE_MODEnever restarts the poll timer.setupLiveUpdatesstarts one interval andtick()early-returns while Timeline is on (app/src/hooks/useManifestSource.ts:286):So the resume assertion needs a tick to land in a 1000ms window and clear all three guards.
SCAN_PROGRESSis module-level, and an earlier test in the same file leaks a load that writes it.exitTimelineMode(line 297) starts a live-HEAD reload and only asserts the stream opened:That
loadSourceoutlives the test.pumpManifestStreamwritesSCAN_PROGRESS.value = {...}per stream event (useManifestSource.ts:100) and clears it only infinally(line 214). The flaky test'sbeforeEachnullsSCAN_PROGRESS, but the leaked stream writes it non-null again — and if that lands insideadvanceTimersByTimeAsync, the guard fires and no fetch happens.Load-dependent, which is why it survives isolation and only shows under a loaded CI run.
Fix
Make
exitTimelineMode's test finish what it starts — drive the stub stream to completion and await it — so no async work outlives the test. Not a retry wrapper, and not a wider timer window: both just lower the odds without removing the leak.Worth checking the other
void-dispatched loads in the file for the same shape while in there.