mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
fix(site): fix flaky UsageUserDrillIn story assertion (#23416)
## 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. <img width="1110" height="649" alt="image" src="https://github.com/user-attachments/assets/8b5c36c2-09c4-4dd6-a280-ab6379c1464e" /> ### 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.
This commit is contained in:
@@ -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"));
|
||||
|
||||
Reference in New Issue
Block a user