Skip to content

Conversation

@sukvvon
Copy link
Contributor

@sukvvon sukvvon commented Nov 23, 2025

🎯 Changes

βœ… 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).

Summary by CodeRabbit

  • Tests
    • Centralized fake-timer control for deterministic timing, replacing ad-hoc waits with explicit timer advancement.
    • Restored asynchronous timing for persistence and query flows to better reflect real behavior.
    • Reworked test sequencing to advance timers, trigger DOM updates, and assert hydration/fetch transitions.
    • Expanded coverage for success and error paths through staged timer progression.
    • Added enhanced DOM matchers to the test setup for clearer UI assertions.

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Nov 23, 2025

⚠️ No Changeset found

Latest commit: 3f92720

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 23, 2025

Walkthrough

Tests were refactored to use Vitest fake timers with explicit vi.advanceTimersByTimeAsync calls; persister and queryFn now resolve asynchronously via sleep(...).then(...). Test render assertions use a single captured render result and call fixture.detectChanges(); test setup imports @testing-library/jest-dom/vitest.

Changes

Cohort / File(s) Summary
Test timer refactoring
packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts
Adds global fake timer setup/teardown (vi.useFakeTimers() / vi.useRealTimers()); changes persister and queryFn to return sleep(...).then(...) so resolves occur under fake timers; replaces waitFor/ad-hoc awaits with vi.advanceTimersByTimeAsync(...); captures single rendered result and uses rendered.fixture.detectChanges() and rendered.getByText() for DOM checks; expands assertions for onSuccess/onError flows.
Test environment setup
packages/angular-query-persist-client/test-setup.ts
Adds import '@testing-library/jest-dom/vitest' to enable Jest DOM matchers in Vitest tests.

Sequence Diagram(s)

sequenceDiagram
    participant Test as Test Runner
    participant Timers as vi (fake timers)
    participant Persister as Persister / prefetch
    participant Renderer as Angular Test Renderer
    participant Fetch as Query / fetch

    Note over Test,Timers: Test start β€” fake timers enabled
    Test->>Timers: vi.useFakeTimers()
    Test->>Persister: trigger prefetch (returns sleep().then(...))
    Timers->>Timers: vi.advanceTimersByTimeAsync(n)
    Timers-->>Persister: sleep resolves -> persister resolves
    Persister->>Renderer: provide hydrated/initial data
    Renderer->>Test: detectChanges() + getByText("hydrated")
    Test->>Fetch: trigger fetch (returns sleep().then(...))
    Timers->>Timers: vi.advanceTimersByTimeAsync(m)
    Timers-->>Fetch: sleep resolves -> fetch resolves
    Fetch->>Renderer: update DOM to "fetched"
    Renderer->>Test: detectChanges() + getByText("fetched")
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Check pairing of vi.useFakeTimers()/vi.useRealTimers() in all tests.
  • Verify sleep durations correspond to vi.advanceTimersByTimeAsync calls.
  • Confirm DOM updates use rendered.fixture.detectChanges() at correct transition points.
  • Ensure onError/onSuccess branches are asserted correctly after timer advances.

Suggested reviewers

  • manudeli

Poem

πŸ‡ Timers paused, I bound and sneak,
Sleep then .then() β€” the seconds speak.
Advance the ticks, see DOM take flight,
Hydrated, fetched β€” the tests delight.
Rabbit hops off β€” CI smiles tonight.

Pre-merge checks and finishing touches

βœ… Passed checks (3 passed)
Check name Status Explanation
Title check βœ… Passed The title comprehensively summarizes all major changes in the PR (fake timers, advanceTimersByTimeAsync, sleep().then() pattern, rendered replacement, toBeInTheDocument, and @testing-library/jest-dom/vitest addition) and directly matches the changeset modifications.
Description check βœ… Passed The PR description follows the template structure with completed checklist items and clearly marks the change as dev-only, though the '🎯 Changes' section lacks detailed motivation for why these test modifications improve the codebase.
Docstring Coverage βœ… Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • πŸ“ Generate docstrings
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

@nx-cloud
Copy link

nx-cloud bot commented Nov 23, 2025

