Skip to content

Fixes #32968: focus the entity-type trigger before opening its listbox - #32969

Queued
ShaileshParmar11 wants to merge 1 commit into
mainfrom
fix/test-library-entity-type-select-flake
Queued

Fixes #32968: focus the entity-type trigger before opening its listbox#32969
ShaileshParmar11 wants to merge 1 commit into
mainfrom
fix/test-library-entity-type-select-flake

Conversation

@ShaileshParmar11

Copy link
Copy Markdown
Contributor

Describe your changes:

Fixes #32968

TestLibrary.spec.ts has been ejecting PRs from the merge queue via playwright-summary — most recently #32524 (run, shard chromium-07), a PR that touches nothing in this path. Two tests fail on the same line, clicking the TABLE option in the entity-type dropdown.

Root cause. The listbox dismisses itself ~160 ms after it opens, deterministically — no CI load required:

295ms  focusin   button#root/entityType   ← the click
306ms  listbox+                           ← options appear
421ms  focusout  div{listbox}
426ms  listbox-                           ← destroyed, and nothing reopens it

React Aria's listbox is a non-modal popover. A press on a trigger that does not already hold focus both opens it and produces a focus transition, and that transition dismisses it a frame later. The trigger and form nodes are not remounted, so this is not an RJSF re-render; it is also unrelated to the doc panel (forcing every programmatic scroll instant changes nothing, and the teardown is identical with no fields filled).

Measured, 3/3 runs each:

Gesture Listbox
locator.click() on an unfocused trigger closes after ~160 ms
focus() + assert focused + click() stays open
raw mouse.click() on an unfocused trigger closes at ~0 ms
focus() + Enter stays open

So the four cold-click sites have always had a ~160 ms window. A dev machine wins that race; a loaded 2-core runner does not — and since nothing reopens the listbox, option.click() retries until the test timeout.

The change. Four sites opened the Select on an unfocused trigger (:156, :375, :876, :1219); a fifth (:635-650) already focused first and passed in the same CI run that failed the other two. All five collapse into one selectEntityType helper built on that working sequence — net +27 / −42.

Type of change:

  • Bug fix

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR is adequately covered with tests

Manual test steps / verification:

Page-side CPU throttling does not reproduce this, because CI's lag is on the driver side. Injecting a delay between the trigger press and the option click reproduces it exactly:

Injected driver lag Before Signature
100 ms 2/2 fail element is not stable + element was detached from the DOM — CI's exact first-attempt text
140 / 170 / 220 / 400 ms fail waiting for getByRole('option', …)

With the trigger focused first, the same scenario passes at 400 ms and at 1500 ms of injected lag — 10× the window.

Running the spec at 4 workers against a local stack:

Run Result
origin/main unmodified 2 failed, 13 passed — incl. should maintain page on edit and reset to first page on delete, one of the two CI failures
this branch 1 failed, 14 passed — only a platform badges failure that also fails on unmodified origin/main and is unrelated

The two CI-affected tests, --repeat-each=3 --workers=4 on this branch: 6/6 passed.

Lint and types: the CI ui-checkstyle playwright sequence (organize-imports → eslint --fix → prettier) is clean and idempotent on the changed file, and tsc --project playwright/tsconfig.json reports 0 errors in it (165 pre-existing elsewhere in the project, untouched).

Note for reviewers — possible product bug

With a human-speed press (60 ms hold) rather than Playwright's instantaneous down/up, the listbox closed at ~0 ms on both the first and second click, 3/3. If that holds for real hardware input, the entity-type dropdown does not open on a normal mouse click and the real fix belongs in the ui-core-components Select. I did not confirm this by hand and CDP-injected press-and-hold may not match real input, so it is captured as a note in #32968 rather than a claim — but there are 118 getByRole('option') call sites across 38 spec files sitting on the same behaviour, so it is worth someone clicking it.

🤖 Generated with Claude Code

React Aria's listbox is a non-modal popover, and a press on a trigger that
does not already hold focus both opens it and dismisses it a frame later via
the focus transition that same press produces. That left the four cold-click
call sites roughly 160ms to pick an option, with nothing to reopen the listbox
afterwards, so a loaded runner that missed the window retried the option click
until the test timed out and ejected the PR from the merge queue.

Collapse all five entity-type selections into one selectEntityType helper built
on the focus-first sequence the site at :635 already used and which passed in
the same CI run that failed the other two.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 8, 2026 15:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

✅ PR checks passed

The linked issue has a description and all required Shipping project fields set. Thanks!

@github-actions github-actions Bot added safe to test Add this label to run secure Github workflows on PRs UI UI specific issues labels Sep 8, 2026
@gitar-bot

gitar-bot Bot commented Sep 8, 2026

Copy link
Copy Markdown
Code Review ✅ Approved

Fixes a race condition in TestLibrary.spec.ts where the entity-type dropdown listbox dismisses itself ~160 ms after opening when clicked on an unfocused trigger. Consolidates four separate click sites into a single selectEntityType helper that focuses the trigger before opening the listbox, resolving the flaky test failures (−42 lines, +27 lines net). Verified to pass the two previously failing tests at 6/6 with --repeat-each=3 --workers=4.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

✅ Playwright Results — workflow succeeded

Validated commit 2194667887e2c57a4df1e503b61a7cd09a89a15f in Playwright run 34244477822, attempt 1.

✅ 61 passed · ❌ 0 failed · 🟡 0 flaky · ⏭️ 0 skipped · 🧰 0 lifecycle flaky

Performance

Blocking targets: ✅ met · Optimization targets: 🟡 in progress

Shard-job maxima below are not the full workflow wall time; the linked run includes build, fixture, planning, and reporting.

🕒 Full workflow signal wall (to summary) 35m 51s

⏱️ Max setup 3m 19s · max shard execution 6m 49s · max shard-job elapsed before upload 11m 1s · reporting 2s

🌐 140.15 requests/attempt · 1.46 app boots/UI scenario · 0.00% common-shard skew

Optimization targets still in progress:

  • Application boot ratio was 1.46 per UI scenario (92 boots / 63 scenarios; convergence target: at most 1).
Shard Passed Failed Flaky Skipped Lifecycle failed Lifecycle flaky
✅ Shard chromium-01 61 0 0 0 0 0

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

@ShaileshParmar11
ShaileshParmar11 added this pull request to the merge queue Sep 8, 2026
Any commits made after this event will not be merged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to test Add this label to run secure Github workflows on PRs UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Playwright: TestLibrary entity-type Select self-dismisses ~160ms after a cold click, ejecting PRs from the merge queue

3 participants