From 69d430f51bc64bf29ebe631dd3a369c13b877855 Mon Sep 17 00:00:00 2001 From: Ethan <39577870+ethanndickson@users.noreply.github.com> Date: Mon, 23 Mar 2026 19:45:30 +1100 Subject: [PATCH] fix(site): fix flaky UsageUserDrillIn story assertion (#23416) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem The `UsageUserDrillIn` play function in `AgentSettingsPageView.stories.tsx` flakes in Chromatic (noticed in #23282). After clicking a user row to drill into the detail view, sync assertions fire before React finishes the state transition — element not found. image ### Root cause The play function clicks "Alice Liddell" and then waits with `findByText("Alice Liddell")` before asserting on detail-view content. But "Alice Liddell" appears in **both** the list row and the detail header, so `findByText` resolves immediately against the stale list-row text that is still in the DOM. The same is true for `"@alice"` — `UserRow` renders `@${user.username}` as a subtitle in the list, and `AvatarData` renders it again in the detail view. ### Fix Gate on `"User ID: ..."` instead — text that **only** renders in the detail panel. Once it is in the DOM, the detail view is fully mounted and all sync assertions are safe. Applied to both `UsageUserDrillIn` and `UsageUserDrillInAndBack`, which had the same issue. --- .../AgentSettingsPageView.stories.tsx | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/site/src/pages/AgentsPage/AgentSettingsPageView.stories.tsx b/site/src/pages/AgentsPage/AgentSettingsPageView.stories.tsx index 497a02961d..1c33dd1a84 100644 --- a/site/src/pages/AgentsPage/AgentSettingsPageView.stories.tsx +++ b/site/src/pages/AgentsPage/AgentSettingsPageView.stories.tsx @@ -484,20 +484,15 @@ export const UsageUserDrillIn: Story = { play: async ({ canvasElement }) => { const body = within(canvasElement.ownerDocument.body); - // Wait for the user list to load. + // Click Alice's row to drill into the detail view. await userEvent.click(await body.findByText("Alice Liddell")); - // The detail view should show the user header with name - // and username subtitle. - await expect(await body.findByText("Alice Liddell")).toBeInTheDocument(); - await expect(body.getByText("@alice")).toBeInTheDocument(); + // Wait for the detail view to mount. "User ID:" only + // renders in the detail panel, not the list. + await body.findByText(`User ID: ${mockUserProfile.id}`); - // The user profile was pre-seeded in the query cache via - // parameters.queries, so the detail header should show the - // user ID from that data. - await expect( - body.getByText(`User ID: ${mockUserProfile.id}`), - ).toBeInTheDocument(); + await expect(body.getByText("Alice Liddell")).toBeInTheDocument(); + await expect(body.getByText("@alice")).toBeInTheDocument(); // The cost summary should have been fetched. await waitFor(() => { @@ -523,11 +518,12 @@ export const UsageUserDrillInAndBack: Story = { play: async ({ canvasElement }) => { const body = within(canvasElement.ownerDocument.body); - // Click Alice's row to drill in. + // Click Alice's row to drill into the detail view. await userEvent.click(await body.findByText("Alice Liddell")); - // Wait for the detail view to appear. - await body.findByText("@alice"); + // Wait for the detail view to mount. "User ID:" only + // renders in the detail panel, not the list. + await body.findByText(`User ID: ${mockUserProfile.id}`); // Click Back to return to the list. await userEvent.click(body.getByText("Back"));