Repository navigation
test(web): settle the lazy Guidance tab inside act() in SettingsModal guidance test - #176
Merged
ChesterRa merged 2 commits intoOct 23, 2026
Merged
Conversation
… guidance test The first it.each case renders SettingsModal while the lazily imported GuidanceTab chunk is still loading. The render's act() scope exits with the Suspense boundary pending, so the chunk resolves outside act(): React logs "A suspended resource finished loading inside a test, but the event was not wrapped in act(...)" and the tab's retry render, its mount effect and its prompt load run on the Scheduler while the test polls with vi.waitFor. On a loaded runner the portaled expanded dialog is then not found within vi.waitFor's 1000 ms budget. The second case is unaffected because the lazy component is already resolved. Wait for the tab in back-to-back act() scopes instead of vi.waitFor, so an act() scope is open whenever the chunk resolves and every follow-up render and effect is flushed by act() before the click. A single act() scope around vi.waitFor would not work: act() flushes queued React work only when its outermost scope exits, so the DOM would never update while polling. Test-only change; no product code is touched.
Contributor
Author
|
CI note: on current |
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.
SettingsModal.guidance.test.tsx› "keeps expanded Guidance 0 keyboard focus and Escape in the child dialog" fails intermittently on CI withAssertionError: expected undefined to be definedat line 98 after about 1.39 s. Only case 0 fails. Case 1, the same code path, passes in about 100 ms. The failing case logs React's "A suspended resource finished loading inside a test, but the event was not wrapped in act(...)".Root cause.
SettingsModalloadsGuidanceTabwithReact.lazy. In case 0 the chunk is still loading when the render'sact()scope exits. When it resolves, noact()scope is open. React then commits the tab, runs its mount effect and its prompt load on the Scheduler, while the test polls withvi.waitFor. The test's readiness check (two textareas) passes before the tab has settled: the textareas render before the prompt load finishes, and the expand button staysdisabledwhile the load runs. Its follow-up renders also stay offact(). On a loaded runner the portaled expanded dialog is then not in the document withinvi.waitFor's 1000 ms default. Case 1 never suspends because the lazy component is already resolved.Fix (test-only). Wait for the tab in back-to-back
act()scopes instead ofvi.waitFor. Anact()scope is then open whenever the chunk resolves, and the tab's retry render, effects and prompt load are flushed byact()before the click. A singleact()aroundvi.waitFordoes not work, becauseact()flushes queued work only when its outermost scope exits. The DOM would never update while polling. Readiness now has a 4000 ms deadline followed by an exact two-textarea assertion, so a lazy-chunk failure reaches that assertion before the default 5 s test timeout.Why not a longer timeout. Raising the
vi.waitFortimeout only widens the window for Scheduler work to land. The test would still depend on wall-clock timing, would fail more slowly when it fails, and would hide that the tab mounts outsideact().Verification. The test-only red run (
39806277470, using a reference commit based on upstreammainatf1d27838) forces the lazy chunk to resolve after renderact():currentfails andfixedpasses (the Web job reports 1 failed and 2,912 passed). The exact fix headde391350e9383881fd412d6de7a0efad12248b53passed all six GitHub Actions jobs on the fork, includingrust-linux(run39820886384). The gated tests remain on the fork, not in this PR.Test environment: GitHub Actions CI on the fork (
ubuntu-latest, Node 24.19.0,npm -C web run checkandnpm -C web test).