diff --git a/packages/query-core/src/__tests__/hydration.test.tsx b/packages/query-core/src/__tests__/hydration.test.tsx index 46945e1b89..d07cfef75e 100644 --- a/packages/query-core/src/__tests__/hydration.test.tsx +++ b/packages/query-core/src/__tests__/hydration.test.tsx @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest' -import { sleep } from '@tanstack/query-test-utils' +import { queryKey, sleep } from '@tanstack/query-test-utils' import { QueryClient } from '../queryClient' import { QueryCache } from '../queryCache' import { dehydrate, hydrate } from '../hydration' @@ -16,42 +16,49 @@ describe('dehydration and rehydration', () => { }) test('should work with serializable values', async () => { + const stringKey = queryKey() + const numberKey = queryKey() + const booleanKey = queryKey() + const nullKey = queryKey() + const arrayKey = queryKey() + const nestedKey = queryKey() + const queryCache = new QueryCache() const queryClient = new QueryClient({ queryCache }) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['string'], + queryKey: stringKey, queryFn: () => sleep(0).then(() => 'string'), }), ) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['number'], + queryKey: numberKey, queryFn: () => sleep(0).then(() => 1), }), ) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['boolean'], + queryKey: booleanKey, queryFn: () => sleep(0).then(() => true), }), ) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['null'], + queryKey: nullKey, queryFn: () => sleep(0).then(() => null), }), ) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['array'], + queryKey: arrayKey, queryFn: () => sleep(0).then(() => ['string', 0]), }), ) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['nested'], + queryKey: nestedKey, queryFn: () => sleep(0).then(() => ({ key: [{ nestedKey: 1 }] })), }), ) @@ -66,51 +73,49 @@ describe('dehydration and rehydration', () => { queryCache: hydrationCache, }) hydrate(hydrationClient, parsed) - expect(hydrationCache.find({ queryKey: ['string'] })?.state.data).toBe( + expect(hydrationCache.find({ queryKey: stringKey })?.state.data).toBe( 'string', ) - expect(hydrationCache.find({ queryKey: ['number'] })?.state.data).toBe(1) - expect(hydrationCache.find({ queryKey: ['boolean'] })?.state.data).toBe( - true, - ) - expect(hydrationCache.find({ queryKey: ['null'] })?.state.data).toBe(null) - expect(hydrationCache.find({ queryKey: ['array'] })?.state.data).toEqual([ + expect(hydrationCache.find({ queryKey: numberKey })?.state.data).toBe(1) + expect(hydrationCache.find({ queryKey: booleanKey })?.state.data).toBe(true) + expect(hydrationCache.find({ queryKey: nullKey })?.state.data).toBe(null) + expect(hydrationCache.find({ queryKey: arrayKey })?.state.data).toEqual([ 'string', 0, ]) - expect(hydrationCache.find({ queryKey: ['nested'] })?.state.data).toEqual({ + expect(hydrationCache.find({ queryKey: nestedKey })?.state.data).toEqual({ key: [{ nestedKey: 1 }], }) const fetchDataAfterHydration = vi.fn<(...args: Array) => unknown>() await hydrationClient.prefetchQuery({ - queryKey: ['string'], + queryKey: stringKey, queryFn: fetchDataAfterHydration, staleTime: 1000, }) await hydrationClient.prefetchQuery({ - queryKey: ['number'], + queryKey: numberKey, queryFn: fetchDataAfterHydration, staleTime: 1000, }) await hydrationClient.prefetchQuery({ - queryKey: ['boolean'], + queryKey: booleanKey, queryFn: fetchDataAfterHydration, staleTime: 1000, }) await hydrationClient.prefetchQuery({ - queryKey: ['null'], + queryKey: nullKey, queryFn: fetchDataAfterHydration, staleTime: 1000, }) await hydrationClient.prefetchQuery({ - queryKey: ['array'], + queryKey: arrayKey, queryFn: fetchDataAfterHydration, staleTime: 1000, }) await hydrationClient.prefetchQuery({ - queryKey: ['nested'], + queryKey: nestedKey, queryFn: fetchDataAfterHydration, staleTime: 1000, }) @@ -121,11 +126,12 @@ describe('dehydration and rehydration', () => { }) test('should not dehydrate queries if dehydrateQueries is set to false', () => { + const key = queryKey() const queryCache = new QueryCache() const queryClient = new QueryClient({ queryCache }) vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['string'], + queryKey: key, queryFn: () => sleep(0).then(() => 'string'), }), ) @@ -140,11 +146,12 @@ describe('dehydration and rehydration', () => { }) test('should use the garbage collection time from the client', async () => { + const key = queryKey() const queryCache = new QueryCache() const queryClient = new QueryClient({ queryCache }) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['string'], + queryKey: key, queryFn: () => sleep(0).then(() => 'string'), gcTime: 50, }), @@ -160,22 +167,21 @@ describe('dehydration and rehydration', () => { const hydrationCache = new QueryCache() const hydrationClient = new QueryClient({ queryCache: hydrationCache }) hydrate(hydrationClient, parsed) - expect(hydrationCache.find({ queryKey: ['string'] })?.state.data).toBe( - 'string', - ) + expect(hydrationCache.find({ queryKey: key })?.state.data).toBe('string') await vi.advanceTimersByTimeAsync(100) - expect(hydrationCache.find({ queryKey: ['string'] })).toBeTruthy() + expect(hydrationCache.find({ queryKey: key })).toBeTruthy() queryClient.clear() hydrationClient.clear() }) test('should be able to provide default options for the hydrated queries', async () => { + const key = queryKey() const queryCache = new QueryCache() const queryClient = new QueryClient({ queryCache }) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['string'], + queryKey: key, queryFn: () => sleep(0).then(() => 'string'), }), ) @@ -187,14 +193,13 @@ describe('dehydration and rehydration', () => { hydrate(hydrationClient, parsed, { defaultOptions: { queries: { retry: 10 } }, }) - expect(hydrationCache.find({ queryKey: ['string'] })?.options.retry).toBe( - 10, - ) + expect(hydrationCache.find({ queryKey: key })?.options.retry).toBe(10) queryClient.clear() hydrationClient.clear() }) test('should respect query defaultOptions specified on the QueryClient', async () => { + const key = queryKey() const queryCache = new QueryCache() const queryClient = new QueryClient({ queryCache, @@ -204,7 +209,7 @@ describe('dehydration and rehydration', () => { }) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['string'], + queryKey: key, retry: 0, queryFn: () => Promise.reject(new Error('error')), }), @@ -222,17 +227,14 @@ describe('dehydration and rehydration', () => { hydrate(hydrationClient, parsed, { defaultOptions: { queries: { gcTime: 10 } }, }) - expect(hydrationCache.find({ queryKey: ['string'] })?.options.retry).toBe( - 10, - ) - expect(hydrationCache.find({ queryKey: ['string'] })?.options.gcTime).toBe( - 10, - ) + expect(hydrationCache.find({ queryKey: key })?.options.retry).toBe(10) + expect(hydrationCache.find({ queryKey: key })?.options.gcTime).toBe(10) queryClient.clear() hydrationClient.clear() }) test('should respect mutation defaultOptions specified on the QueryClient', async () => { + const key = queryKey() const mutationCache = new MutationCache() const queryClient = new QueryClient({ mutationCache, @@ -245,7 +247,7 @@ describe('dehydration and rehydration', () => { await executeMutation( queryClient, { - mutationKey: ['string'], + mutationKey: key, mutationFn: () => Promise.resolve('done'), }, undefined, @@ -264,22 +266,20 @@ describe('dehydration and rehydration', () => { hydrate(hydrationClient, parsed, { defaultOptions: { mutations: { gcTime: 10 } }, }) - expect( - hydrationCache.find({ mutationKey: ['string'] })?.options.retry, - ).toBe(10) - expect( - hydrationCache.find({ mutationKey: ['string'] })?.options.gcTime, - ).toBe(10) + expect(hydrationCache.find({ mutationKey: key })?.options.retry).toBe(10) + expect(hydrationCache.find({ mutationKey: key })?.options.gcTime).toBe(10) queryClient.clear() hydrationClient.clear() }) test('should work with complex keys', async () => { + const key = queryKey() + const complexKey = [...key, { key: ['string'], key2: 0 }] const queryCache = new QueryCache() const queryClient = new QueryClient({ queryCache }) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['string', { key: ['string'], key2: 0 }], + queryKey: complexKey, queryFn: () => sleep(0).then(() => 'string'), }), ) @@ -294,7 +294,7 @@ describe('dehydration and rehydration', () => { hydrate(hydrationClient, parsed) expect( hydrationCache.find({ - queryKey: ['string', { key: ['string'], key2: 0 }], + queryKey: complexKey, })?.state.data, ).toBe('string') @@ -302,7 +302,7 @@ describe('dehydration and rehydration', () => { vi.fn<(...args: Array) => unknown>() await vi.waitFor(() => hydrationClient.prefetchQuery({ - queryKey: ['string', { key: ['string'], key2: 0 }], + queryKey: complexKey, queryFn: fetchDataAfterHydration, staleTime: 100, }), @@ -314,6 +314,10 @@ describe('dehydration and rehydration', () => { }) test('should only hydrate successful queries by default', async () => { + const successKey = queryKey() + const loadingKey = queryKey() + const errorKey = queryKey() + const consoleMock = vi.spyOn(console, 'error') consoleMock.mockImplementation(() => undefined) @@ -321,17 +325,17 @@ describe('dehydration and rehydration', () => { const queryClient = new QueryClient({ queryCache }) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['success'], + queryKey: successKey, queryFn: () => sleep(0).then(() => 'success'), }), ) queryClient.prefetchQuery({ - queryKey: ['loading'], + queryKey: loadingKey, queryFn: () => sleep(10000).then(() => 'loading'), }) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['error'], + queryKey: errorKey, queryFn: () => { throw new Error() }, @@ -347,9 +351,9 @@ describe('dehydration and rehydration', () => { const hydrationClient = new QueryClient({ queryCache: hydrationCache }) hydrate(hydrationClient, parsed) - expect(hydrationCache.find({ queryKey: ['success'] })).toBeTruthy() - expect(hydrationCache.find({ queryKey: ['loading'] })).toBeFalsy() - expect(hydrationCache.find({ queryKey: ['error'] })).toBeFalsy() + expect(hydrationCache.find({ queryKey: successKey })).toBeTruthy() + expect(hydrationCache.find({ queryKey: loadingKey })).toBeFalsy() + expect(hydrationCache.find({ queryKey: errorKey })).toBeFalsy() queryClient.clear() hydrationClient.clear() @@ -357,28 +361,30 @@ describe('dehydration and rehydration', () => { }) test('should filter queries via dehydrateQuery', async () => { + const stringKey = queryKey() + const numberKey = queryKey() const queryCache = new QueryCache() const queryClient = new QueryClient({ queryCache }) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['string'], + queryKey: stringKey, queryFn: () => sleep(0).then(() => 'string'), }), ) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['number'], + queryKey: numberKey, queryFn: () => sleep(0).then(() => 1), }), ) const dehydrated = dehydrate(queryClient, { - shouldDehydrateQuery: (query) => query.queryKey[0] !== 'string', + shouldDehydrateQuery: (query) => query.queryKey !== stringKey, }) // This is testing implementation details that can change and are not // part of the public API, but is important for keeping the payload small const dehydratedQuery = dehydrated.queries.find( - (query) => query.queryKey[0] === 'string', + (query) => query.queryKey === stringKey, ) expect(dehydratedQuery).toBeUndefined() @@ -390,19 +396,20 @@ describe('dehydration and rehydration', () => { const hydrationCache = new QueryCache() const hydrationClient = new QueryClient({ queryCache: hydrationCache }) hydrate(hydrationClient, parsed) - expect(hydrationCache.find({ queryKey: ['string'] })).toBeUndefined() - expect(hydrationCache.find({ queryKey: ['number'] })?.state.data).toBe(1) + expect(hydrationCache.find({ queryKey: stringKey })).toBeUndefined() + expect(hydrationCache.find({ queryKey: numberKey })?.state.data).toBe(1) queryClient.clear() hydrationClient.clear() }) test('should not overwrite query in cache if hydrated query is older', async () => { + const key = queryKey() const queryCache = new QueryCache() const queryClient = new QueryClient({ queryCache }) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['string'], + queryKey: key, queryFn: () => sleep(5).then(() => 'string-older'), }), ) @@ -416,13 +423,13 @@ describe('dehydration and rehydration', () => { const hydrationClient = new QueryClient({ queryCache: hydrationCache }) await vi.waitFor(() => hydrationClient.prefetchQuery({ - queryKey: ['string'], + queryKey: key, queryFn: () => sleep(5).then(() => 'string-newer'), }), ) hydrate(hydrationClient, parsed) - expect(hydrationCache.find({ queryKey: ['string'] })?.state.data).toBe( + expect(hydrationCache.find({ queryKey: key })?.state.data).toBe( 'string-newer', ) @@ -431,11 +438,12 @@ describe('dehydration and rehydration', () => { }) test('should overwrite query in cache if hydrated query is newer', async () => { + const key = queryKey() const hydrationCache = new QueryCache() const hydrationClient = new QueryClient({ queryCache: hydrationCache }) await vi.waitFor(() => hydrationClient.prefetchQuery({ - queryKey: ['string'], + queryKey: key, queryFn: () => sleep(5).then(() => 'string-older'), }), ) @@ -446,7 +454,7 @@ describe('dehydration and rehydration', () => { const queryClient = new QueryClient({ queryCache }) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['string'], + queryKey: key, queryFn: () => sleep(5).then(() => 'string-newer'), }), ) @@ -457,7 +465,7 @@ describe('dehydration and rehydration', () => { const parsed = JSON.parse(stringified) hydrate(hydrationClient, parsed) - expect(hydrationCache.find({ queryKey: ['string'] })?.state.data).toBe( + expect(hydrationCache.find({ queryKey: key })?.state.data).toBe( 'string-newer', ) @@ -466,6 +474,7 @@ describe('dehydration and rehydration', () => { }) test('should be able to dehydrate mutations and continue on hydration', async () => { + const key = queryKey() const consoleMock = vi.spyOn(console, 'error') consoleMock.mockImplementation(() => undefined) const onlineMock = mockOnlineManagerIsOnline(false) @@ -483,7 +492,7 @@ describe('dehydration and rehydration', () => { const serverClient = new QueryClient() - serverClient.setMutationDefaults(['addTodo'], { + serverClient.setMutationDefaults(key, { mutationFn: serverAddTodo, onMutate: serverOnMutate, onSuccess: serverOnSuccess, @@ -494,7 +503,7 @@ describe('dehydration and rehydration', () => { executeMutation( serverClient, { - mutationKey: ['addTodo'], + mutationKey: key, }, { text: 'text' }, ).catch(() => undefined) @@ -526,7 +535,7 @@ describe('dehydration and rehydration', () => { }) const clientOnSuccess = vi.fn() - client.setMutationDefaults(['addTodo'], { + client.setMutationDefaults(key, { mutationFn: clientAddTodo, onMutate: clientOnMutate, onSuccess: clientOnSuccess, @@ -545,7 +554,7 @@ describe('dehydration and rehydration', () => { { id: 2, text: 'text' }, { text: 'text' }, { optimisticTodo: { id: 1, text: 'text' } }, - { client: client, meta: undefined, mutationKey: ['addTodo'] }, + { client: client, meta: undefined, mutationKey: key }, ) client.clear() @@ -554,6 +563,7 @@ describe('dehydration and rehydration', () => { }) test('should not dehydrate mutations if dehydrateMutations is set to false', async () => { + const key = queryKey() const consoleMock = vi.spyOn(console, 'error') consoleMock.mockImplementation(() => undefined) @@ -563,7 +573,7 @@ describe('dehydration and rehydration', () => { const queryClient = new QueryClient() - queryClient.setMutationDefaults(['addTodo'], { + queryClient.setMutationDefaults(key, { mutationFn: serverAddTodo, retry: false, }) @@ -571,7 +581,7 @@ describe('dehydration and rehydration', () => { executeMutation( queryClient, { - mutationKey: ['addTodo'], + mutationKey: key, }, { text: 'text' }, ).catch(() => undefined) @@ -588,6 +598,7 @@ describe('dehydration and rehydration', () => { }) test('should not dehydrate mutation if mutation state is set to pause', async () => { + const key = queryKey() const consoleMock = vi.spyOn(console, 'error') consoleMock.mockImplementation(() => undefined) @@ -597,7 +608,7 @@ describe('dehydration and rehydration', () => { const queryClient = new QueryClient() - queryClient.setMutationDefaults(['addTodo'], { + queryClient.setMutationDefaults(key, { mutationFn: serverAddTodo, retry: 1, retryDelay: 20, @@ -606,7 +617,7 @@ describe('dehydration and rehydration', () => { executeMutation( queryClient, { - mutationKey: ['addTodo'], + mutationKey: key, }, { text: 'text' }, ).catch(() => undefined) @@ -643,6 +654,7 @@ describe('dehydration and rehydration', () => { }) test('should set the fetchStatus to idle when creating a query with dehydrate', async () => { + const key = queryKey() const queryCache = new QueryCache() const queryClient = new QueryClient({ queryCache }) @@ -663,16 +675,16 @@ describe('dehydration and rehydration', () => { } await queryClient.prefetchQuery({ - queryKey: ['string'], + queryKey: key, queryFn: () => customFetchData(), }) - queryClient.refetchQueries({ queryKey: ['string'] }) + queryClient.refetchQueries({ queryKey: key }) const dehydrated = dehydrate(queryClient) resolvePromise('string') expect( - dehydrated.queries.find((q) => q.queryHash === '["string"]')?.state + dehydrated.queries.find((q) => q.queryHash === JSON.stringify(key))?.state .fetchStatus, ).toBe('fetching') const stringified = JSON.stringify(dehydrated) @@ -682,17 +694,19 @@ describe('dehydration and rehydration', () => { const hydrationCache = new QueryCache() const hydrationClient = new QueryClient({ queryCache: hydrationCache }) hydrate(hydrationClient, parsed) - expect( - hydrationCache.find({ queryKey: ['string'] })?.state.fetchStatus, - ).toBe('idle') + expect(hydrationCache.find({ queryKey: key })?.state.fetchStatus).toBe( + 'idle', + ) }) test('should dehydrate and hydrate meta for queries', async () => { + const metaKey = queryKey() + const noMetaKey = queryKey() const queryCache = new QueryCache() const queryClient = new QueryClient({ queryCache }) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['meta'], + queryKey: metaKey, queryFn: () => Promise.resolve('meta'), meta: { some: 'meta', @@ -701,7 +715,7 @@ describe('dehydration and rehydration', () => { ) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['no-meta'], + queryKey: noMetaKey, queryFn: () => Promise.resolve('no-meta'), }), ) @@ -709,18 +723,22 @@ describe('dehydration and rehydration', () => { const dehydrated = dehydrate(queryClient) expect( - dehydrated.queries.find((q) => q.queryHash === '["meta"]')?.meta, + dehydrated.queries.find((q) => q.queryHash === JSON.stringify(metaKey)) + ?.meta, ).toEqual({ some: 'meta', }) expect( - dehydrated.queries.find((q) => q.queryHash === '["no-meta"]')?.meta, + dehydrated.queries.find((q) => q.queryHash === JSON.stringify(noMetaKey)) + ?.meta, ).toEqual(undefined) expect( Object.keys( - dehydrated.queries.find((q) => q.queryHash === '["no-meta"]')!, + dehydrated.queries.find( + (q) => q.queryHash === JSON.stringify(noMetaKey), + )!, ), ).not.toEqual(expect.arrayContaining(['meta'])) @@ -734,22 +752,24 @@ describe('dehydration and rehydration', () => { queryCache: hydrationCache, }) hydrate(hydrationClient, parsed) - expect(hydrationCache.find({ queryKey: ['meta'] })?.meta).toEqual({ + expect(hydrationCache.find({ queryKey: metaKey })?.meta).toEqual({ some: 'meta', }) - expect(hydrationCache.find({ queryKey: ['no-meta'] })?.meta).toEqual( + expect(hydrationCache.find({ queryKey: noMetaKey })?.meta).toEqual( undefined, ) }) test('should dehydrate and hydrate meta for mutations', async () => { + const metaKey = queryKey() + const noMetaKey = queryKey() const mutationCache = new MutationCache() const queryClient = new QueryClient({ mutationCache }) await executeMutation( queryClient, { - mutationKey: ['meta'], + mutationKey: metaKey, mutationFn: () => Promise.resolve('meta'), meta: { some: 'meta', @@ -761,7 +781,7 @@ describe('dehydration and rehydration', () => { await executeMutation( queryClient, { - mutationKey: ['no-meta'], + mutationKey: noMetaKey, mutationFn: () => Promise.resolve('no-meta'), }, undefined, @@ -793,19 +813,20 @@ describe('dehydration and rehydration', () => { mutationCache: hydrationCache, }) hydrate(hydrationClient, parsed) - expect(hydrationCache.find({ mutationKey: ['meta'] })?.meta).toEqual({ + expect(hydrationCache.find({ mutationKey: metaKey })?.meta).toEqual({ some: 'meta', }) - expect(hydrationCache.find({ mutationKey: ['no-meta'] })?.meta).toEqual( + expect(hydrationCache.find({ mutationKey: noMetaKey })?.meta).toEqual( undefined, ) }) test('should not change fetchStatus when updating a query with dehydrate', async () => { + const key = queryKey() const queryClient = new QueryClient() const options = { - queryKey: ['string'], + queryKey: key, queryFn: async () => { await sleep(10) return 'string' @@ -816,7 +837,7 @@ describe('dehydration and rehydration', () => { const dehydrated = dehydrate(queryClient) expect( - dehydrated.queries.find((q) => q.queryHash === '["string"]')?.state + dehydrated.queries.find((q) => q.queryHash === JSON.stringify(key))?.state .fetchStatus, ).toBe('idle') const stringified = JSON.stringify(dehydrated) @@ -828,23 +849,24 @@ describe('dehydration and rehydration', () => { const promise = hydrationClient.prefetchQuery(options) hydrate(hydrationClient, parsed) - expect( - hydrationCache.find({ queryKey: ['string'] })?.state.fetchStatus, - ).toBe('fetching') + expect(hydrationCache.find({ queryKey: key })?.state.fetchStatus).toBe( + 'fetching', + ) await vi.waitFor(() => promise) - expect( - hydrationCache.find({ queryKey: ['string'] })?.state.fetchStatus, - ).toBe('idle') + expect(hydrationCache.find({ queryKey: key })?.state.fetchStatus).toBe( + 'idle', + ) }) test('should dehydrate and hydrate mutation scopes', () => { + const key = queryKey() const queryClient = new QueryClient() const onlineMock = mockOnlineManagerIsOnline(false) void executeMutation( queryClient, { - mutationKey: ['mutation'], + mutationKey: key, mutationFn: () => { return Promise.resolve('mutation') }, @@ -872,6 +894,8 @@ describe('dehydration and rehydration', () => { }) test('should dehydrate promises for pending queries', async () => { + const successKey = queryKey() + const pendingKey = queryKey() const queryCache = new QueryCache() const queryClient = new QueryClient({ queryCache, @@ -879,13 +903,13 @@ describe('dehydration and rehydration', () => { }) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['success'], + queryKey: successKey, queryFn: () => sleep(0).then(() => 'success'), }), ) const promise = queryClient.prefetchQuery({ - queryKey: ['pending'], + queryKey: pendingKey, queryFn: () => sleep(10).then(() => 'pending'), }) const dehydrated = dehydrate(queryClient) @@ -898,6 +922,8 @@ describe('dehydration and rehydration', () => { }) test('should hydrate promises even without observers', async () => { + const successKey = queryKey() + const pendingKey = queryKey() const queryCache = new QueryCache() const queryClient = new QueryClient({ queryCache, @@ -905,13 +931,13 @@ describe('dehydration and rehydration', () => { }) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['success'], + queryKey: successKey, queryFn: () => sleep(0).then(() => 'success'), }), ) void queryClient.prefetchQuery({ - queryKey: ['pending'], + queryKey: pendingKey, queryFn: () => sleep(20).then(() => 'pending'), }) const dehydrated = dehydrate(queryClient) @@ -925,30 +951,28 @@ describe('dehydration and rehydration', () => { hydrate(hydrationClient, dehydrated) - expect(hydrationCache.find({ queryKey: ['success'] })?.state.data).toBe( + expect(hydrationCache.find({ queryKey: successKey })?.state.data).toBe( 'success', ) - expect(hydrationCache.find({ queryKey: ['pending'] })?.state).toMatchObject( - { - data: undefined, - dataUpdateCount: 0, - dataUpdatedAt: 0, - error: null, - errorUpdateCount: 0, - errorUpdatedAt: 0, - fetchFailureCount: 0, - fetchFailureReason: null, - fetchMeta: null, - fetchStatus: 'fetching', - isInvalidated: false, - status: 'pending', - }, - ) + expect(hydrationCache.find({ queryKey: pendingKey })?.state).toMatchObject({ + data: undefined, + dataUpdateCount: 0, + dataUpdatedAt: 0, + error: null, + errorUpdateCount: 0, + errorUpdatedAt: 0, + fetchFailureCount: 0, + fetchFailureReason: null, + fetchMeta: null, + fetchStatus: 'fetching', + isInvalidated: false, + status: 'pending', + }) await vi.waitFor(() => expect( - hydrationCache.find({ queryKey: ['pending'] })?.state, + hydrationCache.find({ queryKey: pendingKey })?.state, ).toMatchObject({ data: 'pending', dataUpdateCount: 1, @@ -967,6 +991,7 @@ describe('dehydration and rehydration', () => { }) test('should transform promise result', async () => { + const key = queryKey() const queryClient = new QueryClient({ defaultOptions: { dehydrate: { @@ -977,7 +1002,7 @@ describe('dehydration and rehydration', () => { }) const promise = queryClient.prefetchQuery({ - queryKey: ['transformedStringToDate'], + queryKey: key, queryFn: () => sleep(20).then(() => new Date('2024-01-01T00:00:00.000Z')), }) const dehydrated = dehydrate(queryClient) @@ -994,15 +1019,14 @@ describe('dehydration and rehydration', () => { hydrate(hydrationClient, dehydrated) await vi.waitFor(() => promise) await vi.waitFor(() => - expect( - hydrationClient.getQueryData(['transformedStringToDate']), - ).toBeInstanceOf(Date), + expect(hydrationClient.getQueryData(key)).toBeInstanceOf(Date), ) queryClient.clear() }) test('should transform query data if promise is already resolved', async () => { + const key = queryKey() const queryClient = new QueryClient({ defaultOptions: { dehydrate: { @@ -1013,7 +1037,7 @@ describe('dehydration and rehydration', () => { }) const promise = queryClient.prefetchQuery({ - queryKey: ['transformedStringToDate'], + queryKey: key, queryFn: () => sleep(0).then(() => new Date('2024-01-01T00:00:00.000Z')), }) await vi.advanceTimersByTimeAsync(20) @@ -1030,15 +1054,14 @@ describe('dehydration and rehydration', () => { hydrate(hydrationClient, dehydrated) await vi.waitFor(() => promise) await vi.waitFor(() => - expect( - hydrationClient.getQueryData(['transformedStringToDate']), - ).toBeInstanceOf(Date), + expect(hydrationClient.getQueryData(key)).toBeInstanceOf(Date), ) queryClient.clear() }) test('should overwrite query in cache if hydrated query is newer (with transformation)', async () => { + const key = queryKey() const hydrationClient = new QueryClient({ defaultOptions: { hydrate: { @@ -1048,7 +1071,7 @@ describe('dehydration and rehydration', () => { }) await vi.waitFor(() => hydrationClient.prefetchQuery({ - queryKey: ['date'], + queryKey: key, queryFn: () => sleep(5).then(() => new Date('2024-01-01T00:00:00.000Z')), }), @@ -1066,7 +1089,7 @@ describe('dehydration and rehydration', () => { }) await vi.waitFor(() => queryClient.prefetchQuery({ - queryKey: ['date'], + queryKey: key, queryFn: () => sleep(10).then(() => new Date('2024-01-02T00:00:00.000Z')), }), @@ -1077,7 +1100,7 @@ describe('dehydration and rehydration', () => { hydrate(hydrationClient, dehydrated) - expect(hydrationClient.getQueryData(['date'])).toStrictEqual( + expect(hydrationClient.getQueryData(key)).toStrictEqual( new Date('2024-01-02T00:00:00.000Z'), ) @@ -1086,6 +1109,7 @@ describe('dehydration and rehydration', () => { }) test('should overwrite query in cache if hydrated query is newer (with promise)', async () => { + const key = queryKey() // --- server --- const serverQueryClient = new QueryClient({ @@ -1097,7 +1121,7 @@ describe('dehydration and rehydration', () => { }) const promise = serverQueryClient.prefetchQuery({ - queryKey: ['data'], + queryKey: key, queryFn: async () => { await sleep(10) return 'server data' @@ -1110,13 +1134,13 @@ describe('dehydration and rehydration', () => { const clientQueryClient = new QueryClient() - clientQueryClient.setQueryData(['data'], 'old data', { updatedAt: 10 }) + clientQueryClient.setQueryData(key, 'old data', { updatedAt: 10 }) hydrate(clientQueryClient, dehydrated) await vi.waitFor(() => promise) await vi.waitFor(() => - expect(clientQueryClient.getQueryData(['data'])).toBe('server data'), + expect(clientQueryClient.getQueryData(key)).toBe('server data'), ) clientQueryClient.clear() @@ -1124,6 +1148,7 @@ describe('dehydration and rehydration', () => { }) test('should not overwrite query in cache if existing query is newer (with promise)', async () => { + const key = queryKey() // --- server --- const serverQueryClient = new QueryClient({ @@ -1135,7 +1160,7 @@ describe('dehydration and rehydration', () => { }) const promise = serverQueryClient.prefetchQuery({ - queryKey: ['data'], + queryKey: key, queryFn: async () => { await sleep(10) return 'server data' @@ -1155,7 +1180,7 @@ describe('dehydration and rehydration', () => { const clientQueryClient = new QueryClient() - clientQueryClient.setQueryData(['data'], 'newer data', { + clientQueryClient.setQueryData(key, 'newer data', { updatedAt: Date.now(), }) @@ -1165,12 +1190,10 @@ describe('dehydration and rehydration', () => { // to end up in the cache, so for the test to fail properly on regressions, // wait for the fetchStatus to be idle await vi.waitFor(() => - expect(clientQueryClient.getQueryState(['data'])?.fetchStatus).toBe( - 'idle', - ), + expect(clientQueryClient.getQueryState(key)?.fetchStatus).toBe('idle'), ) await vi.waitFor(() => - expect(clientQueryClient.getQueryData(['data'])).toBe('newer data'), + expect(clientQueryClient.getQueryData(key)).toBe('newer data'), ) clientQueryClient.clear() @@ -1178,6 +1201,7 @@ describe('dehydration and rehydration', () => { }) test('should overwrite data when a new promise is streamed in', async () => { + const key = queryKey() const serializeDataMock = vi.fn((data: any) => data) const deserializeDataMock = vi.fn((data: any) => data) @@ -1193,7 +1217,7 @@ describe('dehydration and rehydration', () => { }) const query = { - queryKey: ['data'], + queryKey: key, queryFn: async () => { await sleep(10) return countRef.current @@ -1254,6 +1278,7 @@ describe('dehydration and rehydration', () => { }) test('should not redact errors when shouldRedactErrors returns false', async () => { + const key = queryKey() const queryCache = new QueryCache() const queryClient = new QueryClient({ queryCache, @@ -1269,7 +1294,7 @@ describe('dehydration and rehydration', () => { const promise = queryClient .prefetchQuery({ - queryKey: ['error'], + queryKey: key, queryFn: () => Promise.reject(testError), retry: false, }) @@ -1283,6 +1308,7 @@ describe('dehydration and rehydration', () => { }) test('should handle errors in promises for pending queries', async () => { + const key = queryKey() const consoleMock = vi.spyOn(console, 'error') consoleMock.mockImplementation(() => undefined) @@ -1298,7 +1324,7 @@ describe('dehydration and rehydration', () => { const promise = queryClient .prefetchQuery({ - queryKey: ['error'], + queryKey: key, queryFn: () => Promise.reject(new Error('test error')), retry: false, }) @@ -1314,6 +1340,7 @@ describe('dehydration and rehydration', () => { }) test('should log error in development environment when redacting errors', async () => { + const key = queryKey() const originalNodeEnv = process.env.NODE_ENV process.env.NODE_ENV = 'development' @@ -1335,7 +1362,7 @@ describe('dehydration and rehydration', () => { const promise = queryClient .prefetchQuery({ - queryKey: ['error'], + queryKey: key, queryFn: () => Promise.reject(testError), retry: false, }) @@ -1364,6 +1391,7 @@ describe('dehydration and rehydration', () => { // server, but the client renders a Suspense fallback, only to immediately show // the data again. test('should rehydrate synchronous thenable immediately', async () => { + const key = queryKey() // --- server --- const serverQueryClient = new QueryClient({ @@ -1374,7 +1402,7 @@ describe('dehydration and rehydration', () => { }, }) const originalPromise = serverQueryClient.prefetchQuery({ - queryKey: ['data'], + queryKey: key, queryFn: () => null, }) @@ -1394,7 +1422,7 @@ describe('dehydration and rehydration', () => { hydrate(clientQueryClient, dehydrated) // If data is already resolved, it should end up in the cache immediately - expect(clientQueryClient.getQueryData(['data'])).toBe('server data') + expect(clientQueryClient.getQueryData(key)).toBe('server data') // Need to await the original promise or else it will get a cancellation // error and test will fail diff --git a/packages/query-core/src/__tests__/query.test.tsx b/packages/query-core/src/__tests__/query.test.tsx index dfb8c0381a..646ec62193 100644 --- a/packages/query-core/src/__tests__/query.test.tsx +++ b/packages/query-core/src/__tests__/query.test.tsx @@ -482,9 +482,10 @@ describe('query', () => { }) test('should reset to default state when created from hydration', async () => { + const key = queryKey() const client = new QueryClient() await client.prefetchQuery({ - queryKey: ['string'], + queryKey: key, queryFn: () => Promise.resolve('string'), }) @@ -493,12 +494,12 @@ describe('query', () => { const hydrationClient = new QueryClient() hydrate(hydrationClient, dehydrated) - expect(hydrationClient.getQueryData(['string'])).toBe('string') + expect(hydrationClient.getQueryData(key)).toBe('string') - const query = hydrationClient.getQueryCache().find({ queryKey: ['string'] }) + const query = hydrationClient.getQueryCache().find({ queryKey: key }) query?.reset() - expect(hydrationClient.getQueryData(['string'])).toBe(undefined) + expect(hydrationClient.getQueryData(key)).toBe(undefined) }) test('should be able to refetch a cancelled query', async () => { diff --git a/packages/query-core/src/__tests__/queryCache.test.tsx b/packages/query-core/src/__tests__/queryCache.test.tsx index 821efa8061..67c807a838 100644 --- a/packages/query-core/src/__tests__/queryCache.test.tsx +++ b/packages/query-core/src/__tests__/queryCache.test.tsx @@ -125,18 +125,21 @@ describe('queryCache', () => { const testClient = new QueryClient({ queryCache: testCache }) + const key1 = queryKey() + const key2 = queryKey() + const key3 = queryKey() testClient.prefetchQuery({ - queryKey: ['key1'], + queryKey: key1, queryFn: () => sleep(100).then(() => 'data1'), }) expect(testCache.findAll().length).toBe(1) testClient.prefetchQuery({ - queryKey: ['key2'], + queryKey: key2, queryFn: () => sleep(100).then(() => 'data2'), }) expect(testCache.findAll().length).toBe(2) testClient.prefetchQuery({ - queryKey: ['key3'], + queryKey: key3, queryFn: () => sleep(100).then(() => 'data3'), }) await vi.advanceTimersByTimeAsync(100) diff --git a/packages/query-core/src/__tests__/queryClient.test-d.tsx b/packages/query-core/src/__tests__/queryClient.test-d.tsx index 8a3be1a9e2..4cd092ddd6 100644 --- a/packages/query-core/src/__tests__/queryClient.test-d.tsx +++ b/packages/query-core/src/__tests__/queryClient.test-d.tsx @@ -1,4 +1,5 @@ import { assertType, describe, expectTypeOf, it } from 'vitest' +import { queryKey } from '@tanstack/query-test-utils' import { QueryClient } from '../queryClient' import type { MutationFilters, QueryFilters, Updater } from '../utils' import type { Mutation } from '../mutation' @@ -18,25 +19,25 @@ import type { describe('getQueryData', () => { it('should be typed if key is tagged', () => { - const queryKey = ['key'] as DataTag, number> + const key = ['key'] as DataTag, number> const queryClient = new QueryClient() - const data = queryClient.getQueryData(queryKey) + const data = queryClient.getQueryData(key) expectTypeOf(data).toEqualTypeOf() }) it('should infer unknown if key is not tagged', () => { - const queryKey = ['key'] as const + const key = ['key'] as const const queryClient = new QueryClient() - const data = queryClient.getQueryData(queryKey) + const data = queryClient.getQueryData(key) expectTypeOf(data).toEqualTypeOf() }) it('should infer passed generic if passed', () => { - const queryKey = ['key'] as const + const key = ['key'] as const const queryClient = new QueryClient() - const data = queryClient.getQueryData(queryKey) + const data = queryClient.getQueryData(key) expectTypeOf(data).toEqualTypeOf() }) @@ -51,9 +52,9 @@ describe('getQueryData', () => { describe('setQueryData', () => { it('updater should be typed if key is tagged', () => { - const queryKey = ['key'] as DataTag, number> + const key = ['key'] as DataTag, number> const queryClient = new QueryClient() - const data = queryClient.setQueryData(queryKey, (prev) => { + const data = queryClient.setQueryData(key, (prev) => { expectTypeOf(prev).toEqualTypeOf() return prev }) @@ -62,24 +63,24 @@ describe('setQueryData', () => { }) it('value should be typed if key is tagged', () => { - const queryKey = ['key'] as DataTag, number> + const key = ['key'] as DataTag, number> const queryClient = new QueryClient() // @ts-expect-error value should be a number - queryClient.setQueryData(queryKey, '1') + queryClient.setQueryData(key, '1') // @ts-expect-error value should be a number - queryClient.setQueryData(queryKey, () => '1') + queryClient.setQueryData(key, () => '1') - const data = queryClient.setQueryData(queryKey, 1) + const data = queryClient.setQueryData(key, 1) expectTypeOf(data).toEqualTypeOf() }) it('should infer unknown for updater if key is not tagged', () => { - const queryKey = ['key'] as const + const key = ['key'] as const const queryClient = new QueryClient() - const data = queryClient.setQueryData(queryKey, (prev) => { + const data = queryClient.setQueryData(key, (prev) => { expectTypeOf(prev).toEqualTypeOf() return prev }) @@ -88,17 +89,17 @@ describe('setQueryData', () => { }) it('should infer unknown for value if key is not tagged', () => { - const queryKey = ['key'] as const + const key = ['key'] as const const queryClient = new QueryClient() - const data = queryClient.setQueryData(queryKey, 'foo') + const data = queryClient.setQueryData(key, 'foo') expectTypeOf(data).toEqualTypeOf() }) it('should infer passed generic if passed', () => { - const queryKey = ['key'] as const + const key = ['key'] as const const queryClient = new QueryClient() - const data = queryClient.setQueryData(queryKey, (prev) => { + const data = queryClient.setQueryData(key, (prev) => { expectTypeOf(prev).toEqualTypeOf() return prev }) @@ -107,21 +108,21 @@ describe('setQueryData', () => { }) it('should infer passed generic for value', () => { - const queryKey = ['key'] as const + const key = ['key'] as const const queryClient = new QueryClient() - const data = queryClient.setQueryData(queryKey, 'foo') + const data = queryClient.setQueryData(key, 'foo') expectTypeOf(data).toEqualTypeOf() }) it('should preserve updater parameter type inference when used in functions with explicit return types', () => { - const queryKey = ['key'] as DataTag, number> + const key = ['key'] as DataTag, number> const queryClient = new QueryClient() // Simulate usage inside a function with explicit return type // The outer function returns 'unknown' but this shouldn't affect the updater's type inference ;(() => - queryClient.setQueryData(queryKey, (data) => { + queryClient.setQueryData(key, (data) => { expectTypeOf(data).toEqualTypeOf() return data })) satisfies () => unknown @@ -130,26 +131,26 @@ describe('setQueryData', () => { describe('getQueryState', () => { it('should be loose typed without tag', () => { - const queryKey = ['key'] as const + const key = ['key'] as const const queryClient = new QueryClient() - const data = queryClient.getQueryState(queryKey) + const data = queryClient.getQueryState(key) expectTypeOf(data).toEqualTypeOf | undefined>() }) it('should be typed if key is tagged', () => { - const queryKey = ['key'] as DataTag, number> + const key = ['key'] as DataTag, number> const queryClient = new QueryClient() - const data = queryClient.getQueryState(queryKey) + const data = queryClient.getQueryState(key) expectTypeOf(data).toEqualTypeOf | undefined>() }) it('should be typed including error if key is tagged', () => { type CustomError = Error & { customError: string } - const queryKey = ['key'] as DataTag, number, CustomError> + const key = ['key'] as DataTag, number, CustomError> const queryClient = new QueryClient() - const data = queryClient.getQueryState(queryKey) + const data = queryClient.getQueryState(key) expectTypeOf(data).toEqualTypeOf< QueryState | undefined @@ -160,7 +161,7 @@ describe('getQueryState', () => { describe('fetchInfiniteQuery', () => { it('should allow passing pages', async () => { const data = await new QueryClient().fetchInfiniteQuery({ - queryKey: ['key'], + queryKey: queryKey(), queryFn: () => Promise.resolve('string'), getNextPageParam: () => 1, initialPageParam: 1, @@ -252,7 +253,7 @@ describe('fully typed usage', () => { return false }, } - const queryKey = queryFilters.queryKey! + const filterKey = queryFilters.queryKey! const mutationFilters: MutationFilters = { predicate(mutation) { @@ -268,10 +269,10 @@ describe('fully typed usage', () => { // Method type tests // - const state = queryClient.getQueryState(queryKey) + const state = queryClient.getQueryState(filterKey) expectTypeOf(state).toEqualTypeOf | undefined>() - const queryData1 = queryClient.getQueryData(queryKey) + const queryData1 = queryClient.getQueryData(filterKey) expectTypeOf(queryData1).toEqualTypeOf() const queryData2 = await queryClient.ensureQueryData(queryOptions) @@ -282,9 +283,9 @@ describe('fully typed usage', () => { Array<[ReadonlyArray, unknown]> >() - const queryData3 = queryClient.setQueryData(queryKey, { foo: '' }) + const queryData3 = queryClient.setQueryData(filterKey, { foo: '' }) type SetQueryDataUpdaterArg = Parameters< - typeof queryClient.setQueryData + typeof queryClient.setQueryData >[1] expectTypeOf().toEqualTypeOf< @@ -302,7 +303,7 @@ describe('fully typed usage', () => { >() expectTypeOf(queriesData2).toEqualTypeOf>() - const queryState = queryClient.getQueryState(queryKey) + const queryState = queryClient.getQueryState(filterKey) expectTypeOf(queryState).toEqualTypeOf< QueryState | undefined >() @@ -343,7 +344,7 @@ describe('fully typed usage', () => { }, }) - const queryDefaults = queryClient.getQueryDefaults(queryKey) + const queryDefaults = queryClient.getQueryDefaults(filterKey) expectTypeOf(queryDefaults).toEqualTypeOf< OmitKeyof, 'queryKey'> >() @@ -358,7 +359,7 @@ describe('fully typed usage', () => { queryClient.invalidateQueries(queryFilters) queryClient.refetchQueries(queryFilters) queryClient.prefetchInfiniteQuery(fetchInfiniteQueryOptions) - queryClient.setQueryDefaults(queryKey, {} as any) + queryClient.setQueryDefaults(filterKey, {} as any) queryClient.getMutationDefaults(mutationKey) }) @@ -391,7 +392,7 @@ describe('fully typed usage', () => { return false }, } - const queryKey = queryFilters.queryKey! + const filterKey = queryFilters.queryKey! const mutationFilters: MutationFilters = { predicate(mutation) { @@ -407,12 +408,12 @@ describe('fully typed usage', () => { // Method type tests // - const state = queryClient.getQueryState(queryKey) + const state = queryClient.getQueryState(filterKey) expectTypeOf(state).toEqualTypeOf< QueryState | undefined >() - const queryData1 = queryClient.getQueryData(queryKey) + const queryData1 = queryClient.getQueryData(filterKey) expectTypeOf(queryData1).toEqualTypeOf() const queryData2 = await queryClient.ensureQueryData(queryOptions) @@ -421,9 +422,9 @@ describe('fully typed usage', () => { const queriesData = queryClient.getQueriesData(queryFilters) expectTypeOf(queriesData).toEqualTypeOf>() - const queryData3 = queryClient.setQueryData(queryKey, { foo: '' }) + const queryData3 = queryClient.setQueryData(filterKey, { foo: '' }) type SetQueryDataUpdaterArg = Parameters< - typeof queryClient.setQueryData + typeof queryClient.setQueryData >[1] expectTypeOf().toEqualTypeOf< @@ -441,7 +442,7 @@ describe('fully typed usage', () => { >() expectTypeOf(queriesData2).toEqualTypeOf>() - const queryState = queryClient.getQueryState(queryKey) + const queryState = queryClient.getQueryState(filterKey) expectTypeOf(queryState).toEqualTypeOf< QueryState | undefined >() @@ -488,7 +489,7 @@ describe('fully typed usage', () => { }, }) - const queryDefaults = queryClient.getQueryDefaults(queryKey) + const queryDefaults = queryClient.getQueryDefaults(filterKey) expectTypeOf(queryDefaults).toEqualTypeOf< OmitKeyof, 'queryKey'> >() @@ -503,7 +504,7 @@ describe('fully typed usage', () => { queryClient.invalidateQueries(queryFilters) queryClient.refetchQueries(queryFilters) queryClient.prefetchInfiniteQuery(fetchInfiniteQueryOptions) - queryClient.setQueryDefaults(queryKey, {} as any) + queryClient.setQueryDefaults(filterKey, {} as any) queryClient.getMutationDefaults(mutationKey) }) }) @@ -526,10 +527,10 @@ describe('invalidateQueries', () => { }) }) it('predicate should be typed if key is tagged', () => { - const queryKey = ['key'] as DataTag, number> + const key = ['key'] as DataTag, number> const queryClient = new QueryClient() queryClient.invalidateQueries({ - queryKey, + queryKey: key, predicate: (query) => { expectTypeOf(query.state.data).toEqualTypeOf() expectTypeOf(query.queryKey).toEqualTypeOf() @@ -541,10 +542,10 @@ describe('invalidateQueries', () => { describe('cancelQueries', () => { it('predicate should be typed if key is tagged', () => { - const queryKey = ['key'] as DataTag, number> + const key = ['key'] as DataTag, number> const queryClient = new QueryClient() queryClient.cancelQueries({ - queryKey, + queryKey: key, predicate: (query) => { expectTypeOf(query.state.data).toEqualTypeOf() expectTypeOf(query.queryKey).toEqualTypeOf() @@ -556,10 +557,10 @@ describe('cancelQueries', () => { describe('removeQueries', () => { it('predicate should be typed if key is tagged', () => { - const queryKey = ['key'] as DataTag, number> + const key = ['key'] as DataTag, number> const queryClient = new QueryClient() queryClient.removeQueries({ - queryKey, + queryKey: key, predicate: (query) => { expectTypeOf(query.state.data).toEqualTypeOf() expectTypeOf(query.queryKey).toEqualTypeOf() @@ -571,10 +572,10 @@ describe('removeQueries', () => { describe('refetchQueries', () => { it('predicate should be typed if key is tagged', () => { - const queryKey = ['key'] as DataTag, number> + const key = ['key'] as DataTag, number> const queryClient = new QueryClient() queryClient.refetchQueries({ - queryKey, + queryKey: key, predicate: (query) => { expectTypeOf(query.state.data).toEqualTypeOf() expectTypeOf(query.queryKey).toEqualTypeOf() @@ -586,10 +587,10 @@ describe('refetchQueries', () => { describe('resetQueries', () => { it('predicate should be typed if key is tagged', () => { - const queryKey = ['key'] as DataTag, number> + const key = ['key'] as DataTag, number> const queryClient = new QueryClient() queryClient.resetQueries({ - queryKey, + queryKey: key, predicate: (query) => { expectTypeOf(query.state.data).toEqualTypeOf() expectTypeOf(query.queryKey).toEqualTypeOf() @@ -600,24 +601,24 @@ describe('resetQueries', () => { }) type SuccessCallback = () => unknown it('should infer types correctly with expression body arrow functions', () => { - const queryKey = ['key'] as DataTag, number> + const key = ['key'] as DataTag, number> const queryClient = new QueryClient() // @ts-expect-error const callbackTest: SuccessCallback = () => - queryClient.setQueryData(queryKey, (data) => { + queryClient.setQueryData(key, (data) => { expectTypeOf(data).toEqualTypeOf() return data }) }) it('should infer types correctly with block body arrow functions', () => { - const queryKey = ['key'] as DataTag, number> + const key = ['key'] as DataTag, number> const queryClient = new QueryClient() // @ts-expect-error const callbackTest2: SuccessCallback = () => { - queryClient.setQueryData(queryKey, (data) => { + queryClient.setQueryData(key, (data) => { expectTypeOf(data).toEqualTypeOf() return data }) diff --git a/packages/query-core/src/__tests__/queryObserver.test-d.tsx b/packages/query-core/src/__tests__/queryObserver.test-d.tsx index f248c393de..5d929e40ad 100644 --- a/packages/query-core/src/__tests__/queryObserver.test-d.tsx +++ b/packages/query-core/src/__tests__/queryObserver.test-d.tsx @@ -122,7 +122,7 @@ describe('queryObserver', () => { } new QueryObserver(new QueryClient(), { - queryKey: ['key'], + queryKey: queryKey(), placeholderData: (_, previousQuery) => { if (previousQuery) { expectTypeOf( @@ -138,7 +138,7 @@ describe('queryObserver', () => { const queryData = { foo: 'bar' } as const new QueryObserver(new QueryClient(), { - queryKey: ['key'], + queryKey: queryKey(), queryFn: () => queryData, select: (data) => data.foo, placeholderData: (previousData) => { diff --git a/packages/query-core/src/__tests__/utils.test.tsx b/packages/query-core/src/__tests__/utils.test.tsx index 9cee1b4642..f9b0ee4fa0 100644 --- a/packages/query-core/src/__tests__/utils.test.tsx +++ b/packages/query-core/src/__tests__/utils.test.tsx @@ -1,4 +1,5 @@ import { describe, expect, it, vi } from 'vitest' +import { queryKey } from '@tanstack/query-test-utils' import { QueryClient } from '..' import { addToEnd, @@ -19,21 +20,21 @@ import { Mutation } from '../mutation' describe('core/utils', () => { describe('hashQueryKeyByOptions', () => { it('should use custom hash function when provided in options', () => { - const queryKey = ['test', { a: 1, b: 2 }] + const key = ['test', { a: 1, b: 2 }] const customHashFn = vi.fn(() => 'custom-hash') - const result = hashQueryKeyByOptions(queryKey, { + const result = hashQueryKeyByOptions(key, { queryKeyHashFn: customHashFn, }) - expect(customHashFn).toHaveBeenCalledWith(queryKey) + expect(customHashFn).toHaveBeenCalledWith(key) expect(result).toEqual('custom-hash') }) it('should use default hash function when no options provided', () => { - const queryKey = ['test', { a: 1, b: 2 }] - const defaultResult = hashKey(queryKey) - const result = hashQueryKeyByOptions(queryKey) + const key = ['test', { a: 1, b: 2 }] + const defaultResult = hashKey(key) + const result = hashQueryKeyByOptions(key) expect(result).toEqual(defaultResult) }) @@ -420,7 +421,7 @@ describe('core/utils', () => { describe('matchMutation', () => { it('should return false if mutationKey options is undefined', () => { - const filters = { mutationKey: ['key1'] } + const filters = { mutationKey: queryKey() } const queryClient = new QueryClient() const mutation = new Mutation({ client: queryClient,