test(frontend): useAuth's expiry test waits for the user, not the element (main is red) #785

Merged
claude-bot merged 3 commits from fix/useauth-test-race into main 2026-09-23 20:56:25 +00:00
Collaborator

Main is red after #783 merged: run #10357, useAuth.test.jsx, "Expected … Test User / Received: anonymous". Nothing in #783 touched auth, and the same tree had passed on #783's own PR run and inside #782's.

Cause

AuthProvider renders its children immediately, so the test's probe exists reading "anonymous" until /api/me answers. The test did:

expect(await screen.findByTestId("home-user")).toHaveTextContent("Test User");

findByTestId resolves as soon as the element exists, and then the text is asserted, which on a loaded runner is a moment before the user arrives. The test has always been a race that usually won.

Fix

It now waits for the name itself:

await waitFor(() => {
  expect(screen.getByTestId("home-user")).toHaveTextContent("Test User");
});

Five runs on a single CPU: 2/2 each.

The pattern

This is the third race of the same shape today. Each time, the test waits for the first thing on the page and asserts something that arrives later:

  1. J6's axe scan waited for the session's first request, and the failing elements came in a second one (#770).
  2. The Contents test waited for "This week" (from the URL) and asserted the GM-only Settings entry, which waits for my_role (23c82b4).
  3. This one.

expect(await findBy…(…)).toHaveTextContent(…) appears in 50 places across the suite. Most are safe: where the element only appears once its data has arrived, existing is being ready. It races only when a placeholder with the same selector renders first and its content changes later. I haven't rewritten them blind. Worth a separate audit that classifies each site.

🤖 Generated with Claude Code

**Main is red** after #783 merged: run #10357, `useAuth.test.jsx`, *"Expected … Test User / Received: anonymous"*. Nothing in #783 touched auth, and the same tree had passed on #783's own PR run and inside #782's. ## Cause `AuthProvider` renders its children immediately, so the test's probe exists reading **"anonymous"** until `/api/me` answers. The test did: ```js expect(await screen.findByTestId("home-user")).toHaveTextContent("Test User"); ``` `findByTestId` resolves as soon as the element **exists**, and then the text is asserted, which on a loaded runner is a moment before the user arrives. The test has always been a race that usually won. ## Fix It now waits for the name itself: ```js await waitFor(() => { expect(screen.getByTestId("home-user")).toHaveTextContent("Test User"); }); ``` Five runs on a single CPU: 2/2 each. ## The pattern This is the **third race of the same shape today**. Each time, the test waits for the first thing on the page and asserts something that arrives later: 1. J6's axe scan waited for the session's first request, and the failing elements came in a second one (#770). 2. The Contents test waited for "This week" (from the URL) and asserted the GM-only Settings entry, which waits for `my_role` (23c82b4). 3. This one. `expect(await findBy…(…)).toHaveTextContent(…)` appears in **50** places across the suite. Most are safe: where the element only appears once its data has arrived, existing *is* being ready. It races only when a placeholder with the same selector renders first and its content changes later. I haven't rewritten them blind. Worth a separate audit that classifies each site. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
test(frontend): useAuth's expiry test waits for the user, not the element
All checks were successful
CI / Bot/backend version sync (pull_request) Successful in 57s
CI / Backend lint (ruff) (pull_request) Successful in 1m3s
CI / Feedback site tests (pull_request) Successful in 1m20s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m45s
CI / Bot tests and audit (pull_request) Successful in 3m5s
CI / Docker image build (pull_request) Successful in 4m37s
CI / Frontend tests, audit, and build (pull_request) Successful in 7m50s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Successful in 5m31s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 15m16s
CI / Backend migration, tests, and audit (pull_request) Successful in 15m18s
8e7b0b4da1
Main went red after #783 merged (run #10357): `useAuth.test.jsx` expected
"Test User" and read "anonymous". Nothing in #783 touched auth; the same tree
had passed on two PR runs.

`AuthProvider` renders its children at once, so the probe exists reading
"anonymous" until /api/me answers. `findByTestId` resolves on existence, and
the text was then asserted a moment too early on a loaded runner. It has
always been a race that usually won.

Now it waits for the name itself. Five runs on a single CPU: 2/2 each.

This is the third race of the same shape today — wait for the first thing
on the page, assert something that arrives later — after J6's axe scan and
the Contents' Settings assertion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test(frontend): the crumb tests wait for the campaign's name (#729)
All checks were successful
CI / Bot/backend version sync (pull_request) Successful in 1m7s
CI / Backend lint (ruff) (pull_request) Successful in 1m19s
CI / Feedback site tests (pull_request) Successful in 1m46s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 2m12s
CI / Bot tests and audit (pull_request) Successful in 3m15s
CI / Docker image build (pull_request) Successful in 3m50s
CI / Frontend tests, audit, and build (pull_request) Successful in 6m30s
CI / End-to-end journeys (desktop, phone, keyboard-only) (pull_request) Successful in 4m40s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 14m23s
CI / Backend migration, tests, and audit (pull_request) Successful in 15m38s
53c8cd9ab0
Main went red again after #782 merged (run #10371), in a different test:
AppFrame.test.jsx › "gives the sessions list a page of its own", line 295.

Same shape as the useAuth fix in this PR and as 23c82b4. The test waited for
the current Contents entry — worked out from the address, there on first
paint — then read the breadcrumb's campaign link, whose name arrives with the
campaign list a request later.

Rather than fix it one red run at a time, every test in the file was checked
for an assertion on campaign data made after a wait on something
address-derived. Two race:

- "gives the sessions list a page of its own" (the one that failed)
- "marks the wiki current for everything under it" — identical shape, and
  had simply not lost yet

Both now wait through `crumbToCampaign()`, which returns the crumb once its
campaign link is there. The others were checked and are sound: "Running it",
the settings-sections tests and "keeps the sections out" all wait on a
role-gated element before asserting, so the role has arrived; the new-session,
new-campaign and edit-session tests assert only address-derived things.

Three runs of both files on a single CPU: 51/51 each.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign in to join this conversation.
No description provided.