From cc08e8826bce1ee2b7c02925e203a928ae7fae37 Mon Sep 17 00:00:00 2001 From: Jonghyeon Ko Date: Fri, 28 Feb 2025 01:24:36 +0900 Subject: [PATCH 1/6] test(query-core): add test case for queryClient.isFetching --- .../src/__tests__/queryClient.test.tsx | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/packages/query-core/src/__tests__/queryClient.test.tsx b/packages/query-core/src/__tests__/queryClient.test.tsx index c308dd1b9a..6ea54a4965 100644 --- a/packages/query-core/src/__tests__/queryClient.test.tsx +++ b/packages/query-core/src/__tests__/queryClient.test.tsx @@ -400,6 +400,27 @@ describe('queryClient', () => { }) }) + describe('isFetching', () => { + test('should return length of fetching queries', async () => { + const key1 = queryKey() + const key2 = queryKey() + + expect(queryClient.isFetching()).toBe(0) + queryClient.prefetchQuery({ + queryKey: key1, + queryFn: () => sleep(300).then(() => 'data'), + }) + expect(queryClient.isFetching()).toBe(1) + queryClient.prefetchQuery({ + queryKey: key2, + queryFn: () => sleep(200).then(() => 'data'), + }) + expect(queryClient.isFetching()).toBe(2) + await waitFor(() => expect(queryClient.isFetching()).toEqual(1)) + await waitFor(() => expect(queryClient.isFetching()).toEqual(0)) + }) + }) + describe('getQueryData', () => { test('should return the query data if the query is found', () => { const key = queryKey() From a628ba87997d46d532f12c9dac1a071effee0756 Mon Sep 17 00:00:00 2001 From: Jonghyeon Ko Date: Fri, 28 Feb 2025 21:05:08 +0900 Subject: [PATCH 2/6] chore: update --- packages/query-core/src/__tests__/queryClient.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/query-core/src/__tests__/queryClient.test.tsx b/packages/query-core/src/__tests__/queryClient.test.tsx index 6ea54a4965..f3a3c252c0 100644 --- a/packages/query-core/src/__tests__/queryClient.test.tsx +++ b/packages/query-core/src/__tests__/queryClient.test.tsx @@ -408,12 +408,12 @@ describe('queryClient', () => { expect(queryClient.isFetching()).toBe(0) queryClient.prefetchQuery({ queryKey: key1, - queryFn: () => sleep(300).then(() => 'data'), + queryFn: () => sleep(10).then(() => 'data'), }) expect(queryClient.isFetching()).toBe(1) queryClient.prefetchQuery({ queryKey: key2, - queryFn: () => sleep(200).then(() => 'data'), + queryFn: () => sleep(5).then(() => 'data'), }) expect(queryClient.isFetching()).toBe(2) await waitFor(() => expect(queryClient.isFetching()).toEqual(1)) From 772aebf5528ec2073b903700ee427bddef16ec8c Mon Sep 17 00:00:00 2001 From: Jonghyeon Ko Date: Fri, 28 Feb 2025 21:17:57 +0900 Subject: [PATCH 3/6] Update packages/query-core/src/__tests__/queryClient.test.tsx --- packages/query-core/src/__tests__/queryClient.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/query-core/src/__tests__/queryClient.test.tsx b/packages/query-core/src/__tests__/queryClient.test.tsx index f3a3c252c0..032a7dd554 100644 --- a/packages/query-core/src/__tests__/queryClient.test.tsx +++ b/packages/query-core/src/__tests__/queryClient.test.tsx @@ -408,7 +408,7 @@ describe('queryClient', () => { expect(queryClient.isFetching()).toBe(0) queryClient.prefetchQuery({ queryKey: key1, - queryFn: () => sleep(10).then(() => 'data'), + queryFn: () => sleep(30).then(() => 'data'), }) expect(queryClient.isFetching()).toBe(1) queryClient.prefetchQuery({ From 0bf7deb7ab6751b65d2bdc1c7c01c911cb68d2d5 Mon Sep 17 00:00:00 2001 From: Jonghyeon Ko Date: Fri, 28 Feb 2025 21:18:19 +0900 Subject: [PATCH 4/6] Update packages/query-core/src/__tests__/queryClient.test.tsx --- packages/query-core/src/__tests__/queryClient.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/query-core/src/__tests__/queryClient.test.tsx b/packages/query-core/src/__tests__/queryClient.test.tsx index 032a7dd554..3fd924a7a4 100644 --- a/packages/query-core/src/__tests__/queryClient.test.tsx +++ b/packages/query-core/src/__tests__/queryClient.test.tsx @@ -413,7 +413,7 @@ describe('queryClient', () => { expect(queryClient.isFetching()).toBe(1) queryClient.prefetchQuery({ queryKey: key2, - queryFn: () => sleep(5).then(() => 'data'), + queryFn: () => sleep(25).then(() => 'data'), }) expect(queryClient.isFetching()).toBe(2) await waitFor(() => expect(queryClient.isFetching()).toEqual(1)) From df05cd737bb4739a5b17e29856c2b13b69643d55 Mon Sep 17 00:00:00 2001 From: Jonghyeon Ko Date: Sat, 1 Mar 2025 02:19:33 +0900 Subject: [PATCH 5/6] chore: use fake timers --- .../src/__tests__/queryClient.test.tsx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/query-core/src/__tests__/queryClient.test.tsx b/packages/query-core/src/__tests__/queryClient.test.tsx index 3fd924a7a4..004211d7b1 100644 --- a/packages/query-core/src/__tests__/queryClient.test.tsx +++ b/packages/query-core/src/__tests__/queryClient.test.tsx @@ -402,22 +402,23 @@ describe('queryClient', () => { describe('isFetching', () => { test('should return length of fetching queries', async () => { - const key1 = queryKey() - const key2 = queryKey() - + vi.useFakeTimers() expect(queryClient.isFetching()).toBe(0) queryClient.prefetchQuery({ - queryKey: key1, - queryFn: () => sleep(30).then(() => 'data'), + queryKey: queryKey(), + queryFn: () => sleep(10).then(() => 'data'), }) expect(queryClient.isFetching()).toBe(1) queryClient.prefetchQuery({ - queryKey: key2, - queryFn: () => sleep(25).then(() => 'data'), + queryKey: queryKey(), + queryFn: () => sleep(5).then(() => 'data'), }) expect(queryClient.isFetching()).toBe(2) - await waitFor(() => expect(queryClient.isFetching()).toEqual(1)) - await waitFor(() => expect(queryClient.isFetching()).toEqual(0)) + await vi.advanceTimersByTimeAsync(5) + expect(queryClient.isFetching()).toEqual(1) + await vi.advanceTimersByTimeAsync(5) + expect(queryClient.isFetching()).toEqual(0) + vi.useRealTimers() }) }) From 01568112856abedcf0c9785b21eebda230a79cc7 Mon Sep 17 00:00:00 2001 From: Jonghyeon Ko Date: Sat, 1 Mar 2025 15:09:03 +0900 Subject: [PATCH 6/6] test(query-core): use fakeTimer for queryClient.test.tsx's all test --- .../src/__tests__/queryClient.test.tsx | 178 ++++++++---------- 1 file changed, 75 insertions(+), 103 deletions(-) diff --git a/packages/query-core/src/__tests__/queryClient.test.tsx b/packages/query-core/src/__tests__/queryClient.test.tsx index 004211d7b1..24907332b8 100644 --- a/packages/query-core/src/__tests__/queryClient.test.tsx +++ b/packages/query-core/src/__tests__/queryClient.test.tsx @@ -1,6 +1,4 @@ import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest' -import { waitFor } from '@testing-library/dom' - import { MutationObserver, QueryClient, @@ -9,8 +7,8 @@ import { focusManager, hydrate, onlineManager, + skipToken, } from '..' -import { skipToken } from '../utils' import { createQueryClient, mockOnlineManagerIsOnline, @@ -24,6 +22,7 @@ describe('queryClient', () => { let queryCache: QueryCache beforeEach(() => { + vi.useFakeTimers() queryClient = createQueryClient() queryCache = queryClient.getQueryCache() queryClient.mount() @@ -32,6 +31,7 @@ describe('queryClient', () => { afterEach(() => { queryClient.clear() queryClient.unmount() + vi.useRealTimers() }) describe('defaultOptions', () => { @@ -75,7 +75,6 @@ describe('queryClient', () => { test('should not trigger a fetch', async () => { const key = queryKey() queryClient.setQueryDefaults(key, { queryFn: () => 'data' }) - await sleep(1) const data = queryClient.getQueryData(key) expect(data).toBeUndefined() }) @@ -333,10 +332,7 @@ describe('queryClient', () => { const key = queryKey() queryClient.prefetchQuery({ queryKey: key, - queryFn: async () => { - await sleep(10) - return 23 - }, + queryFn: () => sleep(10).then(() => 23), }) expect(queryClient.getQueryState(key)).toMatchObject({ data: undefined, @@ -347,12 +343,11 @@ describe('queryClient', () => { data: 42, fetchStatus: 'fetching', }) - await waitFor(() => - expect(queryClient.getQueryState(key)).toMatchObject({ - data: 23, - fetchStatus: 'idle', - }), - ) + await vi.advanceTimersByTimeAsync(10) + expect(queryClient.getQueryState(key)).toMatchObject({ + data: 23, + fetchStatus: 'idle', + }) }) }) @@ -402,7 +397,6 @@ describe('queryClient', () => { describe('isFetching', () => { test('should return length of fetching queries', async () => { - vi.useFakeTimers() expect(queryClient.isFetching()).toBe(0) queryClient.prefetchQuery({ queryKey: queryKey(), @@ -418,7 +412,6 @@ describe('queryClient', () => { expect(queryClient.isFetching()).toEqual(1) await vi.advanceTimersByTimeAsync(5) expect(queryClient.isFetching()).toEqual(0) - vi.useRealTimers() }) }) @@ -490,7 +483,7 @@ describe('queryClient', () => { revalidateIfStale: true, }), ).resolves.toEqual('old') - await sleep(TIMEOUT + 10) + await vi.advanceTimersByTimeAsync(TIMEOUT + 10) await expect( queryClient.ensureQueryData({ queryKey: [key, 'id'], @@ -552,10 +545,7 @@ describe('queryClient', () => { const key = queryKey() queryClient.setQueryData([key, 'id'], { pages: ['old'], pageParams: [0] }) - const queryFn = () => - new Promise((resolve) => { - setTimeout(() => resolve('new'), TIMEOUT) - }) + const queryFn = () => sleep(TIMEOUT).then(() => 'new') await expect( queryClient.ensureInfiniteQueryData({ @@ -566,7 +556,7 @@ describe('queryClient', () => { revalidateIfStale: true, }), ).resolves.toEqual({ pages: ['old'], pageParams: [0] }) - await sleep(TIMEOUT + 10) + await vi.advanceTimersByTimeAsync(TIMEOUT + 10) await expect( queryClient.ensureInfiniteQueryData({ queryKey: [key, 'id'], @@ -659,32 +649,28 @@ describe('queryClient', () => { test('should be able to fetch when garbage collection time is set to 0 and then be removed', async () => { const key1 = queryKey() - const result = await queryClient.fetchQuery({ + const promise = queryClient.fetchQuery({ queryKey: key1, - queryFn: async () => { - await sleep(10) - return 1 - }, + queryFn: () => sleep(10).then(() => 1), gcTime: 0, }) - expect(result).toEqual(1) - await waitFor(() => + vi.advanceTimersByTimeAsync(10) + await expect(promise).resolves.toEqual(1) + await vi.waitFor(() => expect(queryClient.getQueryData(key1)).toEqual(undefined), ) }) test('should keep a query in cache if garbage collection time is Infinity', async () => { const key1 = queryKey() - const result = await queryClient.fetchQuery({ + const promise = queryClient.fetchQuery({ queryKey: key1, - queryFn: async () => { - await sleep(10) - return 1 - }, + queryFn: () => sleep(10).then(() => 1), gcTime: Infinity, }) + await vi.advanceTimersByTimeAsync(10) const result2 = queryClient.getQueryData(key1) - expect(result).toEqual(1) + await expect(promise).resolves.toEqual(1) expect(result2).toEqual(1) }) @@ -706,35 +692,35 @@ describe('queryClient', () => { const key = queryKey() let count = 0 - const fetchFn = () => ++count + const queryFn = () => ++count queryClient.setQueryData(key, count) - const first = await queryClient.fetchQuery({ + const firstPromise = queryClient.fetchQuery({ queryKey: key, - queryFn: fetchFn, + queryFn, staleTime: 100, }) - await sleep(11) - const second = await queryClient.fetchQuery({ + await expect(firstPromise).resolves.toBe(0) + await vi.advanceTimersByTimeAsync(10) + const secondPromise = queryClient.fetchQuery({ queryKey: key, - queryFn: fetchFn, + queryFn, staleTime: 10, }) - const third = await queryClient.fetchQuery({ + await expect(secondPromise).resolves.toBe(1) + const thirdPromise = queryClient.fetchQuery({ queryKey: key, - queryFn: fetchFn, + queryFn, staleTime: 10, }) - await sleep(11) - const fourth = await queryClient.fetchQuery({ + await expect(thirdPromise).resolves.toBe(1) + await vi.advanceTimersByTimeAsync(10) + const fourthPromise = queryClient.fetchQuery({ queryKey: key, - queryFn: fetchFn, + queryFn, staleTime: 10, }) - expect(first).toBe(0) - expect(second).toBe(1) - expect(third).toBe(1) - expect(fourth).toBe(2) + await expect(fourthPromise).resolves.toBe(2) }) test('should allow new meta', async () => { @@ -933,13 +919,11 @@ describe('queryClient', () => { await queryClient.prefetchQuery({ queryKey: key, - queryFn: async () => { - return 'data' - }, + queryFn: async () => 'data', gcTime: 10, }) expect(queryCache.find({ queryKey: key })).toBeDefined() - await sleep(15) + await vi.advanceTimersByTimeAsync(15) expect(queryCache.find({ queryKey: key })).not.toBeDefined() }) }) @@ -971,9 +955,7 @@ describe('queryClient', () => { const key3 = queryKey() await queryClient.fetchQuery({ queryKey: key1, - queryFn: async () => { - return 'data' - }, + queryFn: async () => 'data', }) try { await queryClient.fetchQuery({ @@ -985,28 +967,20 @@ describe('queryClient', () => { } catch {} queryClient.fetchQuery({ queryKey: key1, - queryFn: async () => { - await sleep(1000) - return 'data2' - }, + queryFn: () => sleep(1000).then(() => 'data2'), }) try { queryClient.fetchQuery({ queryKey: key2, - queryFn: async () => { - await sleep(1000) - return Promise.reject('err2') - }, + queryFn: () => + sleep(1000).then(() => Promise.reject('err2')), }) } catch {} queryClient.fetchQuery({ queryKey: key3, - queryFn: async () => { - await sleep(1000) - return 'data3' - }, + queryFn: () => sleep(1000).then(() => 'data3'), }) - await sleep(10) + await vi.advanceTimersByTime(10) await queryClient.cancelQueries() const state1 = queryClient.getQueryState(key1) const state2 = queryClient.getQueryState(key2) @@ -1031,18 +1005,13 @@ describe('queryClient', () => { const key1 = queryKey() await queryClient.fetchQuery({ queryKey: key1, - queryFn: async () => { - return 'data' - }, + queryFn: async () => 'data', }) queryClient.fetchQuery({ queryKey: key1, - queryFn: async () => { - await sleep(1000) - return 'data2' - }, + queryFn: () => sleep(1000).then(() => 'data2'), }) - await sleep(10) + await vi.advanceTimersByTimeAsync(10) await queryClient.cancelQueries({ queryKey: key1 }, { revert: false }) const state1 = queryClient.getQueryState(key1) expect(state1).toMatchObject({ @@ -1514,18 +1483,18 @@ describe('queryClient', () => { let fetchCount = 0 const observer = new QueryObserver(queryClient, { queryKey: key, - queryFn: ({ signal }) => { - return new Promise((resolve) => { + queryFn: ({ signal }) => + new Promise((resolve) => { fetchCount++ setTimeout(() => resolve(5), 10) signal.addEventListener('abort', abortFn) - }) - }, + }), initialData: 1, }) observer.subscribe(() => undefined) - await queryClient.refetchQueries() + queryClient.refetchQueries() + await vi.advanceTimersByTime(10) observer.destroy() expect(abortFn).toHaveBeenCalledTimes(1) expect(fetchCount).toBe(2) @@ -1548,7 +1517,8 @@ describe('queryClient', () => { }) observer.subscribe(() => undefined) - await queryClient.refetchQueries(undefined, { cancelRefetch: false }) + queryClient.refetchQueries(undefined, { cancelRefetch: false }) + await vi.advanceTimersByTime(10) observer.destroy() expect(abortFn).toHaveBeenCalledTimes(0) expect(fetchCount).toBe(1) @@ -1674,7 +1644,9 @@ describe('queryClient', () => { expect(mutationCacheResumePausedMutationsSpy).not.toHaveBeenCalled() focusManager.setFocused(true) - await waitFor(() => expect(queryCacheOnFocusSpy).toHaveBeenCalledTimes(1)) + await vi.waitFor(() => + expect(queryCacheOnFocusSpy).toHaveBeenCalledTimes(1), + ) expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(1) expect(queryCacheOnOnlineSpy).not.toHaveBeenCalled() @@ -1706,7 +1678,7 @@ describe('queryClient', () => { expect(mutationCacheResumePausedMutationsSpy).not.toHaveBeenCalled() onlineManager.setOnline(true) - await waitFor(() => + await vi.waitFor(() => expect(queryCacheOnOnlineSpy).toHaveBeenCalledTimes(1), ) @@ -1734,14 +1706,14 @@ describe('queryClient', () => { void observer1.mutate() void observer2.mutate() - await waitFor(() => { + await vi.waitFor(() => { expect(observer1.getCurrentResult().isPaused).toBeTruthy() expect(observer2.getCurrentResult().isPaused).toBeTruthy() }) onlineManager.setOnline(true) - await waitFor(() => { + await vi.waitFor(() => { expect(observer1.getCurrentResult().status).toBe('success') expect(observer2.getCurrentResult().status).toBe('success') }) @@ -1772,14 +1744,14 @@ describe('queryClient', () => { void observer1.mutate() void observer2.mutate() - await waitFor(() => { + await vi.waitFor(() => { expect(observer1.getCurrentResult().isPaused).toBeTruthy() expect(observer2.getCurrentResult().isPaused).toBeTruthy() }) onlineManager.setOnline(true) - await waitFor(() => { + await vi.waitFor(() => { expect(observer1.getCurrentResult().status).toBe('success') expect(observer2.getCurrentResult().status).toBe('success') }) @@ -1820,17 +1792,15 @@ describe('queryClient', () => { void observer1.mutate() void observer2.mutate() - await waitFor(() => { + await vi.waitFor(() => { expect(observer1.getCurrentResult().isPaused).toBeTruthy() expect(observer2.getCurrentResult().isPaused).toBeTruthy() }) onlineManager.setOnline(true) void queryClient.resumePausedMutations() - await sleep(5) - await queryClient.resumePausedMutations() - await waitFor(() => { + await vi.waitFor(() => { expect(observer1.getCurrentResult().status).toBe('success') expect(observer2.getCurrentResult().status).toBe('success') }) @@ -1858,7 +1828,7 @@ describe('queryClient', () => { onlineManager.setOnline(true) - await waitFor(() => { + await vi.waitFor(() => { expect(observer.getCurrentResult().status).toBe('success') }) }) @@ -1899,7 +1869,7 @@ describe('queryClient', () => { onlineManager.setOnline(true) - await waitFor(() => { + await vi.waitFor(() => { expect( newQueryClient.getMutationCache().getAll()[0]?.state.status, ).toBe('success') @@ -1926,7 +1896,7 @@ describe('queryClient', () => { const unsubscribe = queryObserver.subscribe(() => undefined) - await waitFor(() => { + await vi.waitFor(() => { expect(queryClient.getQueryData(key)).toBe('data1') }) @@ -1971,19 +1941,19 @@ describe('queryClient', () => { void observer3.mutate() - await waitFor(() => + await vi.waitFor(() => expect(observer.getCurrentResult().isPaused).toBeTruthy(), ) - await waitFor(() => + await vi.waitFor(() => expect(observer2.getCurrentResult().isPaused).toBeTruthy(), ) - await waitFor(() => + await vi.waitFor(() => expect(observer3.getCurrentResult().isPaused).toBeTruthy(), ) onlineManager.setOnline(true) - await waitFor(() => { + await vi.waitFor(() => { expect(queryClient.getQueryData(key)).toBe('data2') }) @@ -2023,13 +1993,15 @@ describe('queryClient', () => { onlineManager.setOnline(false) onlineManager.setOnline(true) - await waitFor(() => + await vi.waitFor(() => expect(queryCacheOnOnlineSpy).toHaveBeenCalledTimes(1), ) expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(1) focusManager.setFocused(true) - await waitFor(() => expect(queryCacheOnFocusSpy).toHaveBeenCalledTimes(1)) + await vi.waitFor(() => + expect(queryCacheOnFocusSpy).toHaveBeenCalledTimes(1), + ) expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(2) queryCacheOnFocusSpy.mockRestore()