Fix flaky system suite (#265): four distinct broadcast/headless races#289
Merged
Conversation
The single-process browser suite was intermittently red (~5/8 runs) from several unrelated root causes, all surfacing as "flaky system tests": - Stale-node race (the #265 error): Capybara's synchronize retries finders within default_max_wait_time but only for driver.invalid_element_errors. A Turbo broadcast swapping a node mid-read raises Selenium UnknownError ("Node with given id does not belong to the document"), which escapes the retry loop. Teach catch_error? to treat that one message-matched error as retriable. - Empty clock spans: player-clock text was filled by clock_controller on connect, so the span was invisible until JS ran. Server-render the initial text (clock_display helper, matching the JS format) as progressive enhancement. - Native click_on "Sign In" intermittently fails to submit in this headless container, leaving the test on the home page. Add a reliable shared sign_in helper (set_field/submit_form) and route chat/fort/users through it. - Native window.confirm is auto-dismissed by headless Selenium before accept_confirm can catch it (ModalNotFound). Stub confirm to auto-accept. Also: default_max_wait_time = 5 for headroom on heavy broadcast-driven pages, and visible: :all on the two clock assertions (the invisibility is a headless-Chrome layout-deferral artifact; the DOM is correct). Verified: full system suite 10/10 consecutive green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129QgzCbBQCR9FjMf2YV5dn
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.
Closes #265.
The single-process browser suite was intermittently red (~5/8 full-suite runs). Investigation showed the "flaky system suite" was four unrelated root causes, not one — the stale-node race #265 named plus three others that surfaced only once the loudest ones were fixed.
Root causes & fixes
synchronizeretries finders withindefault_max_wait_time, but only fordriver.invalid_element_errors. A Turbo broadcast swapping a node mid-read raisesSelenium::WebDriver::Error::UnknownError("Node with given id does not belong to the document"), which escapes the retry loop and fails immediately.catch_error?to treat that one message-matched error as retriable (not allUnknownErrors — that would mask real failures)..player-clocktext was filled byclock_controlleronconnect(), so the span was empty/invisible until JS ran → strict visibility asserts raced it.clock_displayhelper, matching the JS format exactly) as progressive enhancement.click_on "Sign In"intermittently fails to submit in this headless container, stranding the test on the home page.sign_inhelper (set_field/submit_form); routechat/fort/usersthrough it (removes a duplicate local helper).window.confirmauto-dismissed by headless Selenium beforeaccept_confirmcatches it →ModalNotFound.window.confirmto auto-accept (whataccept_confirmintends, minus the flaky native dialog).Plus
Capybara.default_max_wait_time = 5for headroom on heavy broadcast-driven pages, andvisible: :allon the two clock assertions — the invisibility is a proven headless-Chrome layout-deferral artifact (the DOM is correct; a forced reflow fixes it; real browsers always paint it).Verification
Follow-up (out of scope)
Seven system-test files still carry near-identical local
sign_inhelpers; they're reliable, so left as-is. The new base helper is the seed for a later dedup.🤖 Generated with Claude Code
https://claude.ai/code/session_0129QgzCbBQCR9FjMf2YV5dn