Conversation
…ith different durations when 'isRestoring' is true
📝 WalkthroughWalkthroughA Vitest test case was added to the Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~5 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
View your CI Pipeline Execution ↗ for commit 45b46a7
☁️ Nx Cloud last updated this comment at |
🚀 Changeset Version PreviewNo changeset entries found. Merging this PR will not cause a version bump for any packages. |
size-limit report 📦
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/svelte-query/tests/createQueries/createQueries.svelte.test.ts`:
- Around line 974-1017: The test enables fake timers with vi.useFakeTimers() but
restores them unconditionally at the end, risking leakage if an assertion
throws; wrap the test body that uses vi.useFakeTimers(), the calls to
vi.advanceTimersByTimeAsync(...) and all assertions in a try block and call
vi.useRealTimers() in a finally block so timers are always restored; locate the
code around vi.useFakeTimers(), the advanceTimers calls and the final
vi.useRealTimers() to implement the try/finally.
🪄 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: 6c73de61-7455-43ea-9d7c-38581703f51b
📒 Files selected for processing (1)
packages/svelte-query/tests/createQueries/createQueries.svelte.test.ts
| vi.useFakeTimers() | ||
|
|
||
| const queryFn1 = vi.fn(() => sleep(10).then(() => 'data1')) | ||
| const queryFn2 = vi.fn(() => sleep(20).then(() => 'data2')) | ||
|
|
||
| const rendered = render(IsRestoringExample, { | ||
| props: { queryFn1, queryFn2 }, | ||
| }) | ||
|
|
||
| await vi.advanceTimersByTimeAsync(0) | ||
|
|
||
| expect(rendered.getByTestId('status1')).toHaveTextContent('pending') | ||
| expect(rendered.getByTestId('status2')).toHaveTextContent('pending') | ||
| expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle') | ||
| expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle') | ||
| expect(rendered.getByTestId('data1')).toHaveTextContent('undefined') | ||
| expect(rendered.getByTestId('data2')).toHaveTextContent('undefined') | ||
| expect(queryFn1).toHaveBeenCalledTimes(0) | ||
| expect(queryFn2).toHaveBeenCalledTimes(0) | ||
|
|
||
| await vi.advanceTimersByTimeAsync(11) | ||
|
|
||
| expect(rendered.getByTestId('status1')).toHaveTextContent('pending') | ||
| expect(rendered.getByTestId('status2')).toHaveTextContent('pending') | ||
| expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle') | ||
| expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle') | ||
| expect(rendered.getByTestId('data1')).toHaveTextContent('undefined') | ||
| expect(rendered.getByTestId('data2')).toHaveTextContent('undefined') | ||
| expect(queryFn1).toHaveBeenCalledTimes(0) | ||
| expect(queryFn2).toHaveBeenCalledTimes(0) | ||
|
|
||
| await vi.advanceTimersByTimeAsync(10) | ||
|
|
||
| expect(rendered.getByTestId('status1')).toHaveTextContent('pending') | ||
| expect(rendered.getByTestId('status2')).toHaveTextContent('pending') | ||
| expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle') | ||
| expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle') | ||
| expect(rendered.getByTestId('data1')).toHaveTextContent('undefined') | ||
| expect(rendered.getByTestId('data2')).toHaveTextContent('undefined') | ||
| expect(queryFn1).toHaveBeenCalledTimes(0) | ||
| expect(queryFn2).toHaveBeenCalledTimes(0) | ||
|
|
||
| vi.useRealTimers() | ||
| }) |
There was a problem hiding this comment.
Protect fake-timer cleanup with try/finally to avoid cross-test leakage.
If any assertion fails before Line 1016, fake timers stay enabled and may cascade failures into later tests. Wrap the body in try/finally and restore timers in finally.
Suggested fix
it('should not fetch queries with different durations for the duration of the restoring period when isRestoring is true', async () => {
- vi.useFakeTimers()
-
- const queryFn1 = vi.fn(() => sleep(10).then(() => 'data1'))
- const queryFn2 = vi.fn(() => sleep(20).then(() => 'data2'))
-
- const rendered = render(IsRestoringExample, {
- props: { queryFn1, queryFn2 },
- })
-
- await vi.advanceTimersByTimeAsync(0)
-
- expect(rendered.getByTestId('status1')).toHaveTextContent('pending')
- expect(rendered.getByTestId('status2')).toHaveTextContent('pending')
- expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')
- expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')
- expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')
- expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')
- expect(queryFn1).toHaveBeenCalledTimes(0)
- expect(queryFn2).toHaveBeenCalledTimes(0)
-
- await vi.advanceTimersByTimeAsync(11)
-
- expect(rendered.getByTestId('status1')).toHaveTextContent('pending')
- expect(rendered.getByTestId('status2')).toHaveTextContent('pending')
- expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')
- expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')
- expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')
- expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')
- expect(queryFn1).toHaveBeenCalledTimes(0)
- expect(queryFn2).toHaveBeenCalledTimes(0)
-
- await vi.advanceTimersByTimeAsync(10)
-
- expect(rendered.getByTestId('status1')).toHaveTextContent('pending')
- expect(rendered.getByTestId('status2')).toHaveTextContent('pending')
- expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')
- expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')
- expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')
- expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')
- expect(queryFn1).toHaveBeenCalledTimes(0)
- expect(queryFn2).toHaveBeenCalledTimes(0)
-
- vi.useRealTimers()
+ vi.useFakeTimers()
+ try {
+ const queryFn1 = vi.fn(() => sleep(10).then(() => 'data1'))
+ const queryFn2 = vi.fn(() => sleep(20).then(() => 'data2'))
+
+ const rendered = render(IsRestoringExample, {
+ props: { queryFn1, queryFn2 },
+ })
+
+ await vi.advanceTimersByTimeAsync(0)
+
+ expect(rendered.getByTestId('status1')).toHaveTextContent('pending')
+ expect(rendered.getByTestId('status2')).toHaveTextContent('pending')
+ expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')
+ expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')
+ expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')
+ expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')
+ expect(queryFn1).toHaveBeenCalledTimes(0)
+ expect(queryFn2).toHaveBeenCalledTimes(0)
+
+ await vi.advanceTimersByTimeAsync(11)
+
+ expect(rendered.getByTestId('status1')).toHaveTextContent('pending')
+ expect(rendered.getByTestId('status2')).toHaveTextContent('pending')
+ expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')
+ expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')
+ expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')
+ expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')
+ expect(queryFn1).toHaveBeenCalledTimes(0)
+ expect(queryFn2).toHaveBeenCalledTimes(0)
+
+ await vi.advanceTimersByTimeAsync(10)
+
+ expect(rendered.getByTestId('status1')).toHaveTextContent('pending')
+ expect(rendered.getByTestId('status2')).toHaveTextContent('pending')
+ expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle')
+ expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle')
+ expect(rendered.getByTestId('data1')).toHaveTextContent('undefined')
+ expect(rendered.getByTestId('data2')).toHaveTextContent('undefined')
+ expect(queryFn1).toHaveBeenCalledTimes(0)
+ expect(queryFn2).toHaveBeenCalledTimes(0)
+ } finally {
+ vi.useRealTimers()
+ }
})📝 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.
| vi.useFakeTimers() | |
| const queryFn1 = vi.fn(() => sleep(10).then(() => 'data1')) | |
| const queryFn2 = vi.fn(() => sleep(20).then(() => 'data2')) | |
| const rendered = render(IsRestoringExample, { | |
| props: { queryFn1, queryFn2 }, | |
| }) | |
| await vi.advanceTimersByTimeAsync(0) | |
| expect(rendered.getByTestId('status1')).toHaveTextContent('pending') | |
| expect(rendered.getByTestId('status2')).toHaveTextContent('pending') | |
| expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle') | |
| expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle') | |
| expect(rendered.getByTestId('data1')).toHaveTextContent('undefined') | |
| expect(rendered.getByTestId('data2')).toHaveTextContent('undefined') | |
| expect(queryFn1).toHaveBeenCalledTimes(0) | |
| expect(queryFn2).toHaveBeenCalledTimes(0) | |
| await vi.advanceTimersByTimeAsync(11) | |
| expect(rendered.getByTestId('status1')).toHaveTextContent('pending') | |
| expect(rendered.getByTestId('status2')).toHaveTextContent('pending') | |
| expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle') | |
| expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle') | |
| expect(rendered.getByTestId('data1')).toHaveTextContent('undefined') | |
| expect(rendered.getByTestId('data2')).toHaveTextContent('undefined') | |
| expect(queryFn1).toHaveBeenCalledTimes(0) | |
| expect(queryFn2).toHaveBeenCalledTimes(0) | |
| await vi.advanceTimersByTimeAsync(10) | |
| expect(rendered.getByTestId('status1')).toHaveTextContent('pending') | |
| expect(rendered.getByTestId('status2')).toHaveTextContent('pending') | |
| expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle') | |
| expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle') | |
| expect(rendered.getByTestId('data1')).toHaveTextContent('undefined') | |
| expect(rendered.getByTestId('data2')).toHaveTextContent('undefined') | |
| expect(queryFn1).toHaveBeenCalledTimes(0) | |
| expect(queryFn2).toHaveBeenCalledTimes(0) | |
| vi.useRealTimers() | |
| }) | |
| vi.useFakeTimers() | |
| try { | |
| const queryFn1 = vi.fn(() => sleep(10).then(() => 'data1')) | |
| const queryFn2 = vi.fn(() => sleep(20).then(() => 'data2')) | |
| const rendered = render(IsRestoringExample, { | |
| props: { queryFn1, queryFn2 }, | |
| }) | |
| await vi.advanceTimersByTimeAsync(0) | |
| expect(rendered.getByTestId('status1')).toHaveTextContent('pending') | |
| expect(rendered.getByTestId('status2')).toHaveTextContent('pending') | |
| expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle') | |
| expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle') | |
| expect(rendered.getByTestId('data1')).toHaveTextContent('undefined') | |
| expect(rendered.getByTestId('data2')).toHaveTextContent('undefined') | |
| expect(queryFn1).toHaveBeenCalledTimes(0) | |
| expect(queryFn2).toHaveBeenCalledTimes(0) | |
| await vi.advanceTimersByTimeAsync(11) | |
| expect(rendered.getByTestId('status1')).toHaveTextContent('pending') | |
| expect(rendered.getByTestId('status2')).toHaveTextContent('pending') | |
| expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle') | |
| expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle') | |
| expect(rendered.getByTestId('data1')).toHaveTextContent('undefined') | |
| expect(rendered.getByTestId('data2')).toHaveTextContent('undefined') | |
| expect(queryFn1).toHaveBeenCalledTimes(0) | |
| expect(queryFn2).toHaveBeenCalledTimes(0) | |
| await vi.advanceTimersByTimeAsync(10) | |
| expect(rendered.getByTestId('status1')).toHaveTextContent('pending') | |
| expect(rendered.getByTestId('status2')).toHaveTextContent('pending') | |
| expect(rendered.getByTestId('fetchStatus1')).toHaveTextContent('idle') | |
| expect(rendered.getByTestId('fetchStatus2')).toHaveTextContent('idle') | |
| expect(rendered.getByTestId('data1')).toHaveTextContent('undefined') | |
| expect(rendered.getByTestId('data2')).toHaveTextContent('undefined') | |
| expect(queryFn1).toHaveBeenCalledTimes(0) | |
| expect(queryFn2).toHaveBeenCalledTimes(0) | |
| } finally { | |
| vi.useRealTimers() | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/svelte-query/tests/createQueries/createQueries.svelte.test.ts`
around lines 974 - 1017, The test enables fake timers with vi.useFakeTimers()
but restores them unconditionally at the end, risking leakage if an assertion
throws; wrap the test body that uses vi.useFakeTimers(), the calls to
vi.advanceTimersByTimeAsync(...) and all assertions in a try block and call
vi.useRealTimers() in a finally block so timers are always restored; locate the
code around vi.useFakeTimers(), the advanceTimers calls and the final
vi.useRealTimers() to implement the try/finally.
🎯 Changes
createQueriesdoes not fetch queries with different durations (sleep(10)andsleep(20)) during the restoring period whenisRestoringis truereact-querytest pattern foruseQuerieswithIsRestoringProvider✅ Checklist
pnpm run test:pr.🚀 Release Impact
Summary by CodeRabbit