test(browser): retry lost popover clicks and raise the per-test timeout - #75
Merged
Conversation
…povers The tests waited only for ANY button in the popover, so on a slow runner the click could hit the stale pre-filter option list (or a remounting node) — picking the wrong author / losing the click, then timing out on the save-button wait. Wait until the first option shows the filtered text instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013zh1EN87d1Q7urtu7sDRYG
Filtered-option waits didn't fix CI: the click can land on an option node mid-remount (debounced fetch re-renders the list) and get silently lost. clickUntil re-clicks until the expected outcome materializes, checking the condition first so a registered click is never repeated (no multi-select toggle-off). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013zh1EN87d1Q7urtu7sDRYG
The browser suite drives a real browser through agent-browser, and clickUntil retries a lost popover click up to 3 times with a 3s settle each — a budget of up to 12s for one test. bun's per-test timeout is 5s, so the second retry can never finish: bun kills the test mid-attempt and the assertion reports whatever slice of its own budget was left. That is the "waitFor timed out after 3183ms" in CI, where the runner shares a container with postgres, an S3 stand-in and the Contember engine and the first settle actually elapses. Locally the first click lands immediately, so the suite passes and the ceiling is never reached. bunfig.toml already declares timeout = 15000, but bun ignores that key — verified with a 6s test, killed at 5002ms regardless. Documented there so the next person does not trust it, and the browser script now passes --timeout on the command line, which does work. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GiniFfaE4gb5EuQpQ3Ncee
The workflow installed the browser driver with a bare `bun add -g agent-browser`, so it could change under the suite between two runs of the same commit — and it did: 0.31.1 in early July, 0.32.x from mid-July, 0.34.0 since 2026-08-10. CI last went green on 2026-07-22 with the clickUntil retry helper and 0.32.4. The same helper against 0.34.0 still fails `Article with Author Select`, so the driver version is load-bearing for that test. Locally the suite passes on 0.27.1, 0.32.4 and 0.34.0 alike, which is why this only ever showed up in CI. Pinning makes the suite reproducible. Moving the pin forward is then a deliberate change with its own CI evidence, rather than something that happens silently. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GiniFfaE4gb5EuQpQ3Ncee
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Makes the
Browser Testsjob green again — all three CI checks pass on this branch. Two test-only commits cherry-picked fromexperiment/selection-compiler(PR #69) with their original authorship — they will drop out of that branch on its next rebase — plus a timeout fix that turned out to be the actual root cause.The failure
Since 2026-07-22 the same two tests have failed in CI on every branch, including
main. Both drive a popover: open, type to filter, click the first option.What it is not
agent-browserupgrade, which was the first hypothesis and looked damning: CI installs it with a barebun add -g agent-browser, which went 0.31.1 → 0.32.x right around the date the failures start. But on a pristinemainlocally both tests pass on 0.27.1 and 0.34.0 alike, and the full suite is 66/66. Pinning would have fixed nothing.The actual root cause
bunfig.tomldeclarestimeout = 15000, and bun ignores that key. Verified directly: a test that sleeps 6s is killed at 5002ms regardless of the value. So the per-test timeout is bun's 5000ms default.clickUntilretries a lost click up to 3 times with a 3s settle each — a budget of up to 12s for one test. It therefore cannot complete a second retry inside a 5s test: bun kills it mid-attempt, and the assertion reports whatever slice of its own budget was left. That is exactly the CI log's— a
waitForthat asked for 10s and got 3.2s, inside a test that had already spent its ceiling retrying.Locally the first click lands immediately, so the retry budget is never spent and the ceiling is never reached. That is why this reproduced only on a loaded CI runner, where the browser suite shares a container with postgres, an S3 stand-in and the Contember engine.
The fix
clickUntilhelper intests/browser/browser.ts— retries the click until an observable effect appears;--timeout 30000on thetest:browserscript, so the retry budget fits, with a note inbunfig.tomlrecording that itstimeoutkey is inert so the next person does not trust it;agent-browserto 0.32.4 in the workflow.No assertion is weakened; the tests still fail if the app stops working.
On the pin — a correction
An earlier revision of this description argued that pinning would be "cargo-culting a fix for a disproven cause", because locally the suite passes on 0.27.1, 0.32.4 and 0.34.0 alike. That conclusion was drawn from the one environment that cannot discriminate.
The CI record can: it went green on 2026-07-22 with clickUntil and 0.32.4, and
Article with Author Selectstill failed with clickUntil against 0.34.0 — twice, plus once more after the timeout fix. So the driver version is load-bearing for that test, and the barebun add -g agent-browsermeant it could change under the suite between two runs of the same commit (0.31.1 early July → 0.32.x mid-July → 0.34.0 since 2026-08-10).Moving the pin forward is now a deliberate change that has to carry its own CI evidence.
Verification
Locally 66/66. On CI: 66/66, all three checks green — which is the only place this ever reproduced. Progression across runs on this branch: 64 pass / 2 fail → 65 / 1 (clickUntil + timeout) → 66 / 0 (pin).
Note the other half of what was blocking a green suite is a genuine product bug, fixed separately in #76: an embedded has-many was not materialized before
isDirtywas read or a mutation applied, which is whypackages/bindx-form/tests/formRelations.test.tsxwas failing onmain.Follow-up worth a separate issue
bun add -g agent-browseris unpinned, so the browser driver can change under the suite between two runs of the same commit. A reproducibility problem regardless of this bug, and not bundled here.🤖 Generated with Claude Code
https://claude.ai/code/session_01GiniFfaE4gb5EuQpQ3Ncee