Flaky test: AppFrame "choosing a rule opens it in place" does not find its dialog under load #1080

Closed
opened 2026-10-04 15:27:29 +00:00 by claude-bot · 1 comment
Collaborator

Seen once, on PR #1078's CI (run 11969, 3fc0c32a, Frontend shard 1/2). That PR changes no frontend code except Map.test.jsx, and the same test passed on the run before it (6d03120b) with an identical frontend.

What failed

src/shell/AppFrame.test.jsx, "the search box and the page of results > choosing a rule opens it in place, and Escape gives focus back to its row", at line 935:

TestingLibraryElementError: Unable to find role="dialog" and name "Tidal Surge"

The shard was slow: Duration 994.19s, 1 failed | 2204 passed.

Likely cause (not confirmed)

The test finds the result row, calls row.focus(), then presses Enter:

const row = await within(await panel()).findByRole("button", { name: /Tidal Surge/ });
row.focus();
await user.keyboard("{Enter}");
const preview = await screen.findByRole("dialog", { name: "Tidal Surge" });

Two candidates:

  • The row is replaced between the find and the key press. If the panel renders its results again (a late response, or the debounce settling), the focused node is detached and Enter goes nowhere. This is the same shape as the two flakes fixed in #1036 and #1039.
  • The default 1,000 ms of findByRole is too short on a loaded runner.

Intended approach

  • Reproduce by running the file in a loop under CPU load.
  • If it is the detached row: wait for the panel to settle before focusing, or re-find the row and press it in one step (user.click, or user.type(row, "{Enter}") after a waitFor that the row is the one in the document).
  • If it is only the timeout: say so, and raise it for this assertion alone.
  • Check the neighbouring tests in the same describe for the same pattern.
Seen once, on PR #1078's CI (run 11969, `3fc0c32a`, Frontend shard 1/2). That PR changes no frontend code except `Map.test.jsx`, and the same test passed on the run before it (`6d03120b`) with an identical frontend. ## What failed `src/shell/AppFrame.test.jsx`, "the search box and the page of results > choosing a rule opens it in place, and Escape gives focus back to its row", at line 935: ``` TestingLibraryElementError: Unable to find role="dialog" and name "Tidal Surge" ``` The shard was slow: `Duration 994.19s`, `1 failed | 2204 passed`. ## Likely cause (not confirmed) The test finds the result row, calls `row.focus()`, then presses Enter: ```js const row = await within(await panel()).findByRole("button", { name: /Tidal Surge/ }); row.focus(); await user.keyboard("{Enter}"); const preview = await screen.findByRole("dialog", { name: "Tidal Surge" }); ``` Two candidates: - **The row is replaced between the find and the key press.** If the panel renders its results again (a late response, or the debounce settling), the focused node is detached and Enter goes nowhere. This is the same shape as the two flakes fixed in #1036 and #1039. - **The default 1,000 ms of `findByRole` is too short** on a loaded runner. ## Intended approach - Reproduce by running the file in a loop under CPU load. - If it is the detached row: wait for the panel to settle before focusing, or re-find the row and press it in one step (`user.click`, or `user.type(row, "{Enter}")` after a `waitFor` that the row is the one in the document). - If it is only the timeout: say so, and raise it for this assertion alone. - Check the neighbouring tests in the same `describe` for the same pattern.
Author
Collaborator

Fixed in PR #1084, merged to main. CI was green on the PR's head.

  • Cause: the rule preview is loaded lazily and this test is the first to open one, so on a loaded machine the first load outlasted findByRole's 1,000 ms. The result row is not replaced; a person cannot hit this.
  • Fix: a beforeAll in that describe imports the preview module, outside any test's time limit. No timeout raised, no component changed.
  • Evidence (one test, a fresh process per run, on the dev host): with no added load, 1 of 12 failed before and 0 of 12 after.

What it does not fix: under heavy added load the test can still exceed its own 15 s limit (6 of 12 and 8 of 15 in the loaded runs). That is an overloaded host, not this race. If it shows up in CI, the shard's load is the thing to look at.

**Fixed in PR #1084, merged to main. CI was green on the PR's head.** - **Cause:** the rule preview is loaded lazily and this test is the first to open one, so on a loaded machine the first load outlasted `findByRole`'s 1,000 ms. The result row is not replaced; a person cannot hit this. - **Fix:** a `beforeAll` in that `describe` imports the preview module, outside any test's time limit. No timeout raised, no component changed. - **Evidence** (one test, a fresh process per run, on the dev host): with no added load, 1 of 12 failed before and 0 of 12 after. **What it does not fix:** under heavy added load the test can still exceed its own 15 s limit (6 of 12 and 8 of 15 in the loaded runs). That is an overloaded host, not this race. If it shows up in CI, the shard's load is the thing to look at.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/Quest-Board#1080
No description provided.