fix(e2e): eliminate publishers-tab render race via BeforeAll + Eventually (bookshelf-5kje) #903
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "bd-bookshelf-5kje"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Describe("after clicking the Publishers tab", Ordered, ...)usedJustBeforeEachwhich runs before eachIt. With 2 Its, the full navigate→waitStable→waitController→click sequence ran TWICE. On the second re-navigation, a brief paint window exists betweenwaitForStimulusController('sub-tab')returning and the publishers button being render-stable in Chromium under CI load.MustElementpolled for 60s and panicked with "context deadline exceeded".JustBeforeEach→BeforeAll: navigate once and click once for both Its. The tab-click state persists across the Ordered Its — no repeated re-render.MustElement(...).MustClick()→Eventuallywait for button +MustElement(...).MustClick(): tolerates any residual render delay deterministically without panicking.page = refreshPageTimeout(page)at the start of each innerIt(go-rod Ordered gotcha: absolute deadline must be reset per step when reusing a page).Test plan
e2e-policy-checkpasses (all top-level Describes remain Ordered — verified locally)go build -tags e2e ./e2e/browser/...compiles cleanlyCloses bead bookshelf-5kje on merge.
Recompute Match Score — kebab open screenshot (recompute-match-score-kebab-open)
Workflow Detail page screenshot (wf-detail-older-execution)
Older completed ContinueAsNew epoch detail — execution ID and state visible, Cancel absent.
Code Review — bookshelf-5kje (PR #903)
Diff reviewed:
origin/main...origin/bd-bookshelf-5kje(head79a190014265)File:
e2e/browser/journey_library_stats_test.goPhase 0 — DEMO
This is a test-only flake-fix PR. No runnable DEMO block applies (the "demo" is CI green, confirmed). Proceeding to content review.
Findings
Semantic correctness of JustBeforeEach → BeforeAll
The old
JustBeforeEachran navigate+click before each of the two innerItsteps — twice total. BothItassertions (Publishers panel is visibleandAuthors panel is now hidden) were asserting the same post-click state both times, so the second navigate+click was purely redundant and introduced the re-navigation timing window this PR fixes. The newBeforeAllruns the sequence once; in GinkgoOrdered, state persists acrossItsteps, so both Its observe the correct shared post-click state. No assertion was testing a pre-click/default state thatBeforeAllwould now break. Coverage and test meaning are fully preserved.Both assertions remain distinct and meaningful
Publishers panel is visibleandAuthors panel is now hiddenare two independent behavioral observations of the same SubTabController tab-switch: one panel becomes shown, the other becomes hidden. Both remain real, non-vacuous assertions against the shared post-click state. Neither is made redundant by the structural change.Root cause addressed, not just timeout widened
The race was: second navigate in the old
JustBeforeEachhit a brief window betweenwaitForStimulusControllerreturning and the publishers button being paint-stable, causingMustElementto panic. Moving toBeforeAlleliminates the second navigate+click entirely — a root fix. The addedEventuallybeforeMustClickis belt-and-suspenders for render-readiness on even the single run and correctly waits for the exact element the subsequent click targets ([data-sub-tab-panel-param='publishers']).go-rod gotcha: per-It
refreshPageTimeoutplacementCLAUDE.md requires
Orderedjourneys reusing apageto resetpage.Timeoutat the start of eachIt. The fix addspage = refreshPageTimeout(page)as the first line of both innerItblocks (:225and:242). Correct and consistent with the pattern across the entire browser suite.Eventuallytimeout budget30s/100ms for the button-existence poll is consistent with existing usage across the browser suite. The
refreshPageTimeoutimmediately before grants a fresh 60s page-level deadline, so the poll can consume up to 30s and the subsequentMustClickstill has ≥30s of margin. Correct.No sibling tab-interaction specs with the same unaddressed race
No other nested
Describein this file uses a per-It JustBeforeEach navigate+click pattern. The outerItsteps poll already-rendered page state without re-navigating. No residual instances of the same bug pattern.E2E journey policy
Top-level
DescribeisOrdered— complies with the anti-regrowth guard. Package isbrowser_test. Build tag//go:build e2epresent. Justification comment at top of file explains why real Chromium is required. All conformant.[MINOR] e2e/browser/journey_library_stats_test.go:215-219 — TOCTOU double-lookup between Eventually and MustClick
Eventuallypolls until the element exists, thenMustElementre-queries the DOM to get a handle forMustClick. In theory the element could briefly disappear between the two calls; in practice this button is server-rendered and static, so the window is essentially zero. Noting for awareness only; no correctness risk in this context.REVIEW VERDICT: 0 blocker, 0 major, 1 minor