Uh oh!
There was an error while loading. Please reload this page.
test(web): eliminate timeout flakiness in the web test suite - #1597
Conversation
cliffhall
commented
Jul 2, 2026
@claude review |
Claude finished @cliffhall's task in 2m 29s —— View job Code Review
I reviewed all 7 changed files against I have one substantive observation and a couple of minor notes. Nothing blocking. 🟡 The "cancels a pending debounce timer" test now passes trivially
awaituser.type(textInput,"h");// schedules a 300ms debounce for "text"awaituser.click(siblingInput);awaituser.click(textInput);// handleFocus clears the pending timer + fires immediatelyonCompleteArgument.mockClear();consttextCalls=onCompleteArgument.mock.calls.filter(([n])=>n==="text");expect(textCalls.length).toBe(0);In the source, the keystroke debounce calls (Note: the old assertion The deterministic way to keep this test meaningful is fake timers — advance past the debounce and assert nothing fired, no wall-clock dependence: vi.useFakeTimers();constuser=userEvent.setup({delay: null,advanceTimers: vi.advanceTimersByTime});// … type "h", click away, click back, mockClear() …awaitvi.advanceTimersByTimeAsync(400);// debounce window elapsesexpect(onCompleteArgument.mock.calls.filter(([n])=>n==="text").length).toBe(0);vi.useRealTimers();The same reasoning applies mildly to the negative assertions in "clears stale dropdown options" and "does not call onCompleteArgument when completions are unsupported" — but those genuinely test synchronous teardown / never-scheduled paths, so asserting immediately is correct and deterministic there. Only the cancellation test relies on a timer that would need to elapse. Minor notes (non-blocking)
Overall: 👍 The mechanical |
cliffhall
commented
Jul 2, 2026
@claude review |
Claude finished @cliffhall's task in 1m 16s —— View job Code Review
This review covers both commits, including ✅ Round-1 point resolved — the cancellation test is now load-bearing
✅ The remaining |
cliffhall
commented
Jul 2, 2026
📋 Smoke test & AGENTS.md audit for this PR: #1596 (comment) (posted on the linked issue #1596). |
…ase change; tree unchanged)
Uh oh!
There was an error while loading. Please reload this page.
Closes#1596
What
Deterministically fixes the recurring 5s-timeout flakes in the
clients/websuite that surfaced under v8-instrumented, concurrent load. Test-only — no product source changed. No test was skipped/disabled, no global timeout was inflated, and the per-file coverage gate (≥90 on all four dimensions) still holds for every touched file.Per-test root cause + fix
Common root cause (modals/forms/screens):
userEvent.setup()schedules a realsetTimeoutbetween keystrokes. Under CPU contention those event-loop yields balloon, so multi-field interactions accumulated past the 5s per-test timeout — exactly the "clustered at the default 5s timeout under load" symptom. Fix:userEvent.setup({ delay: null })removes the per-keystroke real-timer dependence (keystrokes dispatch synchronously), making the suites load-independent.delay: nullon everyuserEvent.setup(). The debounced validation in the import modals was already awaited viafindBy/waitFor, so it needed no change beyond fast typing.await new Promise(r => setTimeout(r, 400))), which races the debounce timer under load. Replaced every such sleep with awaited conditions (findBy/waitFor) on the real rendered outcome plusdelay: null; they now resolve as soon as the debounce fires and the response settles, and never depend on machine speed. Negative assertions (stale-option clearing, cancelled debounce) rely on the component's synchronous state/timer teardown rather than a timed window, so they're deterministic. A scoped 3swaitFortimeout (commented) covers the legitimate debounce + async settle under heavy load.getStderrLogs()synchronously right aftercallToolresolved raced the stderr chunk. Wrapped the assertion invi.waitForso it polls until the line lands.Verification
All green with zero intermittent failures:
npm run validate(web) — 191 files / 2438 tests.npm run test:coverage(web) — run 6×: 4 sequential + 2 concurrent under load (two full coverage runs in parallel, the issue's suggested load harness). Every run: 229 files / 3237 tests passed, coverage gate clean (0 threshold errors).npm run test:integration(web) standalone — 38 files / 799 tests.🤖 Generated with Claude Code
https://claude.ai/code/session_01S3fTN8H3R8YV4yUGvZjYnX