test: de-flake medication-page ui-smoke against transient Suspense duplicate - #184
Merged
Merged
Conversation
…plicate
The "prescribing workflow uses in-app medication routes" spec intermittently
failed the Chromium ui-smoke gate with a strict-mode violation:
getByTestId('acamprosate-medication-page') resolved to 2 elements.
Root cause: the medication route renders inside GlobalMockupSearchShell, whose
Suspense fallback renders `props.children` and whose resolved client subtree
also renders `children`. During a navigation/hydration overlap (the mockup->
redirect hard navigation) both <main data-testid="acamprosate-medication-page">
copies briefly coexist. Rendering children in the fallback is an intentional
SSR pattern (content visible while useSearchParams suspends), so the app is
correct in every browser — this is purely a too-strict test locator catching a
transient DOM overlap.
Fix: wait for the testid to settle to exactly one instance before asserting
visibility (new expectSingleMedicationPage helper). toHaveCount(1) retries
through the transition yet still fails on a genuine permanent double-render, so
it does not mask a real regression.
Follow-up (not done here): hoisting `children` out of the Suspense boundary so
it renders exactly once would remove the duplicate at the source, but that is a
broader shell refactor with SSR implications.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>Uh oh!
There was an error while loading. Please reload this page.
10 tasks
BigSimmo added a commit
that referenced
this pull request
Jul 31, 2026
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 freeto 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.
Summary
The required ui-smoke gate intermittently fails the "prescribing workflow uses in-app medication routes" spec with a Playwright strict-mode violation —
getByTestId('acamprosate-medication-page')resolves to 2 elements. This flake blocked #176 (an unrelated eval PR) until a manual re-run.Root cause
The medication route renders inside
GlobalMockupSearchShell, whose<Suspense>fallback rendersprops.childrenand whose resolved client subtree also renderschildren. During the mockup→redirect hard navigation, both<main data-testid="acamprosate-medication-page">copies briefly coexist in the DOM. Rendering children in the fallback is an intentional SSR pattern (content visible whileuseSearchParamssuspends), so the app renders correctly in every browser — this is purely a too-strict test locator catching a transient overlap.Fix
Wait for the testid to settle to exactly one instance before asserting visibility (
expectSingleMedicationPagehelper).toHaveCount(1)retries through the transition but still fails on a genuine permanent double-render, so it does not mask a real regression. Follows the same philosophy as #178.Verification
prettier --check,eslint,tsc --noEmitall clean on the changed file.Follow-up (not in this PR)
Hoisting
childrenout of the Suspense boundary so it renders exactly once would remove the duplicate at the source, but that is a broader shell refactor with SSR implications for everyGlobalSearchShellroute.🤖 Generated with Claude Code