@tanstack/query-core 5.59.17 → 5.60.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/build/legacy/queriesObserver.cjs +16 -10
  2. package/build/legacy/queriesObserver.cjs.map +1 -1
  3. package/build/legacy/queriesObserver.js +16 -10
  4. package/build/legacy/queriesObserver.js.map +1 -1
  5. package/build/modern/queriesObserver.cjs +13 -9
  6. package/build/modern/queriesObserver.cjs.map +1 -1
  7. package/build/modern/queriesObserver.js +13 -9
  8. package/build/modern/queriesObserver.js.map +1 -1
  9. package/package.json +3 -2
  10. package/src/queriesObserver.ts +21 -12
  11. package/src/__tests__/OmitKeyof.test-d.ts +0 -175
  12. package/src/__tests__/focusManager.test.tsx +0 -163
  13. package/src/__tests__/hydration.test.tsx +0 -1069
  14. package/src/__tests__/infiniteQueryBehavior.test.tsx +0 -427
  15. package/src/__tests__/infiniteQueryObserver.test-d.tsx +0 -64
  16. package/src/__tests__/infiniteQueryObserver.test.tsx +0 -198
  17. package/src/__tests__/mutationCache.test.tsx +0 -376
  18. package/src/__tests__/mutationObserver.test.tsx +0 -326
  19. package/src/__tests__/mutations.test.tsx +0 -603
  20. package/src/__tests__/notifyManager.test.tsx +0 -85
  21. package/src/__tests__/onlineManager.test.tsx +0 -168
  22. package/src/__tests__/queriesObserver.test.tsx +0 -267
  23. package/src/__tests__/query.test.tsx +0 -1049
  24. package/src/__tests__/queryCache.test.tsx +0 -350
  25. package/src/__tests__/queryClient.test-d.tsx +0 -156
  26. package/src/__tests__/queryClient.test.tsx +0 -2031
  27. package/src/__tests__/queryObserver.test-d.tsx +0 -108
  28. package/src/__tests__/queryObserver.test.tsx +0 -1236
  29. package/src/__tests__/utils.test.tsx +0 -468
  30. package/src/__tests__/utils.ts +0 -59