View your CI Pipeline Execution β†— for commit 3f92720

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... βœ… Succeeded 1m 50s View β†—
nx run-many --target=build --exclude=examples/*... βœ… Succeeded 5s View β†—

☁️ Nx Cloud last updated this comment at 2025-11-23 17:21:19 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 23, 2025

More templates

@tanstack/angular-query-experimental

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

@tanstack/eslint-plugin-query

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

@tanstack/query-async-storage-persister

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

@tanstack/query-broadcast-client-experimental

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

@tanstack/query-core

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

@tanstack/query-devtools

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

@tanstack/query-persist-client-core

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

@tanstack/query-sync-storage-persister

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

@tanstack/react-query

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

@tanstack/react-query-devtools

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

@tanstack/react-query-next-experimental

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

@tanstack/react-query-persist-client

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

@tanstack/solid-query

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

@tanstack/solid-query-devtools

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

@tanstack/solid-query-persist-client

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

@tanstack/svelte-query

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

@tanstack/svelte-query-devtools

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

@tanstack/svelte-query-persist-client

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

@tanstack/vue-query

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

@tanstack/vue-query-devtools

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

commit: 3f92720

@sukvvon sukvvon force-pushed the test/angular-query-persist-client-with-persist-query-client-fake-timers branch from 2e93bb9 to 652e89a Compare November 23, 2025 12:21
@codecov
Copy link

codecov bot commented Nov 23, 2025

Codecov Report

βœ… All modified and coverable lines are covered by tests.
βœ… Project coverage is 100.00%. Comparing base (ae47807) to head (3f92720).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff              @@
##             main     #9895       +/-   ##
============================================
+ Coverage   45.70%   100.00%   +54.29%     
============================================
  Files         200         1      -199     
  Lines        8437        19     -8418     
  Branches     1936         1     -1935     
============================================
- Hits         3856        19     -3837     
+ Misses       4133         0     -4133     
+ Partials      448         0      -448     
Components Coverage Ξ”
@tanstack/angular-query-experimental βˆ… <ΓΈ> (βˆ…)
@tanstack/eslint-plugin-query βˆ… <ΓΈ> (βˆ…)
@tanstack/query-async-storage-persister βˆ… <ΓΈ> (βˆ…)
@tanstack/query-broadcast-client-experimental βˆ… <ΓΈ> (βˆ…)
@tanstack/query-codemods βˆ… <ΓΈ> (βˆ…)
@tanstack/query-core βˆ… <ΓΈ> (βˆ…)
@tanstack/query-devtools βˆ… <ΓΈ> (βˆ…)
@tanstack/query-persist-client-core βˆ… <ΓΈ> (βˆ…)
@tanstack/query-sync-storage-persister βˆ… <ΓΈ> (βˆ…)
@tanstack/query-test-utils βˆ… <ΓΈ> (βˆ…)
@tanstack/react-query βˆ… <ΓΈ> (βˆ…)
@tanstack/react-query-devtools βˆ… <ΓΈ> (βˆ…)
@tanstack/react-query-next-experimental βˆ… <ΓΈ> (βˆ…)
@tanstack/react-query-persist-client βˆ… <ΓΈ> (βˆ…)
@tanstack/solid-query βˆ… <ΓΈ> (βˆ…)
@tanstack/solid-query-devtools βˆ… <ΓΈ> (βˆ…)
@tanstack/solid-query-persist-client βˆ… <ΓΈ> (βˆ…)
@tanstack/svelte-query βˆ… <ΓΈ> (βˆ…)
@tanstack/svelte-query-devtools βˆ… <ΓΈ> (βˆ…)
@tanstack/svelte-query-persist-client βˆ… <ΓΈ> (βˆ…)
@tanstack/vue-query βˆ… <ΓΈ> (βˆ…)
@tanstack/vue-query-devtools βˆ… <ΓΈ> (βˆ…)
πŸš€ New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • πŸ“¦ JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sukvvon sukvvon force-pushed the test/angular-query-persist-client-with-persist-query-client-fake-timers branch from 652e89a to 9b92bc7 Compare November 23, 2025 12:25
@sukvvon sukvvon marked this pull request as ready for review November 23, 2025 12:29
@sukvvon sukvvon force-pushed the test/angular-query-persist-client-with-persist-query-client-fake-timers branch from 9b92bc7 to fa348ff Compare November 23, 2025 12:32
Copy link
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: 0

🧹 Nitpick comments (2)
packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts (2)

75-80: Prefetch + persist pattern with fake timers is logically sound; consider awaiting persistQueryClientSave

The sequence β€œprefetchQuery with sleep(10), await vi.advanceTimersByTimeAsync(10), then persistQueryClientSave(...); await vi.advanceTimersByTimeAsync(0)” correctly ensures the hydrated state is in the cache before persisting, and the fake timers drive all sleep calls deterministically. Given the current mock persister is synchronous, behavior is correct.

To avoid potential floating‑promise lint warnings and make future async persister changes safer, you might optionally make the persist step explicit:

await persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)

This doesn’t change semantics today but clarifies intent.

If you have ESLint’s no‑floating‑promises (or similar) enabled elsewhere in the repo, it’s worth checking whether this file triggers any warnings with the current pattern.

Also applies to: 83-85, 163-168, 171-173, 251-256, 259-261, 328-333, 335-337


110-110: Timer‑driven DOM assertions + detectChanges pattern is consistent; consider a tiny helper

Across the tests you follow a clear pattern:

  • const rendered = await render(Page, { ... })
  • await vi.advanceTimersByTimeAsync(N)
  • rendered.fixture.detectChanges()
  • DOM assertions using rendered.getByText(...).toBeInTheDocument()

This is exactly what you want with zoneless CD and fake timers, and it nicely replaces the older waitFor + toBeTruthy style.

If you find yourself adding more such tests, you might consider a small helper like await advanceAndDetect(rendered, ms) to reduce repetition and make it harder to forget the detectChanges() call.

Please verify that there are no remaining assertions in this file still using toBeTruthy for DOM presence now that @testing-library/jest-dom/vitest is wired up.

Also applies to: 120-123, 125-127, 202-202, 212-215, 217-219, 293-293, 303-306, 357-357, 371-373, 407-407, 421-422, 427-429

πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between c9bc600 and 9b92bc7.

πŸ“’ Files selected for processing (2)
  • packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts (19 hunks)
  • packages/angular-query-persist-client/test-setup.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
πŸ““ Common learnings
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.
Learnt from: arnoud-dv
Repo: TanStack/query PR: 9669
File: docs/framework/angular/guides/testing.md:49-56
Timestamp: 2025-09-21T00:31:02.518Z
Learning: TestBed.tick() is a valid API introduced in Angular 20 for triggering effects in unit tests, similar to ApplicationRef.tick() but for testing contexts.
πŸ“š Learning: 2025-09-21T00:31:02.518Z
Learnt from: arnoud-dv
Repo: TanStack/query PR: 9669
File: docs/framework/angular/guides/testing.md:49-56
Timestamp: 2025-09-21T00:31:02.518Z
Learning: TestBed.tick() is a valid API introduced in Angular 20 for triggering effects in unit tests, similar to ApplicationRef.tick() but for testing contexts.

Applied to files:

  • packages/angular-query-persist-client/test-setup.ts
  • packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts
πŸ“š Learning: 2025-11-22T09:06:05.219Z
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.

Applied to files:

  • packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts
🧬 Code graph analysis (1)
packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts (2)
packages/query-persist-client-core/src/__tests__/utils.ts (1)
  • createMockPersister (5-20)
packages/query-persist-client-core/src/persist.ts (1)
  • persistQueryClientSave (114-127)
πŸ”‡ Additional comments (3)
packages/angular-query-persist-client/test-setup.ts (1)

1-1: Jest‑DOM matcher setup looks correct

Side‑effect import of @testing-library/jest-dom/vitest in the shared test setup is the right way to enable matchers like toBeInTheDocument for these Angular/Vitest tests; no further changes needed here.

Please double‑check that other package test setups in this repo use the same entry point so matcher behavior stays consistent across packages.

packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts (2)

1-1: Fake‑timer + render setup is clean and well‑scoped

Using beforeEach(vi.useFakeTimers) / afterEach(vi.useRealTimers) together with render from @testing-library/angular keeps timer control localized per test and avoids cross‑test leakage. This fits well with provideZonelessChangeDetection() and the rest of the Angular testing stack.

Please just confirm there are no other tests in this package that rely on real timers implicitly (e.g. setTimeout without advanceTimersByTimeAsync) so this global fake‑timer setup doesn’t introduce surprises.

Also applies to: 13-13, 21-27


275-283: Side‑effecting queryFn correctly uses async/await, matching repo testing conventions

In the β€œshould not refetch after restoring when data is fresh” test, the queryFn that flips the fetched flag uses async/await around sleep(10), while other pure queryFns use the sleep(10).then(...) pattern. This aligns with the prior guidance to prefer async/await when there are side effects and .then when there aren’t, and the fetched flag plus states expectations give a clear signal that no refetch occurred for fresh data.

Based on learnings, this pattern matches similar tests in other persist‑client packages; it’s still worth running the full Angular test suite to ensure no subtle behavior differences slipped in with the fake‑timer migration.

Also applies to: 310-322

…fake timers, replace 'waitFor' with 'advanceTimersByTimeAsync', use 'sleep().then()' pattern, replace 'screen' with 'rendered', add 'toBeInTheDocument', and add '@testing-library/jest-dom/vitest'
@sukvvon sukvvon force-pushed the test/angular-query-persist-client-with-persist-query-client-fake-timers branch from fa348ff to 914e012 Compare November 23, 2025 12:37
@sukvvon sukvvon changed the title test(angular-query-persist-client/withPersistQueryClient): switch to fake timers, replace 'waitFor' with 'advanceTimersByTimeAsync', use 'sleep().then()' pattern, replace 'toBeTruthy' with 'toBeInTheDocument', and add '@testing-library/jest-dom/vitest' test(angular-query-persist-client/withPersistQueryClient): switch to fake timers, replace 'waitFor' with 'advanceTimersByTimeAsync', use 'sleep().then()' pattern, replace 'screen' with 'rendered', add 'toBeInTheDocument', and add '@testing-library/jest-dom/vitest' Nov 23, 2025
…sync/await' with 'sleep().then()' pattern in queryFn and restoreClient
Copy link
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: 0

🧹 Nitpick comments (2)
packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts (2)

75-79: Verify if zero-millisecond timer advancement is necessary.

The prefetch pattern correctly uses sleep().then() and advances timers by 10ms. However, the advanceTimersByTimeAsync(0) after persistQueryClientSave (line 84) appears to flush microtasks. Consider verifying whether this is required for the test to pass or if it can be removed.

Also applies to: 83-84


277-281: Prefer async/await syntax for queryFn with side effects.

The queryFn uses the .then() pattern but contains a side effect (setting the fetched flag). For clarity, prefer async/await syntax when side effects are present.

Based on learnings, when a queryFn contains side effects like setting flags for test verification, async/await syntax is preferred for clarity over the .then() pattern.

Apply this diff to improve clarity:

-        queryFn: () =>
-          sleep(10).then(() => {
-            fetched = true
-            return 'fetched'
-          }),
+        queryFn: async () => {
+          await sleep(10)
+          fetched = true
+          return 'fetched'
+        },
πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 914e012 and 3f92720.

πŸ“’ Files selected for processing (1)
  • packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts (21 hunks)
🧰 Additional context used
🧠 Learnings (3)
πŸ““ Common learnings
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.
Learnt from: arnoud-dv
Repo: TanStack/query PR: 9669
File: docs/framework/angular/guides/testing.md:49-56
Timestamp: 2025-09-21T00:31:02.518Z
Learning: TestBed.tick() is a valid API introduced in Angular 20 for triggering effects in unit tests, similar to ApplicationRef.tick() but for testing contexts.
πŸ“š Learning: 2025-11-22T09:06:05.219Z
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.

Applied to files:

  • packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts
πŸ“š Learning: 2025-09-21T00:31:02.518Z
Learnt from: arnoud-dv
Repo: TanStack/query PR: 9669
File: docs/framework/angular/guides/testing.md:49-56
Timestamp: 2025-09-21T00:31:02.518Z
Learning: TestBed.tick() is a valid API introduced in Angular 20 for triggering effects in unit tests, similar to ApplicationRef.tick() but for testing contexts.

Applied to files:

  • packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts
🧬 Code graph analysis (1)
packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts (2)
packages/query-persist-client-core/src/__tests__/utils.ts (1)
  • createMockPersister (5-20)
packages/query-persist-client-core/src/persist.ts (1)
  • persistQueryClientSave (114-127)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Test
  • GitHub Check: Preview
πŸ”‡ Additional comments (4)
packages/angular-query-persist-client/src/__tests__/with-persist-query-client.test.ts (4)

1-1: LGTM! Fake timer setup is correct.

The import changes and fake timer setup in beforeEach/afterEach hooks align with the PR objectives and follow standard testing patterns.

Also applies to: 13-13, 21-27


36-38: LGTM! Correctly uses .then() pattern for no-side-effect async code.

The restoreClient implementation properly uses the sleep().then() pattern for conciseness, which is appropriate since there are no side effects.

Based on learnings, when a queryFn contains no side effects, the .then() pattern is preferred.


55-59: LGTM! Error persister correctly delays error throw.

The implementation properly uses sleep().then() to throw the error after a delay, ensuring compatibility with fake timer control.


110-128: Verify the 11-millisecond timer advancement.

The render and assertion pattern correctly uses the captured rendered result, manual change detection, and toBeInTheDocument matchers. However, line 125 advances timers by 11ms instead of 10ms (which matches the sleep duration). The extra millisecond might be intended to ensure microtask completion, but this pattern appears fragile and is repeated across multiple tests (lines 217, 376, 427).

Consider verifying whether 10ms is sufficient or if a different approach (e.g., explicit microtask flushing) would be more reliable.

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