Skip to content

test(query-devtools/Devtools): add tests for query list rendering, filtering, and status indicators#10684

Merged
sukvvon merged 4 commits into
mainfrom
test/query-devtools-devtools-query-list
May 10, 2026
Merged

test(query-devtools/Devtools): add tests for query list rendering, filtering, and status indicators#10684
sukvvon merged 4 commits into
mainfrom
test/query-devtools-devtools-query-list

Conversation

@sukvvon
Copy link
Copy Markdown
Collaborator

@sukvvon sukvvon commented May 10, 2026

🎯 Changes

Add tests for the query/mutation list visualization on the Devtools body component.

query list — query rendering, reactivity, filtering, and clear cache:

  • Renders a row for each query in the cache.
  • Reflects newly added queries reactively.
  • Filters queries by queryHash via the filter input.
  • Clears all queries when the clear cache button is clicked.
  • Dispatches a 'CLEAR_MUTATION_CACHE' event when clear cache is clicked in mutations view.

view toggle — switching between queries and mutations views:

  • Switches to mutations view when the mutations toggle is clicked.
  • Renders mutations in the mutations view.

status indicators — labels and badges that summarize cache state:

  • Marks a disabled query in the row label.
  • Renders status count badges (Fresh, Stale, Fetching, Paused, Inactive).
  • Reflects the inactive count when a query is added without observers.
  • Shows/hides the tooltip on hover and focus when the panel is narrow.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with `pnpm run test:pr`.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 10, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds Vitest fake timers in setup and restores real timers in teardown; expands Devtools.test.tsx with tests for query-list rendering/filtering/reactive updates and cache clearing (including CLEAR_MUTATION_CACHE), view toggle to Mutations and mutation submission entries, disabled-query labeling, status-count badges with live Inactive updates, and status-tooltip interactions.

Changes

Devtools Component Tests

Layer / File(s) Summary
Test Setup / Teardown
packages/query-devtools/src/__tests__/Devtools.test.tsx
Enables Vitest fake timers in beforeEach and restores real timers in afterEach.
Query List Functionality
packages/query-devtools/src/__tests__/Devtools.test.tsx
Tests verify rendering of query rows per cached query, reactive updates when new queries are added, filtering by the "Filter queries by query key" input, clearing query cache removes rows, and clearing from the mutations view dispatches CLEAR_MUTATION_CACHE.
View Toggle and Mutations
packages/query-devtools/src/__tests__/Devtools.test.tsx
Tests verify clicking "Mutations" switches the UI view and that submitted mutations are rendered with "Mutation submitted at …" entries after execution.
Query Properties
packages/query-devtools/src/__tests__/Devtools.test.tsx
Tests verify disabled queries are correctly marked in the rendered row label.
Status Displays
packages/query-devtools/src/__tests__/Devtools.test.tsx
Tests verify status-count badges render for Fresh, Stale, Fetching, Paused, and Inactive, and that the Inactive count updates when adding a query without observers.
Status Tooltip Interactions
packages/query-devtools/src/__tests__/Devtools/test.tsx
Tests cover tooltip show/hide behavior on mouse enter/leave and focus/blur when labels are hidden.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • TanStack/query#10671: Both PRs add tests around query status labeling/behavior in the devtools (one UI tests, the other unit-tests getQueryStatusLabel).

Poem

🐰 I hopped through tests with nimble feet,
Rows and badges shining neat,
Mutations tick and tooltips glow,
Devtools watch the queries grow,
Carrots of coverage, crisp and sweet!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding tests for query list rendering, filtering, and status indicators in the Devtools component.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description includes all required sections from the template: a detailed 🎯 Changes section explaining the test additions, a completed ✅ Checklist with steps verified, and a 🚀 Release Impact section correctly marking this as dev-only.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/query-devtools-devtools-query-list

Comment @coderabbitai help to get the list of available commands and usage tips.

@sukvvon sukvvon self-assigned this May 10, 2026
@nx-cloud
Copy link
Copy Markdown

nx-cloud Bot commented May 10, 2026

View your CI Pipeline Execution ↗ for commit 1b7f55e

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 3m 26s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded <1s View ↗

☁️ Nx Cloud last updated this comment at 2026-05-10 15:28:59 UTC

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 10, 2026

🚀 Changeset Version Preview