@@ -1,350 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
2
- import { waitFor } from '@testing-library/react'
3
- import { QueryCache, QueryClient, QueryObserver } from '..'
4
- import { createQueryClient, queryKey, sleep } from './utils'
5
-
6
- describe('queryCache', () => {
7
- let queryClient: QueryClient
8
- let queryCache: QueryCache
9
-
10
- beforeEach(() => {
11
- queryClient = createQueryClient()
12
- queryCache = queryClient.getQueryCache()
13
- })
14
-
15
- afterEach(() => {
16
- queryClient.clear()
17
- })
18
-
19
- describe('subscribe', () => {
20
- test('should pass the correct query', async () => {
21
- const key = queryKey()
22
- const subscriber = vi.fn()
23
- const unsubscribe = queryCache.subscribe(subscriber)
24
- queryClient.setQueryData(key, 'foo')
25
- const query = queryCache.find({ queryKey: key })
26
- await sleep(1)
27
- expect(subscriber).toHaveBeenCalledWith({ query, type: 'added' })
28
- unsubscribe()
29
- })
30
-
31
- test('should notify listeners when new query is added', async () => {
32
- const key = queryKey()
33
- const callback = vi.fn()
34
- queryCache.subscribe(callback)
35
- queryClient.prefetchQuery({ queryKey: key, queryFn: () => 'data' })
36
- await sleep(100)
37
- expect(callback).toHaveBeenCalled()
38
- })
39
-
40
- test('should notify query cache when a query becomes stale', async () => {
41
- const key = queryKey()
42
- const events: Array<string> = []
43
- const queries: Array<unknown> = []
44
- const unsubscribe = queryCache.subscribe((event) => {
45
- events.push(event.type)
46
- queries.push(event.query)
47
- })
48
-
49
- const observer = new QueryObserver(queryClient, {
50
- queryKey: key,
51
- queryFn: () => 'data',
52
- staleTime: 10,
53
- })
54
-
55
- const unsubScribeObserver = observer.subscribe(vi.fn())
56
-
57
- await waitFor(() => {
58
- expect(events.length).toBe(8)
59
- })
60
-
61
- expect(events).toEqual([
62
- 'added', // 1. Query added -> loading
63
- 'observerResultsUpdated', // 2. Observer result updated -> loading
64
- 'observerAdded', // 3. Observer added
65
- 'observerResultsUpdated', // 4. Observer result updated -> fetching
66
- 'updated', // 5. Query updated -> fetching
67
- 'observerResultsUpdated', // 6. Observer result updated -> success
68
- 'updated', // 7. Query updated -> success
69
- 'observerResultsUpdated', // 8. Observer result updated -> stale
70
- ])
71
-
72
- queries.forEach((query) => {
73
- expect(query).toBeDefined()
74
- })
75
-
76
- unsubscribe()
77
- unsubScribeObserver()
78
- })
79
-
80
- test('should include the queryCache and query when notifying listeners', async () => {
81
- const key = queryKey()
82
- const callback = vi.fn()
83
- queryCache.subscribe(callback)
84
- queryClient.prefetchQuery({ queryKey: key, queryFn: () => 'data' })
85
- const query = queryCache.find({ queryKey: key })
86
- await sleep(100)
87
- expect(callback).toHaveBeenCalledWith({ query, type: 'added' })
88
- })
89
-
90
- test('should notify subscribers when new query with initialData is added', async () => {
91
- const key = queryKey()
92
- const callback = vi.fn()
93
- queryCache.subscribe(callback)
94
- queryClient.prefetchQuery({
95
- queryKey: key,
96
- queryFn: () => 'data',
97
- initialData: 'initial',
98
- })
99
- await sleep(100)
100
- expect(callback).toHaveBeenCalled()
101
- })
102
-
103
- test('should be able to limit cache size', async () => {
104
- const testCache = new QueryCache()
105
-
106
- const unsubscribe = testCache.subscribe((event) => {
107
- if (event.type === 'added') {
108
- if (testCache.getAll().length > 2) {
109
- testCache
110
- .findAll({
111
- type: 'inactive',
112
- predicate: (q) => q !== event.query,
113
- })
114
- .forEach((query) => {
115
- testCache.remove(query)
116
- })
117
- }
118
- }
119
- })
120
-
121
- const testClient = new QueryClient({ queryCache: testCache })
122
-
123
- await testClient.prefetchQuery({
124
- queryKey: ['key1'],
125
- queryFn: () => 'data1',
126
- })
127
- expect(testCache.findAll().length).toBe(1)
128
- await testClient.prefetchQuery({
129
- queryKey: ['key2'],
130
- queryFn: () => 'data2',
131
- })
132
- expect(testCache.findAll().length).toBe(2)
133
- await testClient.prefetchQuery({
134
- queryKey: ['key3'],
135
- queryFn: () => 'data3',
136
- })
137
- expect(testCache.findAll().length).toBe(1)
138
- expect(testCache.findAll()[0]!.state.data).toBe('data3')
139
-
140
- unsubscribe()
141
- })
142
- })
143
-
144
- describe('find', () => {
145
- test('find should filter correctly', async () => {
146
- const key = queryKey()
147
- await queryClient.prefetchQuery({ queryKey: key, queryFn: () => 'data1' })
148
- const query = queryCache.find({ queryKey: key })!
149
- expect(query).toBeDefined()
150
- })
151
-
152
- test('find should filter correctly with exact set to false', async () => {
153
- const key = queryKey()
154
- await queryClient.prefetchQuery({ queryKey: key, queryFn: () => 'data1' })
155
- const query = queryCache.find({ queryKey: key, exact: false })!
156
- expect(query).toBeDefined()
157
- })
158
- })
159
-
160
- describe('findAll', () => {
161
- test('should filter correctly', async () => {
162
- const key1 = queryKey()
163
- const key2 = queryKey()
164
- const keyFetching = queryKey()
165
- await queryClient.prefetchQuery({
166
- queryKey: key1,
167
- queryFn: () => 'data1',
168
- })
169
- await queryClient.prefetchQuery({
170
- queryKey: key2,
171
- queryFn: () => 'data2',
172
- })
173
- await queryClient.prefetchQuery({
174
- queryKey: [{ a: 'a', b: 'b' }],
175
- queryFn: () => 'data3',
176
- })
177
- await queryClient.prefetchQuery({
178
- queryKey: ['posts', 1],
179
- queryFn: () => 'data4',
180
- })
181
- queryClient.invalidateQueries({ queryKey: key2 })
182
- const query1 = queryCache.find({ queryKey: key1 })!
183
- const query2 = queryCache.find({ queryKey: key2 })!
184
- const query3 = queryCache.find({ queryKey: [{ a: 'a', b: 'b' }] })!
185
- const query4 = queryCache.find({ queryKey: ['posts', 1] })!
186
-
187
- expect(queryCache.findAll({ queryKey: key1 })).toEqual([query1])
188
- // wrapping in an extra array doesn't yield the same results anymore since v4 because keys need to be an array
189
- expect(queryCache.findAll({ queryKey: [key1] })).toEqual([])
190
- expect(queryCache.findAll()).toEqual([query1, query2, query3, query4])
191
- expect(queryCache.findAll({})).toEqual([query1, query2, query3, query4])
192
- expect(queryCache.findAll({ queryKey: key1, type: 'inactive' })).toEqual([
193
- query1,
194
- ])
195
- expect(queryCache.findAll({ queryKey: key1, type: 'active' })).toEqual([])
196
- expect(queryCache.findAll({ queryKey: key1, stale: true })).toEqual([])
197
- expect(queryCache.findAll({ queryKey: key1, stale: false })).toEqual([
198
- query1,
199
- ])
200
- expect(
201
- queryCache.findAll({ queryKey: key1, stale: false, type: 'active' }),
202
- ).toEqual([])
203
- expect(
204
- queryCache.findAll({ queryKey: key1, stale: false, type: 'inactive' }),
205
- ).toEqual([query1])
206
- expect(
207
- queryCache.findAll({
208
- queryKey: key1,
209
- stale: false,
210
- type: 'inactive',
211
- exact: true,
212
- }),
213
- ).toEqual([query1])
214
-
215
- expect(queryCache.findAll({ queryKey: key2 })).toEqual([query2])
216
- expect(queryCache.findAll({ queryKey: key2, stale: undefined })).toEqual([
217
- query2,
218
- ])
219
- expect(queryCache.findAll({ queryKey: key2, stale: true })).toEqual([
220
- query2,
221
- ])
222
- expect(queryCache.findAll({ queryKey: key2, stale: false })).toEqual([])
223
- expect(queryCache.findAll({ queryKey: [{ b: 'b' }] })).toEqual([query3])
224
- expect(
225
- queryCache.findAll({ queryKey: [{ a: 'a' }], exact: false }),
226
- ).toEqual([query3])
227
- expect(
228
- queryCache.findAll({ queryKey: [{ a: 'a' }], exact: true }),
229
- ).toEqual([])
230
- expect(
231
- queryCache.findAll({ queryKey: [{ a: 'a', b: 'b' }], exact: true }),
232
- ).toEqual([query3])
233
- expect(queryCache.findAll({ queryKey: [{ a: 'a', b: 'b' }] })).toEqual([
234
- query3,
235
- ])
236
- expect(
237
- queryCache.findAll({ queryKey: [{ a: 'a', b: 'b', c: 'c' }] }),
238
- ).toEqual([])
239
- expect(
240
- queryCache.findAll({ queryKey: [{ a: 'a' }], stale: false }),
241
- ).toEqual([query3])
242
- expect(
243
- queryCache.findAll({ queryKey: [{ a: 'a' }], stale: true }),
244
- ).toEqual([])
245
- expect(
246
- queryCache.findAll({ queryKey: [{ a: 'a' }], type: 'active' }),
247
- ).toEqual([])
248
- expect(
249
- queryCache.findAll({ queryKey: [{ a: 'a' }], type: 'inactive' }),
250
- ).toEqual([query3])
251
- expect(
252
- queryCache.findAll({ predicate: (query) => query === query3 }),
253
- ).toEqual([query3])
254
- expect(queryCache.findAll({ queryKey: ['posts'] })).toEqual([query4])
255
-
256
- expect(queryCache.findAll({ fetchStatus: 'idle' })).toEqual([
257
- query1,
258
- query2,
259
- query3,
260
- query4,
261
- ])
262
- expect(
263
- queryCache.findAll({ queryKey: key2, fetchStatus: undefined }),
264
- ).toEqual([query2])
265
-
266
- const promise = queryClient.prefetchQuery({
267
- queryKey: keyFetching,
268
- queryFn: async () => {
269
- await sleep(20)
270
- return 'dataFetching'
271
- },
272
- })
273
- expect(queryCache.findAll({ fetchStatus: 'fetching' })).toEqual([
274
- queryCache.find({ queryKey: keyFetching }),
275
- ])
276
- await promise
277
- expect(queryCache.findAll({ fetchStatus: 'fetching' })).toEqual([])
278
- })
279
-
280
- test('should return all the queries when no filters are defined', async () => {
281
- const key1 = queryKey()
282
- const key2 = queryKey()
283
- await queryClient.prefetchQuery({
284
- queryKey: key1,
285
- queryFn: () => 'data1',
286
- })
287
- await queryClient.prefetchQuery({
288
- queryKey: key2,
289
- queryFn: () => 'data2',
290
- })
291
- expect(queryCache.findAll().length).toBe(2)
292
- })
293
- })
294
-
295
- describe('QueryCacheConfig error callbacks', () => {
296
- test('should call onError and onSettled when a query errors', async () => {
297
- const key = queryKey()
298
- const onSuccess = vi.fn()
299
- const onSettled = vi.fn()
300
- const onError = vi.fn()
301
- const testCache = new QueryCache({ onSuccess, onError, onSettled })
302
- const testClient = createQueryClient({ queryCache: testCache })
303
- await testClient.prefetchQuery({
304
- queryKey: key,
305
- queryFn: () => Promise.reject<unknown>('error'),
306
- })
307
- const query = testCache.find({ queryKey: key })
308
- expect(onError).toHaveBeenCalledWith('error', query)
309
- expect(onError).toHaveBeenCalledTimes(1)
310
- expect(onSuccess).not.toHaveBeenCalled()
311
- expect(onSettled).toHaveBeenCalledTimes(1)
312
- expect(onSettled).toHaveBeenCalledWith(undefined, 'error', query)
313
- })
314
- })
315
-
316
- describe('QueryCacheConfig success callbacks', () => {
317
- test('should call onSuccess and onSettled when a query is successful', async () => {
318
- const key = queryKey()
319
- const onSuccess = vi.fn()
320
- const onSettled = vi.fn()
321
- const onError = vi.fn()
322
- const testCache = new QueryCache({ onSuccess, onError, onSettled })
323
- const testClient = createQueryClient({ queryCache: testCache })
324
- await testClient.prefetchQuery({
325
- queryKey: key,
326
- queryFn: () => Promise.resolve({ data: 5 }),
327
- })
328
- const query = testCache.find({ queryKey: key })
329
- expect(onSuccess).toHaveBeenCalledWith({ data: 5 }, query)
330
- expect(onSuccess).toHaveBeenCalledTimes(1)
331
- expect(onError).not.toHaveBeenCalled()
332
- expect(onSettled).toHaveBeenCalledTimes(1)
333
- expect(onSettled).toHaveBeenCalledWith({ data: 5 }, null, query)
334
- })
335
- })
336
-
337
- describe('QueryCache.add', () => {
338
- test('should not try to add a query already added to the cache', async () => {
339
- const key = queryKey()
340
-
341
- await queryClient.prefetchQuery({ queryKey: key, queryFn: () => 'data1' })
342
-
343
- const query = queryCache.findAll()[0]!
344
- const queryClone = Object.assign({}, query)
345
-
346
- queryCache.add(queryClone)
347
- expect(queryCache.getAll().length).toEqual(1)
348
- })
349
- })
350
- })
@@ -1,156 +0,0 @@
1
- import { describe, expectTypeOf, it } from 'vitest'
2
- import { QueryClient } from '../queryClient'
3
- import type { DataTag, InfiniteData, QueryKey } from '../types'
4
-
5
- describe('getQueryData', () => {
6
- it('should be typed if key is tagged', () => {
7
- const queryKey = ['key'] as DataTag<Array<string>, number>
8
- const queryClient = new QueryClient()
9
- const data = queryClient.getQueryData(queryKey)
10
-
11
- expectTypeOf(data).toEqualTypeOf<number | undefined>()
12
- })
13
-
14
- it('should infer unknown if key is not tagged', () => {
15
- const queryKey = ['key'] as const
16
- const queryClient = new QueryClient()
17
- const data = queryClient.getQueryData(queryKey)
18
-
19
- expectTypeOf(data).toEqualTypeOf<unknown>()
20
- })
21
-
22
- it('should infer passed generic if passed', () => {
23
- const queryKey = ['key'] as const
24
- const queryClient = new QueryClient()
25
- const data = queryClient.getQueryData<number>(queryKey)
26
-
27
- expectTypeOf(data).toEqualTypeOf<number | undefined>()
28
- })
29
-
30
- it('should only allow Arrays to be passed', () => {
31
- const queryKey = 'key'
32
- const queryClient = new QueryClient()
33
- // @ts-expect-error TS2345: Argument of type 'string' is not assignable to parameter of type 'QueryKey'
34
- return queryClient.getQueryData(queryKey)
35
- })
36
- })
37
-
38
- describe('setQueryData', () => {
39
- it('updater should be typed if key is tagged', () => {
40
- const queryKey = ['key'] as DataTag<Array<string>, number>
41
- const queryClient = new QueryClient()
42
- const data = queryClient.setQueryData(queryKey, (prev) => {
43
- expectTypeOf(prev).toEqualTypeOf<number | undefined>()
44
- return prev
45
- })
46
-
47
- expectTypeOf(data).toEqualTypeOf<number | undefined>()
48
- })
49
-
50
- it('value should be typed if key is tagged', () => {
51
- const queryKey = ['key'] as DataTag<Array<string>, number>
52
- const queryClient = new QueryClient()
53
-
54
- // @ts-expect-error value should be a number
55
- queryClient.setQueryData(queryKey, '1')
56
-
57
- // @ts-expect-error value should be a number
58
- queryClient.setQueryData(queryKey, () => '1')
59
-
60
- const data = queryClient.setQueryData(queryKey, 1)
61
-
62
- expectTypeOf(data).toEqualTypeOf<number | undefined>()
63
- })
64
-
65
- it('should infer unknown for updater if key is not tagged', () => {
66
- const queryKey = ['key'] as const
67
- const queryClient = new QueryClient()
68
- const data = queryClient.setQueryData(queryKey, (prev) => {
69
- expectTypeOf(prev).toEqualTypeOf<unknown>()
70
- return prev
71
- })
72
-
73
- expectTypeOf(data).toEqualTypeOf<unknown>()
74
- })
75
-
76
- it('should infer unknown for value if key is not tagged', () => {
77
- const queryKey = ['key'] as const
78
- const queryClient = new QueryClient()
79
- const data = queryClient.setQueryData(queryKey, 'foo')
80
-
81
- expectTypeOf(data).toEqualTypeOf<unknown>()
82
- })
83
-
84
- it('should infer passed generic if passed', () => {
85
- const queryKey = ['key'] as const
86
- const queryClient = new QueryClient()
87
- const data = queryClient.setQueryData<string>(queryKey, (prev) => {
88
- expectTypeOf(prev).toEqualTypeOf<string | undefined>()
89
- return prev
90
- })
91
-
92
- expectTypeOf(data).toEqualTypeOf<string | undefined>()
93
- })
94
-
95
- it('should infer passed generic for value', () => {
96
- const queryKey = ['key'] as const
97
- const queryClient = new QueryClient()
98
- const data = queryClient.setQueryData<string>(queryKey, 'foo')
99
-
100
- expectTypeOf(data).toEqualTypeOf<string | undefined>()
101
- })
102
- })
103
-
104
- describe('fetchInfiniteQuery', () => {
105
- it('should allow passing pages', async () => {
106
- const data = await new QueryClient().fetchInfiniteQuery({
107
- queryKey: ['key'],
108
- queryFn: () => Promise.resolve('string'),
109
- getNextPageParam: () => 1,
110
- initialPageParam: 1,
111
- pages: 5,
112
- })
113
-
114
- expectTypeOf(data).toEqualTypeOf<InfiniteData<string, number>>()
115
- })
116
-
117
- it('should not allow passing getNextPageParam without pages', () => {
118
- new QueryClient().fetchInfiniteQuery({
119
- queryKey: ['key'],
120
- queryFn: () => Promise.resolve('string'),
121
- initialPageParam: 1,
122
- getNextPageParam: () => 1,
123
- })
124
- })
125
-
126
- it('should not allow passing pages without getNextPageParam', () => {
127
- // @ts-expect-error Property 'getNextPageParam' is missing
128
- return new QueryClient().fetchInfiniteQuery({
129
- queryKey: ['key'],
130
- queryFn: () => Promise.resolve('string'),
131
- initialPageParam: 1,
132
- pages: 5,
133
- })
134
- })
135
- })
136
-
137
- describe('defaultOptions', () => {
138
- it('should have a typed QueryFunctionContext', () => {
139
- new QueryClient({
140
- defaultOptions: {
141
- queries: {
142
- queryFn: (context) => {
143
- expectTypeOf(context).toEqualTypeOf<{
144
- queryKey: QueryKey
145
- meta: Record<string, unknown> | undefined
146
- signal: AbortSignal
147
- pageParam?: unknown
148
- direction?: unknown
149
- }>()
150
- return Promise.resolve('data')
151
- },
152
- },
153
- },
154
- })
155
- })
156
- })