Skip to content

fix: await the pairing queue focus assertion - #695

Merged
enaboapps merged 1 commit into
mainfrom
fix/pairing-focus-flake-694
Sep 8, 2026
Merged

enaboapps merged 1 commit into
mainfrom
fix/pairing-focus-flake-694

Conversation

@enaboapps

Copy link
Copy Markdown
Contributor

Closes #694.

The pairing-queue test failed intermittently on CI (Linux, full suite) while passing locally — it surfaced on the CI run for #693, a diff touching only src/settings/, which cannot affect it. The same test passed 10/10 locally in isolation on main.

Cause

The final focus assertion was not wrapped in waitFor, unlike the earlier one in the same test:

await waitFor(() => expect(dialog).toHaveFocus());          // earlier — correct
...
await waitFor(() => expect(screen.queryByRole("heading", { name: "Galaxy" })).not.toBeInTheDocument());
expect(screen.getByRole("button", { name: "Reject ... Pixel ..." })).toHaveFocus();   // raced

PairingDialog moves focus from a passive effect keyed on requests (src/App.tsx):

useEffect(() => {
  if (!actedRequest.current || requests.some((r) => r.requestId === actedRequest.current)) return;
  actedRequest.current = null;
  dialogRef.current?.querySelector<HTMLButtonElement>("button:not(:disabled)")?.focus();
}, [requests]);

The preceding waitFor only observes that the approved device's heading is gone. It does not guarantee that effect has run for the re-rendered dialog, so under CI load the assertion catches the intermediate state.

Scan for the same pattern

All 15 toHaveFocus assertions in the suite were checked:

  • Fixed (1): the assertion above — it follows an async transition.
  • Left strict (3): App.test.tsx:390, :467, :480. Each follows either a synchronous fireEvent (React flushes the effect inside act before returning) or an already-awaited findBy that resolves in the same handler that moves focus. Their focus is set before the assertion is reachable, and wrapping a deterministic assertion in waitFor would mask a real regression where focus arrives late.
  • Left unwrapped, deliberately (2): the not.toHaveFocus() assertions in settings.test.tsx. waitFor would pass immediately on a state that could still change, inverting their meaning.

Validation

Check Result
npm run lint pass
npm test ×5 pass every run — 75 tests, 4 files
cargo gates not run; test-only change, no Rust or app code touched

This is a test-only defect. The application's focus behavior is correct and unchanged.

🤖 Generated with Claude Code

@enaboapps
enaboapps force-pushed the fix/pairing-focus-flake-694 branch from f09fe39 to 3cb30ee Compare September 8, 2026 14:37
"handles simultaneous pairing requests without discarding the queue"
failed intermittently on CI while passing locally. Its final focus
assertion was not wrapped in waitFor, unlike the earlier one in the
same test.

PairingDialog moves focus from a passive effect keyed on `requests`
(src/App.tsx). The preceding waitFor only observes that the approved
device's heading is gone; it does not guarantee that effect has run for
the re-rendered dialog, so under CI load the assertion can catch the
intermediate state.

Scanned the rest of the suite for the same pattern. The three other
unwrapped positive toHaveFocus assertions follow a synchronous
fireEvent or an already-awaited findBy, so their focus is set before
the assertion is reachable; they are left strict deliberately, since
wrapping a deterministic assertion in waitFor would mask a real
regression where focus arrives late. The two not.toHaveFocus
assertions must stay unwrapped, as waitFor would pass on a state that
could still change.

Closes #694

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@enaboapps
enaboapps force-pushed the fix/pairing-focus-flake-694 branch from 3cb30ee to 60d5512 Compare September 8, 2026 14:38
@enaboapps
enaboapps merged commit ad9e03b into main Sep 8, 2026
6 checks passed
@enaboapps
enaboapps deleted the fix/pairing-focus-flake-694 branch September 8, 2026 14:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flaky test: pairing queue focus assertion is not wrapped in waitFor

2 participants