No changeset entries found. Merging this PR will not cause a version bump for any packages.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 10, 2026

More templates

@tanstack/angular-query-experimental

npm i https://pkg.pr.new/@tanstack/angular-query-experimental@10684

@tanstack/eslint-plugin-query

npm i https://pkg.pr.new/@tanstack/eslint-plugin-query@10684

@tanstack/lit-query

npm i https://pkg.pr.new/@tanstack/lit-query@10684

@tanstack/preact-query

npm i https://pkg.pr.new/@tanstack/preact-query@10684

@tanstack/preact-query-devtools

npm i https://pkg.pr.new/@tanstack/preact-query-devtools@10684

@tanstack/preact-query-persist-client

npm i https://pkg.pr.new/@tanstack/preact-query-persist-client@10684

@tanstack/query-async-storage-persister

npm i https://pkg.pr.new/@tanstack/query-async-storage-persister@10684

@tanstack/query-broadcast-client-experimental

npm i https://pkg.pr.new/@tanstack/query-broadcast-client-experimental@10684

@tanstack/query-core

npm i https://pkg.pr.new/@tanstack/query-core@10684

@tanstack/query-devtools

npm i https://pkg.pr.new/@tanstack/query-devtools@10684

@tanstack/query-persist-client-core

npm i https://pkg.pr.new/@tanstack/query-persist-client-core@10684

@tanstack/query-sync-storage-persister

npm i https://pkg.pr.new/@tanstack/query-sync-storage-persister@10684

@tanstack/react-query

npm i https://pkg.pr.new/@tanstack/react-query@10684

@tanstack/react-query-devtools

npm i https://pkg.pr.new/@tanstack/react-query-devtools@10684

@tanstack/react-query-next-experimental

npm i https://pkg.pr.new/@tanstack/react-query-next-experimental@10684

@tanstack/react-query-persist-client

npm i https://pkg.pr.new/@tanstack/react-query-persist-client@10684

@tanstack/solid-query

npm i https://pkg.pr.new/@tanstack/solid-query@10684

@tanstack/solid-query-devtools

npm i https://pkg.pr.new/@tanstack/solid-query-devtools@10684

@tanstack/solid-query-persist-client

npm i https://pkg.pr.new/@tanstack/solid-query-persist-client@10684

@tanstack/svelte-query

npm i https://pkg.pr.new/@tanstack/svelte-query@10684

@tanstack/svelte-query-devtools

npm i https://pkg.pr.new/@tanstack/svelte-query-devtools@10684

@tanstack/svelte-query-persist-client

npm i https://pkg.pr.new/@tanstack/svelte-query-persist-client@10684

@tanstack/vue-query

npm i https://pkg.pr.new/@tanstack/vue-query@10684

@tanstack/vue-query-devtools

npm i https://pkg.pr.new/@tanstack/vue-query-devtools@10684

commit: fded29e

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 10, 2026

size-limit report 📦

