From e2007c5e2fcdc88bdabab7ccff1ea86e4ee057c8 Mon Sep 17 00:00:00 2001 From: iamtoruk Date: Tue, 18 Aug 2026 02:10:24 -0700 Subject: [PATCH] test(dashboard): wait for the Optimize scan on real event-loop turns, not fake-timer hops The Optimize scan does real fs I/O (readdir/stat) that only resolves on a real event-loop turn, but the wait loop counted 20 vi.advanceTimersByTimeAsync hops under full fake timers, which flush fake timers + microtasks but never give real I/O a chance to complete. Under load that read a stale "Scanning Today..." frame. Scope fake timers to just what the 60s auto-refresh interval needs, leave setImmediate/Date real, and wait on a real wall-clock deadline instead of a fixed hop count. --- tests/dashboard.test.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/dashboard.test.ts b/tests/dashboard.test.ts index 9879c8a1..76107e6b 100644 --- a/tests/dashboard.test.ts +++ b/tests/dashboard.test.ts @@ -665,7 +665,12 @@ describe('InteractiveDashboard refresh', () => { }) it('keeps Optimize mounted without a loading frame when auto-refresh fires', async () => { - vi.useFakeTimers() + // The Optimize scan (`o`) does real fs I/O (readdir/stat) that only + // resolves on a real event-loop turn. Leave setImmediate/nextTick/Date + // real (Date stays real so the wait loop below can use a genuine + // wall-clock deadline) and fake only what the 60s auto-refresh + // interval needs. + vi.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout', 'setInterval', 'clearInterval'] }) const stdin = new PassThrough() as PassThrough & NodeJS.ReadStream const stdout = new PassThrough() as PassThrough & NodeJS.WriteStream stdin.isTTY = true @@ -712,7 +717,15 @@ describe('InteractiveDashboard refresh', () => { expect(activityHeader.indexOf('turns') + 'turns'.length).toBe(activityRow.indexOf('12') + '12'.length) expect(activityHeader.indexOf('1-shot') + '1-shot'.length).toBe(activityRow.indexOf('50%') + '50%'.length) stdin.write('o') - for (let i = 0; i < 20 && !frames.some(frame => frame.includes('Token estimates are approximate.')); i++) { + // The scan does real fs work, so wait on real event-loop turns + // (setImmediate is left un-faked above) rather than counting fake-timer + // hops, bounded by a real wall-clock deadline. + const realDeadline = Date.now() + 10_000 + while (!frames.some(frame => frame.includes('Token estimates are approximate.'))) { + if (Date.now() > realDeadline) { + throw new Error('Timed out waiting for the Optimize scan to render "Token estimates are approximate."') + } + await new Promise(resolve => setImmediate(resolve)) await vi.advanceTimersByTimeAsync(50) } const beforeRefresh = frames.filter(frame => frame.trim()).at(-1) ?? '' @@ -731,5 +744,5 @@ describe('InteractiveDashboard refresh', () => { expect(frame).not.toContain('Loading Today') expect(frame).not.toContain('Scanning Today') - }) + }, 30_000) })