Level up's and Start a character's content pickers empty their list during every search #1030

Closed
opened 2026-10-02 03:48:47 +00:00 by claude-bot · 1 comment
Collaborator

Seen

PR #1027 (a backend-only change to audio cutting) went red on one job, CI / End-to-end journeys (keyboard), run https://git.rhoving.com/rbrooks/Quest-Board/actions/runs/1790 :

✘ [keyboard] › e2e/j7-a-character.spec.js:440:3 › J7 a character › Priya levels up: the steps, What changes, and Reach level 2 (D210)
  Locator: getByRole('button', { name: 'Choose Sudden Charge', exact: true })
  Timeout: 10000ms
  Error: element(s) not found
  > 655 |   await expect(choose).not.toHaveAttribute("aria-disabled", "true");
      at chooseFeat (/app/e2e/j7-a-character.spec.js:655:28)

The same journey passed on desktop and phone in that run, and on keyboard in #1024, #1025 and #1026.

Cause (read from the code; not reproduced locally)

FeatPicker (pages/sheet/LevelUp.jsx) and ChooseContent (pages/sheet/StartCharacter.jsx) read their list straight from useAsync's result, which is undefined for as long as a request is in flight. So on every search, 250 ms after the last keystroke:

  1. the list empties, and the picker says and announces "Nothing matches" (role="status") until the answer arrives;
  2. every row is unmounted and then mounted again.

The journey types the feat's name, sees the row (it is already in the unfiltered list), and presses Space on it. If the debounced search starts between the row taking focus and the key going down, the row has gone, the key lands on nothing, and no card or "Choose …" button ever appears. The keyboard project is the one that depends on focus staying on the row.

AddFromContent.jsx does not have this: it keeps the last answer until the next one arrives.

Fix

Both pickers keep the last answer on screen while the next is asked for, as AddFromContent does. Rows are keyed by entry id, so a row that is in both answers is the same element and keeps its focus. A test holds a search open and checks the row is the same element, "Nothing matches" is not shown, and a key pressed on the row still works.

Being fixed in the same PR as #1029 (one CI run rather than two).

## Seen PR #1027 (a backend-only change to audio cutting) went red on one job, **CI / End-to-end journeys (keyboard)**, run https://git.rhoving.com/rbrooks/Quest-Board/actions/runs/1790 : ``` ✘ [keyboard] › e2e/j7-a-character.spec.js:440:3 › J7 a character › Priya levels up: the steps, What changes, and Reach level 2 (D210) Locator: getByRole('button', { name: 'Choose Sudden Charge', exact: true }) Timeout: 10000ms Error: element(s) not found > 655 | await expect(choose).not.toHaveAttribute("aria-disabled", "true"); at chooseFeat (/app/e2e/j7-a-character.spec.js:655:28) ``` The same journey passed on desktop and phone in that run, and on keyboard in #1024, #1025 and #1026. ## Cause (read from the code; not reproduced locally) `FeatPicker` (`pages/sheet/LevelUp.jsx`) and `ChooseContent` (`pages/sheet/StartCharacter.jsx`) read their list straight from `useAsync`'s `result`, which is `undefined` for as long as a request is in flight. So on every search, 250 ms after the last keystroke: 1. the list empties, and the picker says and announces **"Nothing matches"** (`role="status"`) until the answer arrives; 2. every row is unmounted and then mounted again. The journey types the feat's name, sees the row (it is already in the unfiltered list), and presses Space on it. If the debounced search starts between the row taking focus and the key going down, the row has gone, the key lands on nothing, and no card or "Choose …" button ever appears. The keyboard project is the one that depends on focus staying on the row. `AddFromContent.jsx` does not have this: it keeps the last answer until the next one arrives. ## Fix Both pickers keep the last answer on screen while the next is asked for, as `AddFromContent` does. Rows are keyed by entry id, so a row that is in both answers is the same element and keeps its focus. A test holds a search open and checks the row is the same element, "Nothing matches" is not shown, and a key pressed on the row still works. Being fixed in the same PR as #1029 (one CI run rather than two).
Author
Collaborator

Done in PR #1032, merged to main as 35cbc348.

Level up's feat picker (LevelUp.jsx) and Start a character's "Choose from the loaded content" (StartCharacter.jsx) keep the last answer on screen until the next arrives. Test: LevelUp.test.jsx "keeps the list it has while the next search is asked for (#1030)" holds a search open and checks the row is the same element, "Nothing matches" is not shown, and a key pressed on the row still works.

e2e/j7-a-character.spec.js on the keyboard project, three repeats in a local e2e stack: 18 passed, no retries. All three journey jobs were green in #1032's CI.

PR #1027's branch was cut before this, so its red keyboard job can still flake on a re-run; if it does, merging main into it brings this fix.

Done in PR #1032, merged to main as 35cbc348. Level up's feat picker (`LevelUp.jsx`) and Start a character's "Choose from the loaded content" (`StartCharacter.jsx`) keep the last answer on screen until the next arrives. Test: `LevelUp.test.jsx` "keeps the list it has while the next search is asked for (#1030)" holds a search open and checks the row is the same element, "Nothing matches" is not shown, and a key pressed on the row still works. `e2e/j7-a-character.spec.js` on the keyboard project, three repeats in a local e2e stack: 18 passed, no retries. All three journey jobs were green in #1032's CI. PR #1027's branch was cut before this, so its red keyboard job can still flake on a re-run; if it does, merging main into it brings this fix.
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#1030
No description provided.