Path Size
react full 12.1 KB (0%)
react minimal 9.07 KB (0%)

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/query-devtools/src/__tests__/Devtools.test.tsx`:
- Around line 394-414: The test "should show the tooltip on mouse enter when
label is hidden" currently only checks the badge existence; update it to assert
the tooltip appears on hover/focus and disappears on leave/blur by querying the
tooltip DOM instead of just the badge. After fireEvent.mouseEnter(fresh) expect
a tooltip element/text to be present (e.g., use rendered.queryByText or
queryByRole to find the tooltip content shown by the tooltip component), then
after fireEvent.mouseLeave(fresh) assert that tooltip is no longer present;
repeat similar assertions for focus/blur (fireEvent.focus(fresh) -> tooltip
present, fireEvent.blur(fresh) -> tooltip absent). Use the same test helpers
(renderDevtools, fresh = rendered.getByLabelText('Fresh: 0')) to locate the
target and the rendered.queryByText/queryByRole to assert tooltip visibility so
the test actually verifies the show/hide handlers.
- Around line 316-318: The test currently asserts only on the first captured
event (listener.mock.calls[0]) which is brittle; update the assertion to verify
that at least one call contains a CustomEvent whose event.detail.type ===
'CLEAR_MUTATION_CACHE'. Locate the test using the listener mock in
Devtools.test.tsx and replace the two lines referencing listener.mock.calls[0]
and expect(...).toBe(...) with a check that iterates listener.mock.calls (or
uses Array.prototype.some) to find any call where the first argument (cast as
CustomEvent) has detail.type === 'CLEAR_MUTATION_CACHE', and assert that this is
true.
- Around line 336-350: The test is using a single microtask tick (await
Promise.resolve()) which is flaky; replace that with an async DOM assertion such
as awaiting rendered.findByLabelText(/Mutation submitted at/) (or wrap the
expect inside waitFor) after calling mutation.execute({}) so the test waits for
the mutation UI to render; update the assertion that currently uses
rendered.getByLabelText to use await rendered.findByLabelText (or waitFor(() =>
expect(rendered.getByLabelText(...)).toBeInTheDocument())) and keep references
to renderDevtools, queryClient, and mutation.execute to locate the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 403c9b71-f1da-460b-894a-8c0d9916e0c8

📥 Commits

Reviewing files that changed from the base of the PR and between be4f84f and d4b86f6.

📒 Files selected for processing (1)
  • packages/query-devtools/src/__tests__/Devtools.test.tsx

Comment thread packages/query-devtools/src/__tests__/Devtools.test.tsx Outdated
Comment on lines +336 to +350
it('should render mutations in the mutations view', async () => {
const rendered = renderDevtools({ initialIsOpen: true })

fireEvent.click(rendered.getByText('Mutations'))

const mutation = queryClient.getMutationCache().build(queryClient, {
mutationKey: ['add-post'],
mutationFn: () => Promise.resolve('ok'),
})
mutation.execute({})
await Promise.resolve()

expect(
rendered.getByLabelText(/Mutation submitted at/),
).toBeInTheDocument()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use an async DOM assertion instead of a single microtask tick

await Promise.resolve() is timing-sensitive and can make this test flaky when mutation notifications land later than one tick. Assert via findBy.../waitFor on the rendered UI state.

Proposed fix
     it('should render mutations in the mutations view', async () => {
       const rendered = renderDevtools({ initialIsOpen: true })

       fireEvent.click(rendered.getByText('Mutations'))

       const mutation = queryClient.getMutationCache().build(queryClient, {
         mutationKey: ['add-post'],
         mutationFn: () => Promise.resolve('ok'),
       })
-      mutation.execute({})
-      await Promise.resolve()
-
-      expect(
-        rendered.getByLabelText(/Mutation submitted at/),
-      ).toBeInTheDocument()
+      void mutation.execute({})
+      expect(
+        await rendered.findByLabelText(/Mutation submitted at/),
+      ).toBeInTheDocument()
     })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('should render mutations in the mutations view', async () => {
const rendered = renderDevtools({ initialIsOpen: true })
fireEvent.click(rendered.getByText('Mutations'))
const mutation = queryClient.getMutationCache().build(queryClient, {
mutationKey: ['add-post'],
mutationFn: () => Promise.resolve('ok'),
})
mutation.execute({})
await Promise.resolve()
expect(
rendered.getByLabelText(/Mutation submitted at/),
).toBeInTheDocument()
it('should render mutations in the mutations view', async () => {
const rendered = renderDevtools({ initialIsOpen: true })
fireEvent.click(rendered.getByText('Mutations'))
const mutation = queryClient.getMutationCache().build(queryClient, {
mutationKey: ['add-post'],
mutationFn: () => Promise.resolve('ok'),
})
void mutation.execute({})
expect(
await rendered.findByLabelText(/Mutation submitted at/),
).toBeInTheDocument()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/query-devtools/src/__tests__/Devtools.test.tsx` around lines 336 -
350, The test is using a single microtask tick (await Promise.resolve()) which
is flaky; replace that with an async DOM assertion such as awaiting
rendered.findByLabelText(/Mutation submitted at/) (or wrap the expect inside
waitFor) after calling mutation.execute({}) so the test waits for the mutation
UI to render; update the assertion that currently uses rendered.getByLabelText
to use await rendered.findByLabelText (or waitFor(() =>
expect(rendered.getByLabelText(...)).toBeInTheDocument())) and keep references
to renderDevtools, queryClient, and mutation.execute to locate the change.

