Skip to content

test(query-core/queryClient): add test for invalidated 'fetchQuery' resolving consistently#11054

Closed
ckdwns9121 wants to merge 1 commit into
TanStack:mainfrom
ckdwns9121:agent/cover-fetch-query-invalidation
Closed

test(query-core/queryClient): add test for invalidated 'fetchQuery' resolving consistently#11054
ckdwns9121 wants to merge 1 commit into
TanStack:mainfrom
ckdwns9121:agent/cover-fetch-query-invalidation

Conversation

@ckdwns9121

@ckdwns9121 ckdwns9121 commented Jul 12, 2026

Copy link
Copy Markdown

Summary

  • add regression coverage for stale fetchQuery calls invalidated after fetching starts
  • exercise the scenario with both an active and inactive observer
  • assert that both paths resolve with fresh data while preserving their distinct refetch counts

Context

Issue #8060 reported that invalidateQueries could make an imperative fetchQuery reject with a silent CancelledError only when an unrelated active observer existed.

The cancellation changes merged in #9293 now intentionally make a silently cancelled fetch follow the replacement fetch promise. On current main, the active-observer path starts a replacement fetch while the inactive path keeps its original fetch, but both consistently resolve with the updated data. This test locks that behavior against the original reproduction conditions.

Validation

  • pnpm --filter @tanstack/query-core test:lib --run src/__tests__/queryClient.test.tsx (109 tests)
  • pnpm --filter @tanstack/query-core test:lib --run (548 tests)
  • pnpm --filter @tanstack/query-core test:eslint (0 errors; one pre-existing cspell warning)
  • pnpm --filter @tanstack/query-core test:types:tscurrent
  • pnpm prettier --write packages/query-core/src/__tests__/queryClient.test.tsx

The full legacy TypeScript matrix could not run locally because Corepack attempted to execute its cached pnpm.cjs directly and returned EACCES; the current TypeScript build and Vitest type checks pass.

Summary by CodeRabbit

  • Bug Fixes
    • Improved query invalidation behavior while fetches are in progress.
    • Ensured pending fetch requests resolve with updated data whether or not an active observer is present.

Cover the stale fetchQuery invalidation scenario with both active and inactive observers. Silent cancellation now follows the replacement fetch while inactive queries retain their original fetch, and both paths resolve to fresh data.

Constraint: Preserve the silent cancellation contract introduced by TanStack#9293

Rejected: Force CancelledError rejection | current query-core behavior intentionally piggybacks replacement fetches

Confidence: high

Scope-risk: narrow

Tested: query-core 548 tests; queryClient 109 tests; ESLint; TypeScript current; Prettier

Not-tested: legacy TypeScript matrix due local Corepack pnpm.cjs EACCES

Related: TanStack#8060
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Added a parameterized invalidateQueries test covering in-flight imperative fetchQuery behavior with active and inactive matching observers. The test verifies the resolved value and expected queryFn invocation count in both cases.

Changes

InvalidateQueries fetchQuery behavior

Layer / File(s) Summary
Parameterized fetchQuery invalidation test
packages/query-core/src/__tests__/queryClient.test.tsx
Adds active and inactive observer cases, invalidates during an in-flight fetch, and asserts the "updated" result and corresponding queryFn call count.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the change, context, and validation, but it does not follow the required template sections or include the checklist and release impact. Rewrite the PR description to use ## 🎯 Changes, ## ✅ Checklist, and ## 🚀 Release Impact, and fill in the required checklist items.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The new test covers the reported invalidateQueries/fetchQuery inconsistency for both active and inactive observers, matching #8060's repro.
Out of Scope Changes check ✅ Passed The changes stay confined to one regression test file and don't add unrelated code or public API changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title clearly matches the PR’s main change: adding regression coverage for invalidated fetchQuery behavior.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@ckdwns9121 ckdwns9121 marked this pull request as ready for review July 12, 2026 15:43
@nx-cloud

nx-cloud Bot commented Jul 12, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit a1228a2

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

☁️ Nx Cloud last updated this comment at 2026-07-12 17:47:04 UTC

@pkg-pr-new

pkg-pr-new Bot commented Jul 12, 2026

Copy link
Copy Markdown
More templates

@tanstack/angular-query-experimental

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

@tanstack/eslint-plugin-query

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

@tanstack/lit-query

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

@tanstack/preact-query

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

@tanstack/preact-query-devtools

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

@tanstack/preact-query-persist-client

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

@tanstack/query-async-storage-persister

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

@tanstack/query-broadcast-client-experimental

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

@tanstack/query-core

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

@tanstack/query-devtools

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

@tanstack/query-persist-client-core

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

@tanstack/query-sync-storage-persister

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

@tanstack/react-query

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

@tanstack/react-query-devtools

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

@tanstack/react-query-next-experimental

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

@tanstack/react-query-persist-client

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

@tanstack/solid-query

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

@tanstack/solid-query-devtools

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

@tanstack/solid-query-persist-client

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

@tanstack/svelte-query

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

@tanstack/svelte-query-devtools

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

@tanstack/svelte-query-persist-client

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

@tanstack/vue-query

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

@tanstack/vue-query-devtools

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

commit: a1228a2

@sukvvon sukvvon changed the title test(query-core): cover fetchQuery invalidation consistency test(query-core/queryClient): add test for invalidated 'fetchQuery' resolving consistently Jul 12, 2026
@sukvvon

sukvvon commented Jul 12, 2026

Copy link
Copy Markdown
Member

Thanks @ckdwns9121! Closing this one — I don't think it adds coverage we don't already have.

The enabled: true case hits the same silent-cancellation path as should not reject a promise when silently cancelled in the background in query.test.tsx (invalidateQueries defaults to cancelRefetch: true, so it's the same error.silent branch, just a different entry point).

The enabled: false case never actually cancels the fetch — with no active observer there's nothing to refetch, so queryFn runs once and the promise just resolves normally. It doesn't reach the silent-cancellation logic at all.

Appreciate the effort though 🙏

@sukvvon sukvvon closed this Jul 12, 2026
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.

2 participants