Comment thread packages/query-devtools/src/__tests__/Devtools.test.tsx Outdated
@sukvvon sukvvon force-pushed the test/query-devtools-devtools-query-list branch from d4b86f6 to 7af9fbf Compare May 10, 2026 15:19
@sukvvon sukvvon force-pushed the test/query-devtools-devtools-query-list branch from 7af9fbf to 58f3a1f Compare May 10, 2026 15:21
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
packages/query-devtools/src/__tests__/Devtools.test.tsx (2)

337-351: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Replace one-tick wait with an async DOM assertion

Line 347 (await Promise.resolve()) is timing-sensitive and can still make this test flaky. Wait for rendered UI state instead.

Proposed fix
       const mutation = queryClient.getMutationCache().build(queryClient, {
         mutationKey: ['add-post'],
         mutationFn: () => Promise.resolve('ok'),
       })
-      mutation.execute({})
-      await Promise.resolve()
+      void mutation.execute({})

       expect(
-        rendered.getByLabelText(/Mutation submitted at/),
+        await rendered.findByLabelText(/Mutation submitted at/),
       ).toBeInTheDocument()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/query-devtools/src/__tests__/Devtools.test.tsx` around lines 337 -
351, The test uses a fragile one-tick wait (await Promise.resolve()) after
mutation.execute() in the 'should render mutations in the mutations view' test;
replace that with an async DOM assertion so the test waits for the UI to update
reliably—e.g. use rendered.findByLabelText(/Mutation submitted at/) or wrap the
expect in waitFor. Update the test that calls renderDevtools,
queryClient.getMutationCache().build(...), and mutation.execute({}) to await the
DOM query (findByLabelText) or await waitFor(() =>
rendered.getByLabelText(/Mutation submitted at/())) instead of awaiting
Promise.resolve().

395-415: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Tooltip test doesn’t verify tooltip visibility transitions

Line 414 only re-checks the badge exists, which is true regardless of tooltip logic. Assert that tooltip content/element appears on enter/focus and disappears on leave/blur.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/query-devtools/src/__tests__/Devtools.test.tsx` around lines 395 -
415, The test currently only asserts the badge exists (const fresh =
rendered.getByLabelText('Fresh: 0') and expect(fresh).toBeInTheDocument()) which
doesn't verify tooltip visibility transitions; update the test to assert that
the tooltip element/content appears after fireEvent.mouseEnter(fresh) and
fireEvent.focus(fresh) (use a selector like getByText or queryByRole for the
tooltip text) and that it is removed after fireEvent.mouseLeave(fresh) and
fireEvent.blur(fresh) (assert tooltip is not in the document or not visible);
keep using the same element reference 'fresh' and replace the final
existence-only assertion with presence/absence assertions for the tooltip
element.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@packages/query-devtools/src/__tests__/Devtools.test.tsx`:
- Around line 337-351: The test uses a fragile one-tick wait (await
Promise.resolve()) after mutation.execute() in the 'should render mutations in
the mutations view' test; replace that with an async DOM assertion so the test
waits for the UI to update reliably—e.g. use rendered.findByLabelText(/Mutation
submitted at/) or wrap the expect in waitFor. Update the test that calls
renderDevtools, queryClient.getMutationCache().build(...), and
mutation.execute({}) to await the DOM query (findByLabelText) or await
waitFor(() => rendered.getByLabelText(/Mutation submitted at/())) instead of
awaiting Promise.resolve().
- Around line 395-415: The test currently only asserts the badge exists (const
fresh = rendered.getByLabelText('Fresh: 0') and
expect(fresh).toBeInTheDocument()) which doesn't verify tooltip visibility
transitions; update the test to assert that the tooltip element/content appears
after fireEvent.mouseEnter(fresh) and fireEvent.focus(fresh) (use a selector
like getByText or queryByRole for the tooltip text) and that it is removed after
fireEvent.mouseLeave(fresh) and fireEvent.blur(fresh) (assert tooltip is not in
the document or not visible); keep using the same element reference 'fresh' and
replace the final existence-only assertion with presence/absence assertions for
the tooltip element.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: db19ef3a-4fae-460f-8771-0187bc295d43

📥 Commits

Reviewing files that changed from the base of the PR and between 7af9fbf and 58f3a1f.

📒 Files selected for processing (1)
  • packages/query-devtools/src/__tests__/Devtools.test.tsx

@sukvvon sukvvon merged commit ac57627 into main May 10, 2026
8 checks passed
@sukvvon sukvvon deleted the test/query-devtools-devtools-query-list branch May 10, 2026 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant