@tanstack/query-core 5.59.16 → 5.59.20
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.
- package/build/legacy/queriesObserver.cjs +8 -0
- package/build/legacy/queriesObserver.cjs.map +1 -1
- package/build/legacy/queriesObserver.js +8 -0
- package/build/legacy/queriesObserver.js.map +1 -1
- package/build/modern/queriesObserver.cjs +8 -0
- package/build/modern/queriesObserver.cjs.map +1 -1
- package/build/modern/queriesObserver.js +8 -0
- package/build/modern/queriesObserver.js.map +1 -1
- package/package.json +3 -2
- package/src/queriesObserver.ts +9 -0
- package/src/__tests__/OmitKeyof.test-d.ts +0 -175
- package/src/__tests__/focusManager.test.tsx +0 -163
- package/src/__tests__/hydration.test.tsx +0 -1069
- package/src/__tests__/infiniteQueryBehavior.test.tsx +0 -427
- package/src/__tests__/infiniteQueryObserver.test-d.tsx +0 -64
- package/src/__tests__/infiniteQueryObserver.test.tsx +0 -198
- package/src/__tests__/mutationCache.test.tsx +0 -376
- package/src/__tests__/mutationObserver.test.tsx +0 -326
- package/src/__tests__/mutations.test.tsx +0 -603
- package/src/__tests__/notifyManager.test.tsx +0 -85
- package/src/__tests__/onlineManager.test.tsx +0 -168
- package/src/__tests__/queriesObserver.test.tsx +0 -267
- package/src/__tests__/query.test.tsx +0 -1049
- package/src/__tests__/queryCache.test.tsx +0 -350
- package/src/__tests__/queryClient.test-d.tsx +0 -156
- package/src/__tests__/queryClient.test.tsx +0 -2031
- package/src/__tests__/queryObserver.test-d.tsx +0 -108
- package/src/__tests__/queryObserver.test.tsx +0 -1236
- package/src/__tests__/utils.test.tsx +0 -468
- package/src/__tests__/utils.ts +0 -59
|
@@ -1,2031 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
|
|
2
|
-
import { waitFor } from '@testing-library/react'
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
MutationObserver,
|
|
6
|
-
QueryClient,
|
|
7
|
-
QueryObserver,
|
|
8
|
-
dehydrate,
|
|
9
|
-
focusManager,
|
|
10
|
-
hydrate,
|
|
11
|
-
onlineManager,
|
|
12
|
-
} from '..'
|
|
13
|
-
import { skipToken } from '../utils'
|
|
14
|
-
import {
|
|
15
|
-
createQueryClient,
|
|
16
|
-
mockOnlineManagerIsOnline,
|
|
17
|
-
queryKey,
|
|
18
|
-
sleep,
|
|
19
|
-
} from './utils'
|
|
20
|
-
import type { QueryCache, QueryFunction, QueryObserverOptions } from '..'
|
|
21
|
-
|
|
22
|
-
describe('queryClient', () => {
|
|
23
|
-
let queryClient: QueryClient
|
|
24
|
-
let queryCache: QueryCache
|
|
25
|
-
|
|
26
|
-
beforeEach(() => {
|
|
27
|
-
queryClient = createQueryClient()
|
|
28
|
-
queryCache = queryClient.getQueryCache()
|
|
29
|
-
queryClient.mount()
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
afterEach(() => {
|
|
33
|
-
queryClient.clear()
|
|
34
|
-
queryClient.unmount()
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
describe('defaultOptions', () => {
|
|
38
|
-
test('should merge defaultOptions', async () => {
|
|
39
|
-
const key = queryKey()
|
|
40
|
-
|
|
41
|
-
const queryFn = () => 'data'
|
|
42
|
-
const testClient = createQueryClient({
|
|
43
|
-
defaultOptions: { queries: { queryFn } },
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
expect(() => testClient.prefetchQuery({ queryKey: key })).not.toThrow()
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
test('should merge defaultOptions when query is added to cache', async () => {
|
|
50
|
-
const key = queryKey()
|
|
51
|
-
|
|
52
|
-
const testClient = createQueryClient({
|
|
53
|
-
defaultOptions: {
|
|
54
|
-
queries: { gcTime: Infinity },
|
|
55
|
-
},
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
const fetchData = () => Promise.resolve('data')
|
|
59
|
-
await testClient.prefetchQuery({ queryKey: key, queryFn: fetchData })
|
|
60
|
-
const newQuery = testClient.getQueryCache().find({ queryKey: key })
|
|
61
|
-
expect(newQuery?.options.gcTime).toBe(Infinity)
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
test('should get defaultOptions', async () => {
|
|
65
|
-
const queryFn = () => 'data'
|
|
66
|
-
const defaultOptions = { queries: { queryFn } }
|
|
67
|
-
const testClient = createQueryClient({
|
|
68
|
-
defaultOptions,
|
|
69
|
-
})
|
|
70
|
-
expect(testClient.getDefaultOptions()).toMatchObject(defaultOptions)
|
|
71
|
-
})
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
describe('setQueryDefaults', () => {
|
|
75
|
-
test('should not trigger a fetch', async () => {
|
|
76
|
-
const key = queryKey()
|
|
77
|
-
queryClient.setQueryDefaults(key, { queryFn: () => 'data' })
|
|
78
|
-
await sleep(1)
|
|
79
|
-
const data = queryClient.getQueryData(key)
|
|
80
|
-
expect(data).toBeUndefined()
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
test('should be able to override defaults', async () => {
|
|
84
|
-
const key = queryKey()
|
|
85
|
-
queryClient.setQueryDefaults(key, { queryFn: () => 'data' })
|
|
86
|
-
const observer = new QueryObserver(queryClient, { queryKey: key })
|
|
87
|
-
const { data } = await observer.refetch()
|
|
88
|
-
expect(data).toBe('data')
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
test('should match the query key partially', async () => {
|
|
92
|
-
const key = queryKey()
|
|
93
|
-
queryClient.setQueryDefaults([key], { queryFn: () => 'data' })
|
|
94
|
-
const observer = new QueryObserver(queryClient, {
|
|
95
|
-
queryKey: [key, 'a'],
|
|
96
|
-
})
|
|
97
|
-
const { data } = await observer.refetch()
|
|
98
|
-
expect(data).toBe('data')
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
test('should not match if the query key is a subset', async () => {
|
|
102
|
-
const key = queryKey()
|
|
103
|
-
queryClient.setQueryDefaults([key, 'a'], {
|
|
104
|
-
queryFn: () => 'data',
|
|
105
|
-
})
|
|
106
|
-
const observer = new QueryObserver(queryClient, {
|
|
107
|
-
queryKey: [key],
|
|
108
|
-
retry: false,
|
|
109
|
-
enabled: false,
|
|
110
|
-
})
|
|
111
|
-
const { status } = await observer.refetch()
|
|
112
|
-
expect(status).toBe('error')
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
test('should also set defaults for observers', async () => {
|
|
116
|
-
const key = queryKey()
|
|
117
|
-
queryClient.setQueryDefaults(key, {
|
|
118
|
-
queryFn: () => 'data',
|
|
119
|
-
enabled: false,
|
|
120
|
-
})
|
|
121
|
-
const observer = new QueryObserver(queryClient, {
|
|
122
|
-
queryKey: [key],
|
|
123
|
-
})
|
|
124
|
-
expect(observer.getCurrentResult().status).toBe('pending')
|
|
125
|
-
expect(observer.getCurrentResult().fetchStatus).toBe('idle')
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
test('should update existing query defaults', async () => {
|
|
129
|
-
const key = queryKey()
|
|
130
|
-
const queryOptions1 = { queryFn: () => 'data' }
|
|
131
|
-
const queryOptions2 = { retry: false }
|
|
132
|
-
queryClient.setQueryDefaults(key, { ...queryOptions1 })
|
|
133
|
-
queryClient.setQueryDefaults(key, { ...queryOptions2 })
|
|
134
|
-
expect(queryClient.getQueryDefaults(key)).toMatchObject(queryOptions2)
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
test('should merge defaultOptions', async () => {
|
|
138
|
-
const key = queryKey()
|
|
139
|
-
|
|
140
|
-
queryClient.setQueryDefaults([...key, 'todo'], { suspense: true })
|
|
141
|
-
queryClient.setQueryDefaults([...key, 'todo', 'detail'], {
|
|
142
|
-
staleTime: 5000,
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
expect(
|
|
146
|
-
queryClient.getQueryDefaults([...key, 'todo', 'detail']),
|
|
147
|
-
).toMatchObject({ suspense: true, staleTime: 5000 })
|
|
148
|
-
})
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
describe('defaultQueryOptions', () => {
|
|
152
|
-
test('should default networkMode when persister is present', async () => {
|
|
153
|
-
expect(
|
|
154
|
-
createQueryClient({
|
|
155
|
-
defaultOptions: {
|
|
156
|
-
queries: {
|
|
157
|
-
persister: 'ignore' as any,
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
}).defaultQueryOptions({ queryKey: queryKey() }).networkMode,
|
|
161
|
-
).toBe('offlineFirst')
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
test('should not default networkMode without persister', async () => {
|
|
165
|
-
expect(
|
|
166
|
-
createQueryClient({
|
|
167
|
-
defaultOptions: {
|
|
168
|
-
queries: {
|
|
169
|
-
staleTime: 1000,
|
|
170
|
-
},
|
|
171
|
-
},
|
|
172
|
-
}).defaultQueryOptions({ queryKey: queryKey() }).networkMode,
|
|
173
|
-
).toBe(undefined)
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
test('should not default networkMode when already present', async () => {
|
|
177
|
-
expect(
|
|
178
|
-
createQueryClient({
|
|
179
|
-
defaultOptions: {
|
|
180
|
-
queries: {
|
|
181
|
-
persister: 'ignore' as any,
|
|
182
|
-
networkMode: 'always',
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
}).defaultQueryOptions({ queryKey: queryKey() }).networkMode,
|
|
186
|
-
).toBe('always')
|
|
187
|
-
})
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
describe('setQueryData', () => {
|
|
191
|
-
test('should not crash if query could not be found', () => {
|
|
192
|
-
const key = queryKey()
|
|
193
|
-
const user = { userId: 1 }
|
|
194
|
-
expect(() => {
|
|
195
|
-
queryClient.setQueryData([key, user], (prevUser?: typeof user) => ({
|
|
196
|
-
...prevUser!,
|
|
197
|
-
name: 'James',
|
|
198
|
-
}))
|
|
199
|
-
}).not.toThrow()
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
test('should not crash when variable is null', () => {
|
|
203
|
-
const key = queryKey()
|
|
204
|
-
queryClient.setQueryData([key, { userId: null }], 'Old Data')
|
|
205
|
-
expect(() => {
|
|
206
|
-
queryClient.setQueryData([key, { userId: null }], 'New Data')
|
|
207
|
-
}).not.toThrow()
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
test('should use default options', () => {
|
|
211
|
-
const key = queryKey()
|
|
212
|
-
const testClient = createQueryClient({
|
|
213
|
-
defaultOptions: { queries: { queryKeyHashFn: () => 'someKey' } },
|
|
214
|
-
})
|
|
215
|
-
const testCache = testClient.getQueryCache()
|
|
216
|
-
testClient.setQueryData(key, 'data')
|
|
217
|
-
expect(testClient.getQueryData(key)).toBe('data')
|
|
218
|
-
expect(testCache.find({ queryKey: key })).toBe(testCache.get('someKey'))
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
test('should create a new query if query was not found 1', () => {
|
|
222
|
-
const key = queryKey()
|
|
223
|
-
queryClient.setQueryData(key, 'bar')
|
|
224
|
-
expect(queryClient.getQueryData(key)).toBe('bar')
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
test('should create a new query if query was not found 2', () => {
|
|
228
|
-
const key = queryKey()
|
|
229
|
-
queryClient.setQueryData(key, 'qux')
|
|
230
|
-
expect(queryClient.getQueryData(key)).toBe('qux')
|
|
231
|
-
})
|
|
232
|
-
|
|
233
|
-
test('should not create a new query if query was not found and data is undefined', () => {
|
|
234
|
-
const key = queryKey()
|
|
235
|
-
expect(queryClient.getQueryCache().find({ queryKey: key })).toBe(
|
|
236
|
-
undefined,
|
|
237
|
-
)
|
|
238
|
-
queryClient.setQueryData(key, undefined)
|
|
239
|
-
expect(queryClient.getQueryCache().find({ queryKey: key })).toBe(
|
|
240
|
-
undefined,
|
|
241
|
-
)
|
|
242
|
-
})
|
|
243
|
-
|
|
244
|
-
test('should not create a new query if query was not found and updater returns undefined', () => {
|
|
245
|
-
const key = queryKey()
|
|
246
|
-
expect(queryClient.getQueryCache().find({ queryKey: key })).toBe(
|
|
247
|
-
undefined,
|
|
248
|
-
)
|
|
249
|
-
queryClient.setQueryData(key, () => undefined)
|
|
250
|
-
expect(queryClient.getQueryCache().find({ queryKey: key })).toBe(
|
|
251
|
-
undefined,
|
|
252
|
-
)
|
|
253
|
-
})
|
|
254
|
-
|
|
255
|
-
test('should not update query data if data is undefined', () => {
|
|
256
|
-
const key = queryKey()
|
|
257
|
-
queryClient.setQueryData(key, 'qux')
|
|
258
|
-
queryClient.setQueryData(key, undefined)
|
|
259
|
-
expect(queryClient.getQueryData(key)).toBe('qux')
|
|
260
|
-
})
|
|
261
|
-
|
|
262
|
-
test('should not update query data if updater returns undefined', () => {
|
|
263
|
-
const key = queryKey()
|
|
264
|
-
queryClient.setQueryData<string>(key, 'qux')
|
|
265
|
-
queryClient.setQueryData<string>(key, () => undefined)
|
|
266
|
-
expect(queryClient.getQueryData(key)).toBe('qux')
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
test('should accept an update function', () => {
|
|
270
|
-
const key = queryKey()
|
|
271
|
-
|
|
272
|
-
const updater = vi.fn((oldData) => `new data + ${oldData}`)
|
|
273
|
-
|
|
274
|
-
queryClient.setQueryData(key, 'test data')
|
|
275
|
-
queryClient.setQueryData(key, updater)
|
|
276
|
-
|
|
277
|
-
expect(updater).toHaveBeenCalled()
|
|
278
|
-
expect(queryCache.find({ queryKey: key })!.state.data).toEqual(
|
|
279
|
-
'new data + test data',
|
|
280
|
-
)
|
|
281
|
-
})
|
|
282
|
-
|
|
283
|
-
test('should set the new data without comparison if structuralSharing is set to false', () => {
|
|
284
|
-
const key = queryKey()
|
|
285
|
-
|
|
286
|
-
queryClient.setDefaultOptions({
|
|
287
|
-
queries: {
|
|
288
|
-
structuralSharing: false,
|
|
289
|
-
},
|
|
290
|
-
})
|
|
291
|
-
|
|
292
|
-
const oldData = { value: true }
|
|
293
|
-
const newData = { value: true }
|
|
294
|
-
queryClient.setQueryData(key, oldData)
|
|
295
|
-
queryClient.setQueryData(key, newData)
|
|
296
|
-
|
|
297
|
-
expect(queryCache.find({ queryKey: key })!.state.data).toBe(newData)
|
|
298
|
-
})
|
|
299
|
-
|
|
300
|
-
test('should apply a custom structuralSharing function when provided', () => {
|
|
301
|
-
const key = queryKey()
|
|
302
|
-
|
|
303
|
-
const queryObserverOptions = {
|
|
304
|
-
structuralSharing: (
|
|
305
|
-
prevData: { value: Date } | undefined,
|
|
306
|
-
newData: { value: Date },
|
|
307
|
-
) => {
|
|
308
|
-
if (!prevData) {
|
|
309
|
-
return newData
|
|
310
|
-
}
|
|
311
|
-
return newData.value.getTime() === prevData.value.getTime()
|
|
312
|
-
? prevData
|
|
313
|
-
: newData
|
|
314
|
-
},
|
|
315
|
-
} as QueryObserverOptions
|
|
316
|
-
|
|
317
|
-
queryClient.setDefaultOptions({ queries: queryObserverOptions })
|
|
318
|
-
|
|
319
|
-
const oldData = { value: new Date(2022, 6, 19) }
|
|
320
|
-
const newData = { value: new Date(2022, 6, 19) }
|
|
321
|
-
queryClient.setQueryData(key, oldData)
|
|
322
|
-
queryClient.setQueryData(key, newData)
|
|
323
|
-
|
|
324
|
-
expect(queryCache.find({ queryKey: key })!.state.data).toBe(oldData)
|
|
325
|
-
|
|
326
|
-
const distinctData = { value: new Date(2021, 11, 25) }
|
|
327
|
-
queryClient.setQueryData(key, distinctData)
|
|
328
|
-
|
|
329
|
-
expect(queryCache.find({ queryKey: key })!.state.data).toBe(distinctData)
|
|
330
|
-
})
|
|
331
|
-
|
|
332
|
-
test('should not set isFetching to false', async () => {
|
|
333
|
-
const key = queryKey()
|
|
334
|
-
queryClient.prefetchQuery({
|
|
335
|
-
queryKey: key,
|
|
336
|
-
queryFn: async () => {
|
|
337
|
-
await sleep(10)
|
|
338
|
-
return 23
|
|
339
|
-
},
|
|
340
|
-
})
|
|
341
|
-
expect(queryClient.getQueryState(key)).toMatchObject({
|
|
342
|
-
data: undefined,
|
|
343
|
-
fetchStatus: 'fetching',
|
|
344
|
-
})
|
|
345
|
-
queryClient.setQueryData(key, 42)
|
|
346
|
-
expect(queryClient.getQueryState(key)).toMatchObject({
|
|
347
|
-
data: 42,
|
|
348
|
-
fetchStatus: 'fetching',
|
|
349
|
-
})
|
|
350
|
-
await waitFor(() =>
|
|
351
|
-
expect(queryClient.getQueryState(key)).toMatchObject({
|
|
352
|
-
data: 23,
|
|
353
|
-
fetchStatus: 'idle',
|
|
354
|
-
}),
|
|
355
|
-
)
|
|
356
|
-
})
|
|
357
|
-
})
|
|
358
|
-
|
|
359
|
-
describe('setQueriesData', () => {
|
|
360
|
-
test('should update all existing, matching queries', () => {
|
|
361
|
-
queryClient.setQueryData(['key', 1], 1)
|
|
362
|
-
queryClient.setQueryData(['key', 2], 2)
|
|
363
|
-
|
|
364
|
-
const result = queryClient.setQueriesData<number>(
|
|
365
|
-
{ queryKey: ['key'] },
|
|
366
|
-
(old) => (old ? old + 5 : undefined),
|
|
367
|
-
)
|
|
368
|
-
|
|
369
|
-
expect(result).toEqual([
|
|
370
|
-
[['key', 1], 6],
|
|
371
|
-
[['key', 2], 7],
|
|
372
|
-
])
|
|
373
|
-
expect(queryClient.getQueryData(['key', 1])).toBe(6)
|
|
374
|
-
expect(queryClient.getQueryData(['key', 2])).toBe(7)
|
|
375
|
-
})
|
|
376
|
-
|
|
377
|
-
test('should accept queryFilters', () => {
|
|
378
|
-
queryClient.setQueryData(['key', 1], 1)
|
|
379
|
-
queryClient.setQueryData(['key', 2], 2)
|
|
380
|
-
const query1 = queryCache.find({ queryKey: ['key', 1] })!
|
|
381
|
-
|
|
382
|
-
const result = queryClient.setQueriesData<number>(
|
|
383
|
-
{ predicate: (query) => query === query1 },
|
|
384
|
-
(old) => old! + 5,
|
|
385
|
-
)
|
|
386
|
-
|
|
387
|
-
expect(result).toEqual([[['key', 1], 6]])
|
|
388
|
-
expect(queryClient.getQueryData(['key', 1])).toBe(6)
|
|
389
|
-
expect(queryClient.getQueryData(['key', 2])).toBe(2)
|
|
390
|
-
})
|
|
391
|
-
|
|
392
|
-
test('should not update non existing queries', () => {
|
|
393
|
-
const result = queryClient.setQueriesData<string>(
|
|
394
|
-
{ queryKey: ['key'] },
|
|
395
|
-
'data',
|
|
396
|
-
)
|
|
397
|
-
|
|
398
|
-
expect(result).toEqual([])
|
|
399
|
-
expect(queryClient.getQueryData(['key'])).toBe(undefined)
|
|
400
|
-
})
|
|
401
|
-
})
|
|
402
|
-
|
|
403
|
-
describe('getQueryData', () => {
|
|
404
|
-
test('should return the query data if the query is found', () => {
|
|
405
|
-
const key = queryKey()
|
|
406
|
-
queryClient.setQueryData([key, 'id'], 'bar')
|
|
407
|
-
expect(queryClient.getQueryData([key, 'id'])).toBe('bar')
|
|
408
|
-
})
|
|
409
|
-
|
|
410
|
-
test('should return undefined if the query is not found', () => {
|
|
411
|
-
const key = queryKey()
|
|
412
|
-
expect(queryClient.getQueryData(key)).toBeUndefined()
|
|
413
|
-
})
|
|
414
|
-
|
|
415
|
-
test('should match exact by default', () => {
|
|
416
|
-
const key = queryKey()
|
|
417
|
-
queryClient.setQueryData([key, 'id'], 'bar')
|
|
418
|
-
expect(queryClient.getQueryData([key])).toBeUndefined()
|
|
419
|
-
})
|
|
420
|
-
})
|
|
421
|
-
|
|
422
|
-
describe('ensureQueryData', () => {
|
|
423
|
-
test('should return the cached query data if the query is found', async () => {
|
|
424
|
-
const key = queryKey()
|
|
425
|
-
const queryFn = () => Promise.resolve('data')
|
|
426
|
-
|
|
427
|
-
queryClient.setQueryData([key, 'id'], 'bar')
|
|
428
|
-
|
|
429
|
-
await expect(
|
|
430
|
-
queryClient.ensureQueryData({ queryKey: [key, 'id'], queryFn }),
|
|
431
|
-
).resolves.toEqual('bar')
|
|
432
|
-
})
|
|
433
|
-
|
|
434
|
-
test('should return the cached query data if the query is found and cached query data is falsy', async () => {
|
|
435
|
-
const key = queryKey()
|
|
436
|
-
const queryFn = () => Promise.resolve(0)
|
|
437
|
-
|
|
438
|
-
queryClient.setQueryData([key, 'id'], null)
|
|
439
|
-
|
|
440
|
-
await expect(
|
|
441
|
-
queryClient.ensureQueryData({ queryKey: [key, 'id'], queryFn }),
|
|
442
|
-
).resolves.toEqual(null)
|
|
443
|
-
})
|
|
444
|
-
|
|
445
|
-
test('should call fetchQuery and return its results if the query is not found', async () => {
|
|
446
|
-
const key = queryKey()
|
|
447
|
-
const queryFn = () => Promise.resolve('data')
|
|
448
|
-
|
|
449
|
-
await expect(
|
|
450
|
-
queryClient.ensureQueryData({ queryKey: [key], queryFn }),
|
|
451
|
-
).resolves.toEqual('data')
|
|
452
|
-
})
|
|
453
|
-
|
|
454
|
-
test('should return the cached query data if the query is found and preFetchQuery in the background when revalidateIfStale is set', async () => {
|
|
455
|
-
const TIMEOUT = 10
|
|
456
|
-
const key = queryKey()
|
|
457
|
-
queryClient.setQueryData([key, 'id'], 'old')
|
|
458
|
-
|
|
459
|
-
const queryFn = () =>
|
|
460
|
-
new Promise((resolve) => {
|
|
461
|
-
setTimeout(() => resolve('new'), TIMEOUT)
|
|
462
|
-
})
|
|
463
|
-
|
|
464
|
-
await expect(
|
|
465
|
-
queryClient.ensureQueryData({
|
|
466
|
-
queryKey: [key, 'id'],
|
|
467
|
-
queryFn,
|
|
468
|
-
revalidateIfStale: true,
|
|
469
|
-
}),
|
|
470
|
-
).resolves.toEqual('old')
|
|
471
|
-
await sleep(TIMEOUT + 10)
|
|
472
|
-
await expect(
|
|
473
|
-
queryClient.ensureQueryData({
|
|
474
|
-
queryKey: [key, 'id'],
|
|
475
|
-
queryFn,
|
|
476
|
-
revalidateIfStale: true,
|
|
477
|
-
}),
|
|
478
|
-
).resolves.toEqual('new')
|
|
479
|
-
})
|
|
480
|
-
})
|
|
481
|
-
|
|
482
|
-
describe('ensureInfiniteQueryData', () => {
|
|
483
|
-
test('should return the cached query data if the query is found', async () => {
|
|
484
|
-
const key = queryKey()
|
|
485
|
-
const queryFn = () => Promise.resolve('data')
|
|
486
|
-
|
|
487
|
-
queryClient.setQueryData([key, 'id'], { pages: ['bar'], pageParams: [0] })
|
|
488
|
-
|
|
489
|
-
await expect(
|
|
490
|
-
queryClient.ensureInfiniteQueryData({
|
|
491
|
-
queryKey: [key, 'id'],
|
|
492
|
-
queryFn,
|
|
493
|
-
initialPageParam: 1,
|
|
494
|
-
getNextPageParam: () => undefined,
|
|
495
|
-
}),
|
|
496
|
-
).resolves.toEqual({ pages: ['bar'], pageParams: [0] })
|
|
497
|
-
})
|
|
498
|
-
|
|
499
|
-
test('should fetch the query and return its results if the query is not found', async () => {
|
|
500
|
-
const key = queryKey()
|
|
501
|
-
const queryFn = () => Promise.resolve('data')
|
|
502
|
-
|
|
503
|
-
await expect(
|
|
504
|
-
queryClient.ensureInfiniteQueryData({
|
|
505
|
-
queryKey: [key, 'id'],
|
|
506
|
-
queryFn,
|
|
507
|
-
initialPageParam: 1,
|
|
508
|
-
getNextPageParam: () => undefined,
|
|
509
|
-
}),
|
|
510
|
-
).resolves.toEqual({ pages: ['data'], pageParams: [1] })
|
|
511
|
-
})
|
|
512
|
-
|
|
513
|
-
test('should return the cached query data if the query is found and preFetchQuery in the background when revalidateIfStale is set', async () => {
|
|
514
|
-
const TIMEOUT = 10
|
|
515
|
-
const key = queryKey()
|
|
516
|
-
queryClient.setQueryData([key, 'id'], { pages: ['old'], pageParams: [0] })
|
|
517
|
-
|
|
518
|
-
const queryFn = () =>
|
|
519
|
-
new Promise((resolve) => {
|
|
520
|
-
setTimeout(() => resolve('new'), TIMEOUT)
|
|
521
|
-
})
|
|
522
|
-
|
|
523
|
-
await expect(
|
|
524
|
-
queryClient.ensureInfiniteQueryData({
|
|
525
|
-
queryKey: [key, 'id'],
|
|
526
|
-
queryFn,
|
|
527
|
-
initialPageParam: 1,
|
|
528
|
-
getNextPageParam: () => undefined,
|
|
529
|
-
revalidateIfStale: true,
|
|
530
|
-
}),
|
|
531
|
-
).resolves.toEqual({ pages: ['old'], pageParams: [0] })
|
|
532
|
-
await sleep(TIMEOUT + 10)
|
|
533
|
-
await expect(
|
|
534
|
-
queryClient.ensureInfiniteQueryData({
|
|
535
|
-
queryKey: [key, 'id'],
|
|
536
|
-
queryFn,
|
|
537
|
-
initialPageParam: 1,
|
|
538
|
-
getNextPageParam: () => undefined,
|
|
539
|
-
revalidateIfStale: true,
|
|
540
|
-
}),
|
|
541
|
-
).resolves.toEqual({ pages: ['new'], pageParams: [0] })
|
|
542
|
-
})
|
|
543
|
-
})
|
|
544
|
-
|
|
545
|
-
describe('getQueriesData', () => {
|
|
546
|
-
test('should return the query data for all matched queries', () => {
|
|
547
|
-
const key1 = queryKey()
|
|
548
|
-
const key2 = queryKey()
|
|
549
|
-
queryClient.setQueryData([key1, 1], 1)
|
|
550
|
-
queryClient.setQueryData([key1, 2], 2)
|
|
551
|
-
queryClient.setQueryData([key2, 2], 2)
|
|
552
|
-
expect(queryClient.getQueriesData({ queryKey: [key1] })).toEqual([
|
|
553
|
-
[[key1, 1], 1],
|
|
554
|
-
[[key1, 2], 2],
|
|
555
|
-
])
|
|
556
|
-
})
|
|
557
|
-
|
|
558
|
-
test('should return empty array if queries are not found', () => {
|
|
559
|
-
const key = queryKey()
|
|
560
|
-
expect(queryClient.getQueriesData({ queryKey: key })).toEqual([])
|
|
561
|
-
})
|
|
562
|
-
|
|
563
|
-
test('should accept query filters', () => {
|
|
564
|
-
queryClient.setQueryData(['key', 1], 1)
|
|
565
|
-
queryClient.setQueryData(['key', 2], 2)
|
|
566
|
-
const query1 = queryCache.find({ queryKey: ['key', 1] })!
|
|
567
|
-
|
|
568
|
-
const result = queryClient.getQueriesData({
|
|
569
|
-
predicate: (query) => query === query1,
|
|
570
|
-
})
|
|
571
|
-
|
|
572
|
-
expect(result).toEqual([[['key', 1], 1]])
|
|
573
|
-
})
|
|
574
|
-
})
|
|
575
|
-
|
|
576
|
-
describe('fetchQuery', () => {
|
|
577
|
-
test('should not type-error with strict query key', async () => {
|
|
578
|
-
type StrictData = 'data'
|
|
579
|
-
type StrictQueryKey = ['strict', ...ReturnType<typeof queryKey>]
|
|
580
|
-
const key: StrictQueryKey = ['strict', ...queryKey()]
|
|
581
|
-
|
|
582
|
-
const fetchFn: QueryFunction<StrictData, StrictQueryKey> = () =>
|
|
583
|
-
Promise.resolve('data')
|
|
584
|
-
|
|
585
|
-
await expect(
|
|
586
|
-
queryClient.fetchQuery<StrictData, any, StrictData, StrictQueryKey>({
|
|
587
|
-
queryKey: key,
|
|
588
|
-
queryFn: fetchFn,
|
|
589
|
-
}),
|
|
590
|
-
).resolves.toEqual('data')
|
|
591
|
-
})
|
|
592
|
-
|
|
593
|
-
// https://github.com/tannerlinsley/react-query/issues/652
|
|
594
|
-
test('should not retry by default', async () => {
|
|
595
|
-
const key = queryKey()
|
|
596
|
-
|
|
597
|
-
await expect(
|
|
598
|
-
queryClient.fetchQuery({
|
|
599
|
-
queryKey: key,
|
|
600
|
-
queryFn: async (): Promise<unknown> => {
|
|
601
|
-
throw new Error('error')
|
|
602
|
-
},
|
|
603
|
-
}),
|
|
604
|
-
).rejects.toEqual(new Error('error'))
|
|
605
|
-
})
|
|
606
|
-
|
|
607
|
-
test('should return the cached data on cache hit', async () => {
|
|
608
|
-
const key = queryKey()
|
|
609
|
-
|
|
610
|
-
const fetchFn = () => Promise.resolve('data')
|
|
611
|
-
const first = await queryClient.fetchQuery({
|
|
612
|
-
queryKey: key,
|
|
613
|
-
queryFn: fetchFn,
|
|
614
|
-
})
|
|
615
|
-
const second = await queryClient.fetchQuery({
|
|
616
|
-
queryKey: key,
|
|
617
|
-
queryFn: fetchFn,
|
|
618
|
-
})
|
|
619
|
-
|
|
620
|
-
expect(second).toBe(first)
|
|
621
|
-
})
|
|
622
|
-
|
|
623
|
-
test('should be able to fetch when garbage collection time is set to 0 and then be removed', async () => {
|
|
624
|
-
const key1 = queryKey()
|
|
625
|
-
const result = await queryClient.fetchQuery({
|
|
626
|
-
queryKey: key1,
|
|
627
|
-
queryFn: async () => {
|
|
628
|
-
await sleep(10)
|
|
629
|
-
return 1
|
|
630
|
-
},
|
|
631
|
-
gcTime: 0,
|
|
632
|
-
})
|
|
633
|
-
expect(result).toEqual(1)
|
|
634
|
-
await waitFor(() =>
|
|
635
|
-
expect(queryClient.getQueryData(key1)).toEqual(undefined),
|
|
636
|
-
)
|
|
637
|
-
})
|
|
638
|
-
|
|
639
|
-
test('should keep a query in cache if garbage collection time is Infinity', async () => {
|
|
640
|
-
const key1 = queryKey()
|
|
641
|
-
const result = await queryClient.fetchQuery({
|
|
642
|
-
queryKey: key1,
|
|
643
|
-
queryFn: async () => {
|
|
644
|
-
await sleep(10)
|
|
645
|
-
return 1
|
|
646
|
-
},
|
|
647
|
-
gcTime: Infinity,
|
|
648
|
-
})
|
|
649
|
-
const result2 = queryClient.getQueryData(key1)
|
|
650
|
-
expect(result).toEqual(1)
|
|
651
|
-
expect(result2).toEqual(1)
|
|
652
|
-
})
|
|
653
|
-
|
|
654
|
-
test('should not force fetch', async () => {
|
|
655
|
-
const key = queryKey()
|
|
656
|
-
|
|
657
|
-
queryClient.setQueryData(key, 'og')
|
|
658
|
-
const fetchFn = () => Promise.resolve('new')
|
|
659
|
-
const first = await queryClient.fetchQuery({
|
|
660
|
-
queryKey: key,
|
|
661
|
-
queryFn: fetchFn,
|
|
662
|
-
initialData: 'initial',
|
|
663
|
-
staleTime: 100,
|
|
664
|
-
})
|
|
665
|
-
expect(first).toBe('og')
|
|
666
|
-
})
|
|
667
|
-
|
|
668
|
-
test('should only fetch if the data is older then the given stale time', async () => {
|
|
669
|
-
const key = queryKey()
|
|
670
|
-
|
|
671
|
-
let count = 0
|
|
672
|
-
const fetchFn = () => ++count
|
|
673
|
-
|
|
674
|
-
queryClient.setQueryData(key, count)
|
|
675
|
-
const first = await queryClient.fetchQuery({
|
|
676
|
-
queryKey: key,
|
|
677
|
-
queryFn: fetchFn,
|
|
678
|
-
staleTime: 100,
|
|
679
|
-
})
|
|
680
|
-
await sleep(11)
|
|
681
|
-
const second = await queryClient.fetchQuery({
|
|
682
|
-
queryKey: key,
|
|
683
|
-
queryFn: fetchFn,
|
|
684
|
-
staleTime: 10,
|
|
685
|
-
})
|
|
686
|
-
const third = await queryClient.fetchQuery({
|
|
687
|
-
queryKey: key,
|
|
688
|
-
queryFn: fetchFn,
|
|
689
|
-
staleTime: 10,
|
|
690
|
-
})
|
|
691
|
-
await sleep(11)
|
|
692
|
-
const fourth = await queryClient.fetchQuery({
|
|
693
|
-
queryKey: key,
|
|
694
|
-
queryFn: fetchFn,
|
|
695
|
-
staleTime: 10,
|
|
696
|
-
})
|
|
697
|
-
expect(first).toBe(0)
|
|
698
|
-
expect(second).toBe(1)
|
|
699
|
-
expect(third).toBe(1)
|
|
700
|
-
expect(fourth).toBe(2)
|
|
701
|
-
})
|
|
702
|
-
})
|
|
703
|
-
|
|
704
|
-
describe('fetchInfiniteQuery', () => {
|
|
705
|
-
test('should not type-error with strict query key', async () => {
|
|
706
|
-
type StrictData = string
|
|
707
|
-
type StrictQueryKey = ['strict', ...ReturnType<typeof queryKey>]
|
|
708
|
-
const key: StrictQueryKey = ['strict', ...queryKey()]
|
|
709
|
-
|
|
710
|
-
const data = {
|
|
711
|
-
pages: ['data'],
|
|
712
|
-
pageParams: [0],
|
|
713
|
-
} as const
|
|
714
|
-
|
|
715
|
-
const fetchFn: QueryFunction<StrictData, StrictQueryKey, number> = () =>
|
|
716
|
-
Promise.resolve(data.pages[0])
|
|
717
|
-
|
|
718
|
-
await expect(
|
|
719
|
-
queryClient.fetchInfiniteQuery<
|
|
720
|
-
StrictData,
|
|
721
|
-
any,
|
|
722
|
-
StrictData,
|
|
723
|
-
StrictQueryKey,
|
|
724
|
-
number
|
|
725
|
-
>({ queryKey: key, queryFn: fetchFn, initialPageParam: 0 }),
|
|
726
|
-
).resolves.toEqual(data)
|
|
727
|
-
})
|
|
728
|
-
|
|
729
|
-
test('should return infinite query data', async () => {
|
|
730
|
-
const key = queryKey()
|
|
731
|
-
const result = await queryClient.fetchInfiniteQuery({
|
|
732
|
-
queryKey: key,
|
|
733
|
-
initialPageParam: 10,
|
|
734
|
-
queryFn: ({ pageParam }) => Number(pageParam),
|
|
735
|
-
})
|
|
736
|
-
const result2 = queryClient.getQueryData(key)
|
|
737
|
-
|
|
738
|
-
const expected = {
|
|
739
|
-
pages: [10],
|
|
740
|
-
pageParams: [10],
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
expect(result).toEqual(expected)
|
|
744
|
-
expect(result2).toEqual(expected)
|
|
745
|
-
})
|
|
746
|
-
})
|
|
747
|
-
|
|
748
|
-
describe('prefetchInfiniteQuery', () => {
|
|
749
|
-
test('should not type-error with strict query key', async () => {
|
|
750
|
-
type StrictData = 'data'
|
|
751
|
-
type StrictQueryKey = ['strict', ...ReturnType<typeof queryKey>]
|
|
752
|
-
const key: StrictQueryKey = ['strict', ...queryKey()]
|
|
753
|
-
|
|
754
|
-
const fetchFn: QueryFunction<StrictData, StrictQueryKey, number> = () =>
|
|
755
|
-
Promise.resolve('data')
|
|
756
|
-
|
|
757
|
-
await queryClient.prefetchInfiniteQuery<
|
|
758
|
-
StrictData,
|
|
759
|
-
any,
|
|
760
|
-
StrictData,
|
|
761
|
-
StrictQueryKey,
|
|
762
|
-
number
|
|
763
|
-
>({ queryKey: key, queryFn: fetchFn, initialPageParam: 0 })
|
|
764
|
-
|
|
765
|
-
const result = queryClient.getQueryData(key)
|
|
766
|
-
|
|
767
|
-
expect(result).toEqual({
|
|
768
|
-
pages: ['data'],
|
|
769
|
-
pageParams: [0],
|
|
770
|
-
})
|
|
771
|
-
})
|
|
772
|
-
|
|
773
|
-
test('should return infinite query data', async () => {
|
|
774
|
-
const key = queryKey()
|
|
775
|
-
|
|
776
|
-
await queryClient.prefetchInfiniteQuery({
|
|
777
|
-
queryKey: key,
|
|
778
|
-
queryFn: ({ pageParam }) => Number(pageParam),
|
|
779
|
-
initialPageParam: 10,
|
|
780
|
-
})
|
|
781
|
-
|
|
782
|
-
const result = queryClient.getQueryData(key)
|
|
783
|
-
|
|
784
|
-
expect(result).toEqual({
|
|
785
|
-
pages: [10],
|
|
786
|
-
pageParams: [10],
|
|
787
|
-
})
|
|
788
|
-
})
|
|
789
|
-
|
|
790
|
-
test('should prefetch multiple pages', async () => {
|
|
791
|
-
const key = queryKey()
|
|
792
|
-
|
|
793
|
-
await queryClient.prefetchInfiniteQuery({
|
|
794
|
-
queryKey: key,
|
|
795
|
-
queryFn: ({ pageParam }) => String(pageParam),
|
|
796
|
-
getNextPageParam: (_lastPage, _pages, lastPageParam) =>
|
|
797
|
-
lastPageParam + 5,
|
|
798
|
-
initialPageParam: 10,
|
|
799
|
-
pages: 3,
|
|
800
|
-
})
|
|
801
|
-
|
|
802
|
-
const result = queryClient.getQueryData(key)
|
|
803
|
-
|
|
804
|
-
expect(result).toEqual({
|
|
805
|
-
pages: ['10', '15', '20'],
|
|
806
|
-
pageParams: [10, 15, 20],
|
|
807
|
-
})
|
|
808
|
-
})
|
|
809
|
-
|
|
810
|
-
test('should stop prefetching if getNextPageParam returns undefined', async () => {
|
|
811
|
-
const key = queryKey()
|
|
812
|
-
let count = 0
|
|
813
|
-
|
|
814
|
-
await queryClient.prefetchInfiniteQuery({
|
|
815
|
-
queryKey: key,
|
|
816
|
-
queryFn: ({ pageParam }) => String(pageParam),
|
|
817
|
-
getNextPageParam: (_lastPage, _pages, lastPageParam) => {
|
|
818
|
-
count++
|
|
819
|
-
return lastPageParam >= 20 ? undefined : lastPageParam + 5
|
|
820
|
-
},
|
|
821
|
-
initialPageParam: 10,
|
|
822
|
-
pages: 5,
|
|
823
|
-
})
|
|
824
|
-
|
|
825
|
-
const result = queryClient.getQueryData(key)
|
|
826
|
-
|
|
827
|
-
expect(result).toEqual({
|
|
828
|
-
pages: ['10', '15', '20'],
|
|
829
|
-
pageParams: [10, 15, 20],
|
|
830
|
-
})
|
|
831
|
-
|
|
832
|
-
// this check ensures we're exiting the fetch loop early
|
|
833
|
-
expect(count).toBe(3)
|
|
834
|
-
})
|
|
835
|
-
})
|
|
836
|
-
|
|
837
|
-
describe('prefetchQuery', () => {
|
|
838
|
-
test('should not type-error with strict query key', async () => {
|
|
839
|
-
type StrictData = 'data'
|
|
840
|
-
type StrictQueryKey = ['strict', ...ReturnType<typeof queryKey>]
|
|
841
|
-
const key: StrictQueryKey = ['strict', ...queryKey()]
|
|
842
|
-
|
|
843
|
-
const fetchFn: QueryFunction<StrictData, StrictQueryKey> = () =>
|
|
844
|
-
Promise.resolve('data')
|
|
845
|
-
|
|
846
|
-
await queryClient.prefetchQuery<
|
|
847
|
-
StrictData,
|
|
848
|
-
any,
|
|
849
|
-
StrictData,
|
|
850
|
-
StrictQueryKey
|
|
851
|
-
>({ queryKey: key, queryFn: fetchFn })
|
|
852
|
-
|
|
853
|
-
const result = queryClient.getQueryData(key)
|
|
854
|
-
|
|
855
|
-
expect(result).toEqual('data')
|
|
856
|
-
})
|
|
857
|
-
|
|
858
|
-
test('should return undefined when an error is thrown', async () => {
|
|
859
|
-
const key = queryKey()
|
|
860
|
-
|
|
861
|
-
const result = await queryClient.prefetchQuery({
|
|
862
|
-
queryKey: key,
|
|
863
|
-
queryFn: async (): Promise<unknown> => {
|
|
864
|
-
throw new Error('error')
|
|
865
|
-
},
|
|
866
|
-
retry: false,
|
|
867
|
-
})
|
|
868
|
-
|
|
869
|
-
expect(result).toBeUndefined()
|
|
870
|
-
})
|
|
871
|
-
|
|
872
|
-
test('should be garbage collected after gcTime if unused', async () => {
|
|
873
|
-
const key = queryKey()
|
|
874
|
-
|
|
875
|
-
await queryClient.prefetchQuery({
|
|
876
|
-
queryKey: key,
|
|
877
|
-
queryFn: async () => {
|
|
878
|
-
return 'data'
|
|
879
|
-
},
|
|
880
|
-
gcTime: 10,
|
|
881
|
-
})
|
|
882
|
-
expect(queryCache.find({ queryKey: key })).toBeDefined()
|
|
883
|
-
await sleep(15)
|
|
884
|
-
expect(queryCache.find({ queryKey: key })).not.toBeDefined()
|
|
885
|
-
})
|
|
886
|
-
})
|
|
887
|
-
|
|
888
|
-
describe('removeQueries', () => {
|
|
889
|
-
test('should not crash when exact is provided', async () => {
|
|
890
|
-
const key = queryKey()
|
|
891
|
-
|
|
892
|
-
const fetchFn = () => Promise.resolve('data')
|
|
893
|
-
|
|
894
|
-
// check the query was added to the cache
|
|
895
|
-
await queryClient.prefetchQuery({ queryKey: key, queryFn: fetchFn })
|
|
896
|
-
expect(queryCache.find({ queryKey: key })).toBeTruthy()
|
|
897
|
-
|
|
898
|
-
// check the error doesn't occur
|
|
899
|
-
expect(() =>
|
|
900
|
-
queryClient.removeQueries({ queryKey: key, exact: true }),
|
|
901
|
-
).not.toThrow()
|
|
902
|
-
|
|
903
|
-
// check query was successful removed
|
|
904
|
-
expect(queryCache.find({ queryKey: key })).toBeFalsy()
|
|
905
|
-
})
|
|
906
|
-
})
|
|
907
|
-
|
|
908
|
-
describe('cancelQueries', () => {
|
|
909
|
-
test('should revert queries to their previous state', async () => {
|
|
910
|
-
const key1 = queryKey()
|
|
911
|
-
const key2 = queryKey()
|
|
912
|
-
const key3 = queryKey()
|
|
913
|
-
await queryClient.fetchQuery({
|
|
914
|
-
queryKey: key1,
|
|
915
|
-
queryFn: async () => {
|
|
916
|
-
return 'data'
|
|
917
|
-
},
|
|
918
|
-
})
|
|
919
|
-
try {
|
|
920
|
-
await queryClient.fetchQuery({
|
|
921
|
-
queryKey: key2,
|
|
922
|
-
queryFn: async () => {
|
|
923
|
-
return Promise.reject<unknown>('err')
|
|
924
|
-
},
|
|
925
|
-
})
|
|
926
|
-
} catch {}
|
|
927
|
-
queryClient.fetchQuery({
|
|
928
|
-
queryKey: key1,
|
|
929
|
-
queryFn: async () => {
|
|
930
|
-
await sleep(1000)
|
|
931
|
-
return 'data2'
|
|
932
|
-
},
|
|
933
|
-
})
|
|
934
|
-
try {
|
|
935
|
-
queryClient.fetchQuery({
|
|
936
|
-
queryKey: key2,
|
|
937
|
-
queryFn: async () => {
|
|
938
|
-
await sleep(1000)
|
|
939
|
-
return Promise.reject<unknown>('err2')
|
|
940
|
-
},
|
|
941
|
-
})
|
|
942
|
-
} catch {}
|
|
943
|
-
queryClient.fetchQuery({
|
|
944
|
-
queryKey: key3,
|
|
945
|
-
queryFn: async () => {
|
|
946
|
-
await sleep(1000)
|
|
947
|
-
return 'data3'
|
|
948
|
-
},
|
|
949
|
-
})
|
|
950
|
-
await sleep(10)
|
|
951
|
-
await queryClient.cancelQueries()
|
|
952
|
-
const state1 = queryClient.getQueryState(key1)
|
|
953
|
-
const state2 = queryClient.getQueryState(key2)
|
|
954
|
-
const state3 = queryClient.getQueryState(key3)
|
|
955
|
-
expect(state1).toMatchObject({
|
|
956
|
-
data: 'data',
|
|
957
|
-
status: 'success',
|
|
958
|
-
})
|
|
959
|
-
expect(state2).toMatchObject({
|
|
960
|
-
data: undefined,
|
|
961
|
-
error: 'err',
|
|
962
|
-
status: 'error',
|
|
963
|
-
})
|
|
964
|
-
expect(state3).toMatchObject({
|
|
965
|
-
data: undefined,
|
|
966
|
-
status: 'pending',
|
|
967
|
-
fetchStatus: 'idle',
|
|
968
|
-
})
|
|
969
|
-
})
|
|
970
|
-
|
|
971
|
-
test('should not revert if revert option is set to false', async () => {
|
|
972
|
-
const key1 = queryKey()
|
|
973
|
-
await queryClient.fetchQuery({
|
|
974
|
-
queryKey: key1,
|
|
975
|
-
queryFn: async () => {
|
|
976
|
-
return 'data'
|
|
977
|
-
},
|
|
978
|
-
})
|
|
979
|
-
queryClient.fetchQuery({
|
|
980
|
-
queryKey: key1,
|
|
981
|
-
queryFn: async () => {
|
|
982
|
-
await sleep(1000)
|
|
983
|
-
return 'data2'
|
|
984
|
-
},
|
|
985
|
-
})
|
|
986
|
-
await sleep(10)
|
|
987
|
-
await queryClient.cancelQueries({ queryKey: key1 }, { revert: false })
|
|
988
|
-
const state1 = queryClient.getQueryState(key1)
|
|
989
|
-
expect(state1).toMatchObject({
|
|
990
|
-
status: 'error',
|
|
991
|
-
})
|
|
992
|
-
})
|
|
993
|
-
})
|
|
994
|
-
|
|
995
|
-
describe('refetchQueries', () => {
|
|
996
|
-
test('should not refetch if all observers are disabled', async () => {
|
|
997
|
-
const key = queryKey()
|
|
998
|
-
const queryFn = vi
|
|
999
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1000
|
-
.mockReturnValue('data')
|
|
1001
|
-
await queryClient.fetchQuery({ queryKey: key, queryFn })
|
|
1002
|
-
const observer1 = new QueryObserver(queryClient, {
|
|
1003
|
-
queryKey: key,
|
|
1004
|
-
queryFn,
|
|
1005
|
-
enabled: false,
|
|
1006
|
-
})
|
|
1007
|
-
observer1.subscribe(() => undefined)
|
|
1008
|
-
await queryClient.refetchQueries()
|
|
1009
|
-
observer1.destroy()
|
|
1010
|
-
expect(queryFn).toHaveBeenCalledTimes(1)
|
|
1011
|
-
})
|
|
1012
|
-
test('should refetch if at least one observer is enabled', async () => {
|
|
1013
|
-
const key = queryKey()
|
|
1014
|
-
const queryFn = vi
|
|
1015
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1016
|
-
.mockReturnValue('data')
|
|
1017
|
-
await queryClient.fetchQuery({ queryKey: key, queryFn })
|
|
1018
|
-
const observer1 = new QueryObserver(queryClient, {
|
|
1019
|
-
queryKey: key,
|
|
1020
|
-
queryFn,
|
|
1021
|
-
enabled: false,
|
|
1022
|
-
})
|
|
1023
|
-
const observer2 = new QueryObserver(queryClient, {
|
|
1024
|
-
queryKey: key,
|
|
1025
|
-
queryFn,
|
|
1026
|
-
refetchOnMount: false,
|
|
1027
|
-
})
|
|
1028
|
-
observer1.subscribe(() => undefined)
|
|
1029
|
-
observer2.subscribe(() => undefined)
|
|
1030
|
-
await queryClient.refetchQueries()
|
|
1031
|
-
observer1.destroy()
|
|
1032
|
-
observer2.destroy()
|
|
1033
|
-
expect(queryFn).toHaveBeenCalledTimes(2)
|
|
1034
|
-
})
|
|
1035
|
-
test('should refetch all queries when no arguments are given', async () => {
|
|
1036
|
-
const key1 = queryKey()
|
|
1037
|
-
const key2 = queryKey()
|
|
1038
|
-
const queryFn1 = vi
|
|
1039
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1040
|
-
.mockReturnValue('data1')
|
|
1041
|
-
const queryFn2 = vi
|
|
1042
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1043
|
-
.mockReturnValue('data2')
|
|
1044
|
-
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
|
|
1045
|
-
await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })
|
|
1046
|
-
const observer1 = new QueryObserver(queryClient, {
|
|
1047
|
-
queryKey: key1,
|
|
1048
|
-
queryFn: queryFn1,
|
|
1049
|
-
staleTime: Infinity,
|
|
1050
|
-
initialData: 'initial',
|
|
1051
|
-
})
|
|
1052
|
-
const observer2 = new QueryObserver(queryClient, {
|
|
1053
|
-
queryKey: key1,
|
|
1054
|
-
queryFn: queryFn1,
|
|
1055
|
-
staleTime: Infinity,
|
|
1056
|
-
initialData: 'initial',
|
|
1057
|
-
})
|
|
1058
|
-
observer1.subscribe(() => undefined)
|
|
1059
|
-
observer2.subscribe(() => undefined)
|
|
1060
|
-
await queryClient.refetchQueries()
|
|
1061
|
-
observer1.destroy()
|
|
1062
|
-
observer2.destroy()
|
|
1063
|
-
expect(queryFn1).toHaveBeenCalledTimes(2)
|
|
1064
|
-
expect(queryFn2).toHaveBeenCalledTimes(2)
|
|
1065
|
-
})
|
|
1066
|
-
|
|
1067
|
-
test('should be able to refetch all fresh queries', async () => {
|
|
1068
|
-
const key1 = queryKey()
|
|
1069
|
-
const key2 = queryKey()
|
|
1070
|
-
const queryFn1 = vi
|
|
1071
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1072
|
-
.mockReturnValue('data1')
|
|
1073
|
-
const queryFn2 = vi
|
|
1074
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1075
|
-
.mockReturnValue('data2')
|
|
1076
|
-
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
|
|
1077
|
-
await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })
|
|
1078
|
-
const observer = new QueryObserver(queryClient, {
|
|
1079
|
-
queryKey: key1,
|
|
1080
|
-
queryFn: queryFn1,
|
|
1081
|
-
staleTime: Infinity,
|
|
1082
|
-
})
|
|
1083
|
-
const unsubscribe = observer.subscribe(() => undefined)
|
|
1084
|
-
await queryClient.refetchQueries({ type: 'active', stale: false })
|
|
1085
|
-
unsubscribe()
|
|
1086
|
-
expect(queryFn1).toHaveBeenCalledTimes(2)
|
|
1087
|
-
expect(queryFn2).toHaveBeenCalledTimes(1)
|
|
1088
|
-
})
|
|
1089
|
-
|
|
1090
|
-
test('should be able to refetch all stale queries', async () => {
|
|
1091
|
-
const key1 = queryKey()
|
|
1092
|
-
const key2 = queryKey()
|
|
1093
|
-
const queryFn1 = vi
|
|
1094
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1095
|
-
.mockReturnValue('data1')
|
|
1096
|
-
const queryFn2 = vi
|
|
1097
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1098
|
-
.mockReturnValue('data2')
|
|
1099
|
-
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
|
|
1100
|
-
await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })
|
|
1101
|
-
const observer = new QueryObserver(queryClient, {
|
|
1102
|
-
queryKey: key1,
|
|
1103
|
-
queryFn: queryFn1,
|
|
1104
|
-
})
|
|
1105
|
-
const unsubscribe = observer.subscribe(() => undefined)
|
|
1106
|
-
queryClient.invalidateQueries({ queryKey: key1 })
|
|
1107
|
-
await queryClient.refetchQueries({ stale: true })
|
|
1108
|
-
unsubscribe()
|
|
1109
|
-
// fetchQuery, observer mount, invalidation (cancels observer mount) and refetch
|
|
1110
|
-
expect(queryFn1).toHaveBeenCalledTimes(4)
|
|
1111
|
-
expect(queryFn2).toHaveBeenCalledTimes(1)
|
|
1112
|
-
})
|
|
1113
|
-
|
|
1114
|
-
test('should be able to refetch all stale and active queries', async () => {
|
|
1115
|
-
const key1 = queryKey()
|
|
1116
|
-
const key2 = queryKey()
|
|
1117
|
-
const queryFn1 = vi
|
|
1118
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1119
|
-
.mockReturnValue('data1')
|
|
1120
|
-
const queryFn2 = vi
|
|
1121
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1122
|
-
.mockReturnValue('data2')
|
|
1123
|
-
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
|
|
1124
|
-
await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })
|
|
1125
|
-
queryClient.invalidateQueries({ queryKey: key1 })
|
|
1126
|
-
const observer = new QueryObserver(queryClient, {
|
|
1127
|
-
queryKey: key1,
|
|
1128
|
-
queryFn: queryFn1,
|
|
1129
|
-
})
|
|
1130
|
-
const unsubscribe = observer.subscribe(() => undefined)
|
|
1131
|
-
await queryClient.refetchQueries(
|
|
1132
|
-
{ type: 'active', stale: true },
|
|
1133
|
-
{ cancelRefetch: false },
|
|
1134
|
-
)
|
|
1135
|
-
unsubscribe()
|
|
1136
|
-
expect(queryFn1).toHaveBeenCalledTimes(2)
|
|
1137
|
-
expect(queryFn2).toHaveBeenCalledTimes(1)
|
|
1138
|
-
})
|
|
1139
|
-
|
|
1140
|
-
test('should be able to refetch all active and inactive queries (queryClient.refetchQueries()', async () => {
|
|
1141
|
-
const key1 = queryKey()
|
|
1142
|
-
const key2 = queryKey()
|
|
1143
|
-
const queryFn1 = vi
|
|
1144
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1145
|
-
.mockReturnValue('data1')
|
|
1146
|
-
const queryFn2 = vi
|
|
1147
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1148
|
-
.mockReturnValue('data2')
|
|
1149
|
-
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
|
|
1150
|
-
await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })
|
|
1151
|
-
const observer = new QueryObserver(queryClient, {
|
|
1152
|
-
queryKey: key1,
|
|
1153
|
-
queryFn: queryFn1,
|
|
1154
|
-
staleTime: Infinity,
|
|
1155
|
-
})
|
|
1156
|
-
const unsubscribe = observer.subscribe(() => undefined)
|
|
1157
|
-
await queryClient.refetchQueries()
|
|
1158
|
-
unsubscribe()
|
|
1159
|
-
expect(queryFn1).toHaveBeenCalledTimes(2)
|
|
1160
|
-
expect(queryFn2).toHaveBeenCalledTimes(2)
|
|
1161
|
-
})
|
|
1162
|
-
|
|
1163
|
-
test('should be able to refetch all active and inactive queries (queryClient.refetchQueries({ type: "all" }))', async () => {
|
|
1164
|
-
const key1 = queryKey()
|
|
1165
|
-
const key2 = queryKey()
|
|
1166
|
-
const queryFn1 = vi
|
|
1167
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1168
|
-
.mockReturnValue('data1')
|
|
1169
|
-
const queryFn2 = vi
|
|
1170
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1171
|
-
.mockReturnValue('data2')
|
|
1172
|
-
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
|
|
1173
|
-
await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })
|
|
1174
|
-
const observer = new QueryObserver(queryClient, {
|
|
1175
|
-
queryKey: key1,
|
|
1176
|
-
queryFn: queryFn1,
|
|
1177
|
-
staleTime: Infinity,
|
|
1178
|
-
})
|
|
1179
|
-
const unsubscribe = observer.subscribe(() => undefined)
|
|
1180
|
-
await queryClient.refetchQueries({ type: 'all' })
|
|
1181
|
-
unsubscribe()
|
|
1182
|
-
expect(queryFn1).toHaveBeenCalledTimes(2)
|
|
1183
|
-
expect(queryFn2).toHaveBeenCalledTimes(2)
|
|
1184
|
-
})
|
|
1185
|
-
|
|
1186
|
-
test('should be able to refetch only active queries', async () => {
|
|
1187
|
-
const key1 = queryKey()
|
|
1188
|
-
const key2 = queryKey()
|
|
1189
|
-
const queryFn1 = vi
|
|
1190
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1191
|
-
.mockReturnValue('data1')
|
|
1192
|
-
const queryFn2 = vi
|
|
1193
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1194
|
-
.mockReturnValue('data2')
|
|
1195
|
-
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
|
|
1196
|
-
await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })
|
|
1197
|
-
const observer = new QueryObserver(queryClient, {
|
|
1198
|
-
queryKey: key1,
|
|
1199
|
-
queryFn: queryFn1,
|
|
1200
|
-
staleTime: Infinity,
|
|
1201
|
-
})
|
|
1202
|
-
const unsubscribe = observer.subscribe(() => undefined)
|
|
1203
|
-
await queryClient.refetchQueries({ type: 'active' })
|
|
1204
|
-
unsubscribe()
|
|
1205
|
-
expect(queryFn1).toHaveBeenCalledTimes(2)
|
|
1206
|
-
expect(queryFn2).toHaveBeenCalledTimes(1)
|
|
1207
|
-
})
|
|
1208
|
-
|
|
1209
|
-
test('should be able to refetch only inactive queries', async () => {
|
|
1210
|
-
const key1 = queryKey()
|
|
1211
|
-
const key2 = queryKey()
|
|
1212
|
-
const queryFn1 = vi
|
|
1213
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1214
|
-
.mockReturnValue('data1')
|
|
1215
|
-
const queryFn2 = vi
|
|
1216
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1217
|
-
.mockReturnValue('data2')
|
|
1218
|
-
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
|
|
1219
|
-
await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })
|
|
1220
|
-
const observer = new QueryObserver(queryClient, {
|
|
1221
|
-
queryKey: key1,
|
|
1222
|
-
queryFn: queryFn1,
|
|
1223
|
-
staleTime: Infinity,
|
|
1224
|
-
})
|
|
1225
|
-
const unsubscribe = observer.subscribe(() => undefined)
|
|
1226
|
-
await queryClient.refetchQueries({ type: 'inactive' })
|
|
1227
|
-
unsubscribe()
|
|
1228
|
-
expect(queryFn1).toHaveBeenCalledTimes(1)
|
|
1229
|
-
expect(queryFn2).toHaveBeenCalledTimes(2)
|
|
1230
|
-
})
|
|
1231
|
-
|
|
1232
|
-
test('should throw an error if throwOnError option is set to true', async () => {
|
|
1233
|
-
const key1 = queryKey()
|
|
1234
|
-
const queryFnError = () => Promise.reject<unknown>('error')
|
|
1235
|
-
try {
|
|
1236
|
-
await queryClient.fetchQuery({
|
|
1237
|
-
queryKey: key1,
|
|
1238
|
-
queryFn: queryFnError,
|
|
1239
|
-
retry: false,
|
|
1240
|
-
})
|
|
1241
|
-
} catch {}
|
|
1242
|
-
let error: any
|
|
1243
|
-
try {
|
|
1244
|
-
await queryClient.refetchQueries(
|
|
1245
|
-
{ queryKey: key1 },
|
|
1246
|
-
{ throwOnError: true },
|
|
1247
|
-
)
|
|
1248
|
-
} catch (err) {
|
|
1249
|
-
error = err
|
|
1250
|
-
}
|
|
1251
|
-
expect(error).toEqual('error')
|
|
1252
|
-
})
|
|
1253
|
-
|
|
1254
|
-
test('should resolve Promise immediately if query is paused', async () => {
|
|
1255
|
-
const key1 = queryKey()
|
|
1256
|
-
const queryFn1 = vi
|
|
1257
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1258
|
-
.mockReturnValue('data1')
|
|
1259
|
-
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
|
|
1260
|
-
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
1261
|
-
|
|
1262
|
-
await queryClient.refetchQueries({ queryKey: key1 })
|
|
1263
|
-
|
|
1264
|
-
// if we reach this point, the test succeeds because the Promise was resolved immediately
|
|
1265
|
-
expect(queryFn1).toHaveBeenCalledTimes(1)
|
|
1266
|
-
onlineMock.mockRestore()
|
|
1267
|
-
})
|
|
1268
|
-
|
|
1269
|
-
test('should refetch if query we are offline but query networkMode is always', async () => {
|
|
1270
|
-
const key1 = queryKey()
|
|
1271
|
-
queryClient.setQueryDefaults(key1, { networkMode: 'always' })
|
|
1272
|
-
const queryFn1 = vi
|
|
1273
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1274
|
-
.mockReturnValue('data1')
|
|
1275
|
-
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
|
|
1276
|
-
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
1277
|
-
|
|
1278
|
-
await queryClient.refetchQueries({ queryKey: key1 })
|
|
1279
|
-
|
|
1280
|
-
// initial fetch + refetch (even though we are offline)
|
|
1281
|
-
expect(queryFn1).toHaveBeenCalledTimes(2)
|
|
1282
|
-
onlineMock.mockRestore()
|
|
1283
|
-
})
|
|
1284
|
-
})
|
|
1285
|
-
|
|
1286
|
-
describe('invalidateQueries', () => {
|
|
1287
|
-
test('should refetch active queries by default', async () => {
|
|
1288
|
-
const key1 = queryKey()
|
|
1289
|
-
const key2 = queryKey()
|
|
1290
|
-
const queryFn1 = vi
|
|
1291
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1292
|
-
.mockReturnValue('data1')
|
|
1293
|
-
const queryFn2 = vi
|
|
1294
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1295
|
-
.mockReturnValue('data2')
|
|
1296
|
-
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
|
|
1297
|
-
await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })
|
|
1298
|
-
const observer = new QueryObserver(queryClient, {
|
|
1299
|
-
queryKey: key1,
|
|
1300
|
-
queryFn: queryFn1,
|
|
1301
|
-
staleTime: Infinity,
|
|
1302
|
-
})
|
|
1303
|
-
const unsubscribe = observer.subscribe(() => undefined)
|
|
1304
|
-
queryClient.invalidateQueries({ queryKey: key1 })
|
|
1305
|
-
unsubscribe()
|
|
1306
|
-
expect(queryFn1).toHaveBeenCalledTimes(2)
|
|
1307
|
-
expect(queryFn2).toHaveBeenCalledTimes(1)
|
|
1308
|
-
})
|
|
1309
|
-
|
|
1310
|
-
test('should not refetch inactive queries by default', async () => {
|
|
1311
|
-
const key1 = queryKey()
|
|
1312
|
-
const key2 = queryKey()
|
|
1313
|
-
const queryFn1 = vi
|
|
1314
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1315
|
-
.mockReturnValue('data1')
|
|
1316
|
-
const queryFn2 = vi
|
|
1317
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1318
|
-
.mockReturnValue('data2')
|
|
1319
|
-
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
|
|
1320
|
-
await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })
|
|
1321
|
-
const observer = new QueryObserver(queryClient, {
|
|
1322
|
-
queryKey: key1,
|
|
1323
|
-
enabled: false,
|
|
1324
|
-
staleTime: Infinity,
|
|
1325
|
-
})
|
|
1326
|
-
const unsubscribe = observer.subscribe(() => undefined)
|
|
1327
|
-
queryClient.invalidateQueries({ queryKey: key1 })
|
|
1328
|
-
unsubscribe()
|
|
1329
|
-
expect(queryFn1).toHaveBeenCalledTimes(1)
|
|
1330
|
-
expect(queryFn2).toHaveBeenCalledTimes(1)
|
|
1331
|
-
})
|
|
1332
|
-
|
|
1333
|
-
test('should not refetch active queries when "refetch" is "none"', async () => {
|
|
1334
|
-
const key1 = queryKey()
|
|
1335
|
-
const key2 = queryKey()
|
|
1336
|
-
const queryFn1 = vi
|
|
1337
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1338
|
-
.mockReturnValue('data1')
|
|
1339
|
-
const queryFn2 = vi
|
|
1340
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1341
|
-
.mockReturnValue('data2')
|
|
1342
|
-
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
|
|
1343
|
-
await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })
|
|
1344
|
-
const observer = new QueryObserver(queryClient, {
|
|
1345
|
-
queryKey: key1,
|
|
1346
|
-
queryFn: queryFn1,
|
|
1347
|
-
staleTime: Infinity,
|
|
1348
|
-
})
|
|
1349
|
-
const unsubscribe = observer.subscribe(() => undefined)
|
|
1350
|
-
queryClient.invalidateQueries({
|
|
1351
|
-
queryKey: key1,
|
|
1352
|
-
refetchType: 'none',
|
|
1353
|
-
})
|
|
1354
|
-
unsubscribe()
|
|
1355
|
-
expect(queryFn1).toHaveBeenCalledTimes(1)
|
|
1356
|
-
expect(queryFn2).toHaveBeenCalledTimes(1)
|
|
1357
|
-
})
|
|
1358
|
-
|
|
1359
|
-
test('should refetch inactive queries when "refetch" is "inactive"', async () => {
|
|
1360
|
-
const key1 = queryKey()
|
|
1361
|
-
const key2 = queryKey()
|
|
1362
|
-
const queryFn1 = vi
|
|
1363
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1364
|
-
.mockReturnValue('data1')
|
|
1365
|
-
const queryFn2 = vi
|
|
1366
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1367
|
-
.mockReturnValue('data2')
|
|
1368
|
-
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
|
|
1369
|
-
await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })
|
|
1370
|
-
const observer = new QueryObserver(queryClient, {
|
|
1371
|
-
queryKey: key1,
|
|
1372
|
-
queryFn: queryFn1,
|
|
1373
|
-
staleTime: Infinity,
|
|
1374
|
-
refetchOnMount: false,
|
|
1375
|
-
})
|
|
1376
|
-
const unsubscribe = observer.subscribe(() => undefined)
|
|
1377
|
-
unsubscribe()
|
|
1378
|
-
|
|
1379
|
-
await queryClient.invalidateQueries({
|
|
1380
|
-
queryKey: key1,
|
|
1381
|
-
refetchType: 'inactive',
|
|
1382
|
-
})
|
|
1383
|
-
expect(queryFn1).toHaveBeenCalledTimes(2)
|
|
1384
|
-
expect(queryFn2).toHaveBeenCalledTimes(1)
|
|
1385
|
-
})
|
|
1386
|
-
|
|
1387
|
-
test('should refetch active and inactive queries when "refetch" is "all"', async () => {
|
|
1388
|
-
const key1 = queryKey()
|
|
1389
|
-
const key2 = queryKey()
|
|
1390
|
-
const queryFn1 = vi
|
|
1391
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1392
|
-
.mockReturnValue('data1')
|
|
1393
|
-
const queryFn2 = vi
|
|
1394
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1395
|
-
.mockReturnValue('data2')
|
|
1396
|
-
await queryClient.fetchQuery({ queryKey: key1, queryFn: queryFn1 })
|
|
1397
|
-
await queryClient.fetchQuery({ queryKey: key2, queryFn: queryFn2 })
|
|
1398
|
-
const observer = new QueryObserver(queryClient, {
|
|
1399
|
-
queryKey: key1,
|
|
1400
|
-
queryFn: queryFn1,
|
|
1401
|
-
staleTime: Infinity,
|
|
1402
|
-
})
|
|
1403
|
-
const unsubscribe = observer.subscribe(() => undefined)
|
|
1404
|
-
queryClient.invalidateQueries({
|
|
1405
|
-
refetchType: 'all',
|
|
1406
|
-
})
|
|
1407
|
-
unsubscribe()
|
|
1408
|
-
expect(queryFn1).toHaveBeenCalledTimes(2)
|
|
1409
|
-
expect(queryFn2).toHaveBeenCalledTimes(2)
|
|
1410
|
-
})
|
|
1411
|
-
|
|
1412
|
-
test('should not refetch disabled inactive queries even if "refetchType" is "all', async () => {
|
|
1413
|
-
const queryFn = vi
|
|
1414
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1415
|
-
.mockReturnValue('data1')
|
|
1416
|
-
const observer = new QueryObserver(queryClient, {
|
|
1417
|
-
queryKey: queryKey(),
|
|
1418
|
-
queryFn: queryFn,
|
|
1419
|
-
staleTime: Infinity,
|
|
1420
|
-
enabled: false,
|
|
1421
|
-
})
|
|
1422
|
-
const unsubscribe = observer.subscribe(() => undefined)
|
|
1423
|
-
unsubscribe()
|
|
1424
|
-
await queryClient.invalidateQueries({
|
|
1425
|
-
refetchType: 'all',
|
|
1426
|
-
})
|
|
1427
|
-
expect(queryFn).toHaveBeenCalledTimes(0)
|
|
1428
|
-
})
|
|
1429
|
-
|
|
1430
|
-
test('should not refetch inactive queries that have a skipToken queryFn even if "refetchType" is "all', async () => {
|
|
1431
|
-
const key = queryKey()
|
|
1432
|
-
const observer = new QueryObserver(queryClient, {
|
|
1433
|
-
queryKey: key,
|
|
1434
|
-
queryFn: skipToken,
|
|
1435
|
-
staleTime: Infinity,
|
|
1436
|
-
})
|
|
1437
|
-
|
|
1438
|
-
queryClient.setQueryData(key, 'data1')
|
|
1439
|
-
|
|
1440
|
-
const unsubscribe = observer.subscribe(() => undefined)
|
|
1441
|
-
unsubscribe()
|
|
1442
|
-
|
|
1443
|
-
expect(queryClient.getQueryState(key)?.dataUpdateCount).toBe(1)
|
|
1444
|
-
|
|
1445
|
-
await queryClient.invalidateQueries({
|
|
1446
|
-
refetchType: 'all',
|
|
1447
|
-
})
|
|
1448
|
-
|
|
1449
|
-
expect(queryClient.getQueryState(key)?.dataUpdateCount).toBe(1)
|
|
1450
|
-
})
|
|
1451
|
-
|
|
1452
|
-
test('should cancel ongoing fetches if cancelRefetch option is set (default value)', async () => {
|
|
1453
|
-
const key = queryKey()
|
|
1454
|
-
const abortFn = vi.fn()
|
|
1455
|
-
let fetchCount = 0
|
|
1456
|
-
const observer = new QueryObserver(queryClient, {
|
|
1457
|
-
queryKey: key,
|
|
1458
|
-
queryFn: ({ signal }) => {
|
|
1459
|
-
return new Promise((resolve) => {
|
|
1460
|
-
fetchCount++
|
|
1461
|
-
setTimeout(() => resolve(5), 10)
|
|
1462
|
-
signal.addEventListener('abort', abortFn)
|
|
1463
|
-
})
|
|
1464
|
-
},
|
|
1465
|
-
initialData: 1,
|
|
1466
|
-
})
|
|
1467
|
-
observer.subscribe(() => undefined)
|
|
1468
|
-
|
|
1469
|
-
await queryClient.refetchQueries()
|
|
1470
|
-
observer.destroy()
|
|
1471
|
-
expect(abortFn).toHaveBeenCalledTimes(1)
|
|
1472
|
-
expect(fetchCount).toBe(2)
|
|
1473
|
-
})
|
|
1474
|
-
|
|
1475
|
-
test('should not cancel ongoing fetches if cancelRefetch option is set to false', async () => {
|
|
1476
|
-
const key = queryKey()
|
|
1477
|
-
const abortFn = vi.fn()
|
|
1478
|
-
let fetchCount = 0
|
|
1479
|
-
const observer = new QueryObserver(queryClient, {
|
|
1480
|
-
queryKey: key,
|
|
1481
|
-
queryFn: ({ signal }) => {
|
|
1482
|
-
return new Promise((resolve) => {
|
|
1483
|
-
fetchCount++
|
|
1484
|
-
setTimeout(() => resolve(5), 10)
|
|
1485
|
-
signal.addEventListener('abort', abortFn)
|
|
1486
|
-
})
|
|
1487
|
-
},
|
|
1488
|
-
initialData: 1,
|
|
1489
|
-
})
|
|
1490
|
-
observer.subscribe(() => undefined)
|
|
1491
|
-
|
|
1492
|
-
await queryClient.refetchQueries(undefined, { cancelRefetch: false })
|
|
1493
|
-
observer.destroy()
|
|
1494
|
-
expect(abortFn).toHaveBeenCalledTimes(0)
|
|
1495
|
-
expect(fetchCount).toBe(1)
|
|
1496
|
-
})
|
|
1497
|
-
})
|
|
1498
|
-
|
|
1499
|
-
describe('resetQueries', () => {
|
|
1500
|
-
test('should notify listeners when a query is reset', async () => {
|
|
1501
|
-
const key = queryKey()
|
|
1502
|
-
|
|
1503
|
-
const callback = vi.fn()
|
|
1504
|
-
|
|
1505
|
-
await queryClient.prefetchQuery({ queryKey: key, queryFn: () => 'data' })
|
|
1506
|
-
|
|
1507
|
-
queryCache.subscribe(callback)
|
|
1508
|
-
|
|
1509
|
-
queryClient.resetQueries({ queryKey: key })
|
|
1510
|
-
|
|
1511
|
-
expect(callback).toHaveBeenCalled()
|
|
1512
|
-
})
|
|
1513
|
-
|
|
1514
|
-
test('should reset query', async () => {
|
|
1515
|
-
const key = queryKey()
|
|
1516
|
-
|
|
1517
|
-
await queryClient.prefetchQuery({ queryKey: key, queryFn: () => 'data' })
|
|
1518
|
-
|
|
1519
|
-
let state = queryClient.getQueryState(key)
|
|
1520
|
-
expect(state?.data).toEqual('data')
|
|
1521
|
-
expect(state?.status).toEqual('success')
|
|
1522
|
-
|
|
1523
|
-
queryClient.resetQueries({ queryKey: key })
|
|
1524
|
-
|
|
1525
|
-
state = queryClient.getQueryState(key)
|
|
1526
|
-
|
|
1527
|
-
expect(state).toBeTruthy()
|
|
1528
|
-
expect(state?.data).toBeUndefined()
|
|
1529
|
-
expect(state?.status).toEqual('pending')
|
|
1530
|
-
expect(state?.fetchStatus).toEqual('idle')
|
|
1531
|
-
})
|
|
1532
|
-
|
|
1533
|
-
test('should reset query data to initial data if set', async () => {
|
|
1534
|
-
const key = queryKey()
|
|
1535
|
-
|
|
1536
|
-
await queryClient.prefetchQuery({
|
|
1537
|
-
queryKey: key,
|
|
1538
|
-
queryFn: () => 'data',
|
|
1539
|
-
initialData: 'initial',
|
|
1540
|
-
})
|
|
1541
|
-
|
|
1542
|
-
let state = queryClient.getQueryState(key)
|
|
1543
|
-
expect(state?.data).toEqual('data')
|
|
1544
|
-
|
|
1545
|
-
queryClient.resetQueries({ queryKey: key })
|
|
1546
|
-
|
|
1547
|
-
state = queryClient.getQueryState(key)
|
|
1548
|
-
|
|
1549
|
-
expect(state).toBeTruthy()
|
|
1550
|
-
expect(state?.data).toEqual('initial')
|
|
1551
|
-
})
|
|
1552
|
-
|
|
1553
|
-
test('should refetch all active queries', async () => {
|
|
1554
|
-
const key1 = queryKey()
|
|
1555
|
-
const key2 = queryKey()
|
|
1556
|
-
const key3 = queryKey()
|
|
1557
|
-
const queryFn1 = vi
|
|
1558
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1559
|
-
.mockReturnValue('data1')
|
|
1560
|
-
const queryFn2 = vi
|
|
1561
|
-
.fn<(...args: Array<unknown>) => string>()
|
|
1562
|
-
.mockReturnValue('data2')
|
|
1563
|
-
const observer1 = new QueryObserver(queryClient, {
|
|
1564
|
-
queryKey: key1,
|
|
1565
|
-
queryFn: queryFn1,
|
|
1566
|
-
enabled: true,
|
|
1567
|
-
})
|
|
1568
|
-
const observer2 = new QueryObserver(queryClient, {
|
|
1569
|
-
queryKey: key2,
|
|
1570
|
-
queryFn: queryFn2,
|
|
1571
|
-
enabled: false,
|
|
1572
|
-
})
|
|
1573
|
-
const observer3 = new QueryObserver(queryClient, {
|
|
1574
|
-
queryKey: key3,
|
|
1575
|
-
queryFn: skipToken,
|
|
1576
|
-
})
|
|
1577
|
-
let didSkipTokenRun = false
|
|
1578
|
-
observer1.subscribe(() => undefined)
|
|
1579
|
-
observer2.subscribe(() => undefined)
|
|
1580
|
-
observer3.subscribe(() => (didSkipTokenRun = true))
|
|
1581
|
-
await queryClient.resetQueries()
|
|
1582
|
-
observer3.destroy()
|
|
1583
|
-
observer2.destroy()
|
|
1584
|
-
observer1.destroy()
|
|
1585
|
-
expect(queryFn1).toHaveBeenCalledTimes(2)
|
|
1586
|
-
expect(queryFn2).toHaveBeenCalledTimes(0)
|
|
1587
|
-
expect(didSkipTokenRun).toBe(false)
|
|
1588
|
-
})
|
|
1589
|
-
})
|
|
1590
|
-
|
|
1591
|
-
describe('focusManager and onlineManager', () => {
|
|
1592
|
-
afterEach(() => {
|
|
1593
|
-
onlineManager.setOnline(true)
|
|
1594
|
-
focusManager.setFocused(undefined)
|
|
1595
|
-
})
|
|
1596
|
-
test('should notify queryCache and mutationCache if focused', async () => {
|
|
1597
|
-
const testClient = createQueryClient()
|
|
1598
|
-
testClient.mount()
|
|
1599
|
-
|
|
1600
|
-
const queryCacheOnFocusSpy = vi.spyOn(
|
|
1601
|
-
testClient.getQueryCache(),
|
|
1602
|
-
'onFocus',
|
|
1603
|
-
)
|
|
1604
|
-
const queryCacheOnOnlineSpy = vi.spyOn(
|
|
1605
|
-
testClient.getQueryCache(),
|
|
1606
|
-
'onOnline',
|
|
1607
|
-
)
|
|
1608
|
-
const mutationCacheResumePausedMutationsSpy = vi.spyOn(
|
|
1609
|
-
testClient.getMutationCache(),
|
|
1610
|
-
'resumePausedMutations',
|
|
1611
|
-
)
|
|
1612
|
-
|
|
1613
|
-
focusManager.setFocused(false)
|
|
1614
|
-
expect(queryCacheOnFocusSpy).not.toHaveBeenCalled()
|
|
1615
|
-
expect(mutationCacheResumePausedMutationsSpy).not.toHaveBeenCalled()
|
|
1616
|
-
|
|
1617
|
-
focusManager.setFocused(true)
|
|
1618
|
-
await waitFor(() => expect(queryCacheOnFocusSpy).toHaveBeenCalledTimes(1))
|
|
1619
|
-
expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(1)
|
|
1620
|
-
|
|
1621
|
-
expect(queryCacheOnOnlineSpy).not.toHaveBeenCalled()
|
|
1622
|
-
|
|
1623
|
-
queryCacheOnFocusSpy.mockRestore()
|
|
1624
|
-
mutationCacheResumePausedMutationsSpy.mockRestore()
|
|
1625
|
-
queryCacheOnOnlineSpy.mockRestore()
|
|
1626
|
-
})
|
|
1627
|
-
|
|
1628
|
-
test('should notify queryCache and mutationCache if online', async () => {
|
|
1629
|
-
const testClient = createQueryClient()
|
|
1630
|
-
testClient.mount()
|
|
1631
|
-
|
|
1632
|
-
const queryCacheOnFocusSpy = vi.spyOn(
|
|
1633
|
-
testClient.getQueryCache(),
|
|
1634
|
-
'onFocus',
|
|
1635
|
-
)
|
|
1636
|
-
const queryCacheOnOnlineSpy = vi.spyOn(
|
|
1637
|
-
testClient.getQueryCache(),
|
|
1638
|
-
'onOnline',
|
|
1639
|
-
)
|
|
1640
|
-
const mutationCacheResumePausedMutationsSpy = vi.spyOn(
|
|
1641
|
-
testClient.getMutationCache(),
|
|
1642
|
-
'resumePausedMutations',
|
|
1643
|
-
)
|
|
1644
|
-
|
|
1645
|
-
onlineManager.setOnline(false)
|
|
1646
|
-
expect(queryCacheOnOnlineSpy).not.toHaveBeenCalled()
|
|
1647
|
-
expect(mutationCacheResumePausedMutationsSpy).not.toHaveBeenCalled()
|
|
1648
|
-
|
|
1649
|
-
onlineManager.setOnline(true)
|
|
1650
|
-
await waitFor(() =>
|
|
1651
|
-
expect(queryCacheOnOnlineSpy).toHaveBeenCalledTimes(1),
|
|
1652
|
-
)
|
|
1653
|
-
|
|
1654
|
-
expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(1)
|
|
1655
|
-
|
|
1656
|
-
expect(queryCacheOnFocusSpy).not.toHaveBeenCalled()
|
|
1657
|
-
|
|
1658
|
-
queryCacheOnFocusSpy.mockRestore()
|
|
1659
|
-
queryCacheOnOnlineSpy.mockRestore()
|
|
1660
|
-
mutationCacheResumePausedMutationsSpy.mockRestore()
|
|
1661
|
-
})
|
|
1662
|
-
|
|
1663
|
-
test('should resume paused mutations when coming online', async () => {
|
|
1664
|
-
const consoleMock = vi.spyOn(console, 'error')
|
|
1665
|
-
consoleMock.mockImplementation(() => undefined)
|
|
1666
|
-
onlineManager.setOnline(false)
|
|
1667
|
-
|
|
1668
|
-
const observer1 = new MutationObserver(queryClient, {
|
|
1669
|
-
mutationFn: async () => 1,
|
|
1670
|
-
})
|
|
1671
|
-
|
|
1672
|
-
const observer2 = new MutationObserver(queryClient, {
|
|
1673
|
-
mutationFn: async () => 2,
|
|
1674
|
-
})
|
|
1675
|
-
void observer1.mutate()
|
|
1676
|
-
void observer2.mutate()
|
|
1677
|
-
|
|
1678
|
-
await waitFor(() => {
|
|
1679
|
-
expect(observer1.getCurrentResult().isPaused).toBeTruthy()
|
|
1680
|
-
expect(observer2.getCurrentResult().isPaused).toBeTruthy()
|
|
1681
|
-
})
|
|
1682
|
-
|
|
1683
|
-
onlineManager.setOnline(true)
|
|
1684
|
-
|
|
1685
|
-
await waitFor(() => {
|
|
1686
|
-
expect(observer1.getCurrentResult().status).toBe('success')
|
|
1687
|
-
expect(observer2.getCurrentResult().status).toBe('success')
|
|
1688
|
-
})
|
|
1689
|
-
})
|
|
1690
|
-
|
|
1691
|
-
test('should resume paused mutations in parallel', async () => {
|
|
1692
|
-
onlineManager.setOnline(false)
|
|
1693
|
-
|
|
1694
|
-
const orders: Array<string> = []
|
|
1695
|
-
|
|
1696
|
-
const observer1 = new MutationObserver(queryClient, {
|
|
1697
|
-
mutationFn: async () => {
|
|
1698
|
-
orders.push('1start')
|
|
1699
|
-
await sleep(50)
|
|
1700
|
-
orders.push('1end')
|
|
1701
|
-
return 1
|
|
1702
|
-
},
|
|
1703
|
-
})
|
|
1704
|
-
|
|
1705
|
-
const observer2 = new MutationObserver(queryClient, {
|
|
1706
|
-
mutationFn: async () => {
|
|
1707
|
-
orders.push('2start')
|
|
1708
|
-
await sleep(20)
|
|
1709
|
-
orders.push('2end')
|
|
1710
|
-
return 2
|
|
1711
|
-
},
|
|
1712
|
-
})
|
|
1713
|
-
void observer1.mutate()
|
|
1714
|
-
void observer2.mutate()
|
|
1715
|
-
|
|
1716
|
-
await waitFor(() => {
|
|
1717
|
-
expect(observer1.getCurrentResult().isPaused).toBeTruthy()
|
|
1718
|
-
expect(observer2.getCurrentResult().isPaused).toBeTruthy()
|
|
1719
|
-
})
|
|
1720
|
-
|
|
1721
|
-
onlineManager.setOnline(true)
|
|
1722
|
-
|
|
1723
|
-
await waitFor(() => {
|
|
1724
|
-
expect(observer1.getCurrentResult().status).toBe('success')
|
|
1725
|
-
expect(observer2.getCurrentResult().status).toBe('success')
|
|
1726
|
-
})
|
|
1727
|
-
|
|
1728
|
-
expect(orders).toEqual(['1start', '2start', '2end', '1end'])
|
|
1729
|
-
})
|
|
1730
|
-
|
|
1731
|
-
test('should resume paused mutations one after the other when in the same scope when invoked manually at the same time', async () => {
|
|
1732
|
-
const consoleMock = vi.spyOn(console, 'error')
|
|
1733
|
-
consoleMock.mockImplementation(() => undefined)
|
|
1734
|
-
onlineManager.setOnline(false)
|
|
1735
|
-
|
|
1736
|
-
const orders: Array<string> = []
|
|
1737
|
-
|
|
1738
|
-
const observer1 = new MutationObserver(queryClient, {
|
|
1739
|
-
scope: {
|
|
1740
|
-
id: 'scope',
|
|
1741
|
-
},
|
|
1742
|
-
mutationFn: async () => {
|
|
1743
|
-
orders.push('1start')
|
|
1744
|
-
await sleep(50)
|
|
1745
|
-
orders.push('1end')
|
|
1746
|
-
return 1
|
|
1747
|
-
},
|
|
1748
|
-
})
|
|
1749
|
-
|
|
1750
|
-
const observer2 = new MutationObserver(queryClient, {
|
|
1751
|
-
scope: {
|
|
1752
|
-
id: 'scope',
|
|
1753
|
-
},
|
|
1754
|
-
mutationFn: async () => {
|
|
1755
|
-
orders.push('2start')
|
|
1756
|
-
await sleep(20)
|
|
1757
|
-
orders.push('2end')
|
|
1758
|
-
return 2
|
|
1759
|
-
},
|
|
1760
|
-
})
|
|
1761
|
-
void observer1.mutate()
|
|
1762
|
-
void observer2.mutate()
|
|
1763
|
-
|
|
1764
|
-
await waitFor(() => {
|
|
1765
|
-
expect(observer1.getCurrentResult().isPaused).toBeTruthy()
|
|
1766
|
-
expect(observer2.getCurrentResult().isPaused).toBeTruthy()
|
|
1767
|
-
})
|
|
1768
|
-
|
|
1769
|
-
onlineManager.setOnline(true)
|
|
1770
|
-
void queryClient.resumePausedMutations()
|
|
1771
|
-
await sleep(5)
|
|
1772
|
-
await queryClient.resumePausedMutations()
|
|
1773
|
-
|
|
1774
|
-
await waitFor(() => {
|
|
1775
|
-
expect(observer1.getCurrentResult().status).toBe('success')
|
|
1776
|
-
expect(observer2.getCurrentResult().status).toBe('success')
|
|
1777
|
-
})
|
|
1778
|
-
|
|
1779
|
-
expect(orders).toEqual(['1start', '1end', '2start', '2end'])
|
|
1780
|
-
})
|
|
1781
|
-
|
|
1782
|
-
test('should resumePausedMutations when coming online after having called resumePausedMutations while offline', async () => {
|
|
1783
|
-
const consoleMock = vi.spyOn(console, 'error')
|
|
1784
|
-
consoleMock.mockImplementation(() => undefined)
|
|
1785
|
-
onlineManager.setOnline(false)
|
|
1786
|
-
|
|
1787
|
-
const observer = new MutationObserver(queryClient, {
|
|
1788
|
-
mutationFn: async () => 1,
|
|
1789
|
-
})
|
|
1790
|
-
|
|
1791
|
-
void observer.mutate()
|
|
1792
|
-
|
|
1793
|
-
expect(observer.getCurrentResult().isPaused).toBeTruthy()
|
|
1794
|
-
|
|
1795
|
-
await queryClient.resumePausedMutations()
|
|
1796
|
-
|
|
1797
|
-
// still paused because we are still offline
|
|
1798
|
-
expect(observer.getCurrentResult().isPaused).toBeTruthy()
|
|
1799
|
-
|
|
1800
|
-
onlineManager.setOnline(true)
|
|
1801
|
-
|
|
1802
|
-
await waitFor(() => {
|
|
1803
|
-
expect(observer.getCurrentResult().status).toBe('success')
|
|
1804
|
-
})
|
|
1805
|
-
})
|
|
1806
|
-
|
|
1807
|
-
test('should resumePausedMutations when coming online after having restored cache (and resumed) while offline', async () => {
|
|
1808
|
-
const consoleMock = vi.spyOn(console, 'error')
|
|
1809
|
-
consoleMock.mockImplementation(() => undefined)
|
|
1810
|
-
onlineManager.setOnline(false)
|
|
1811
|
-
|
|
1812
|
-
const observer = new MutationObserver(queryClient, {
|
|
1813
|
-
mutationFn: async () => 1,
|
|
1814
|
-
})
|
|
1815
|
-
|
|
1816
|
-
void observer.mutate()
|
|
1817
|
-
|
|
1818
|
-
expect(observer.getCurrentResult().isPaused).toBeTruthy()
|
|
1819
|
-
|
|
1820
|
-
const state = dehydrate(queryClient)
|
|
1821
|
-
|
|
1822
|
-
const newQueryClient = new QueryClient({
|
|
1823
|
-
defaultOptions: {
|
|
1824
|
-
mutations: {
|
|
1825
|
-
mutationFn: async () => 1,
|
|
1826
|
-
},
|
|
1827
|
-
},
|
|
1828
|
-
})
|
|
1829
|
-
|
|
1830
|
-
newQueryClient.mount()
|
|
1831
|
-
|
|
1832
|
-
hydrate(newQueryClient, state)
|
|
1833
|
-
|
|
1834
|
-
// still paused because we are still offline
|
|
1835
|
-
expect(
|
|
1836
|
-
newQueryClient.getMutationCache().getAll()[0]?.state.isPaused,
|
|
1837
|
-
).toBeTruthy()
|
|
1838
|
-
|
|
1839
|
-
await newQueryClient.resumePausedMutations()
|
|
1840
|
-
|
|
1841
|
-
onlineManager.setOnline(true)
|
|
1842
|
-
|
|
1843
|
-
await waitFor(() => {
|
|
1844
|
-
expect(
|
|
1845
|
-
newQueryClient.getMutationCache().getAll()[0]?.state.status,
|
|
1846
|
-
).toBe('success')
|
|
1847
|
-
})
|
|
1848
|
-
|
|
1849
|
-
newQueryClient.unmount()
|
|
1850
|
-
})
|
|
1851
|
-
|
|
1852
|
-
test('should notify queryCache after resumePausedMutations has finished when coming online', async () => {
|
|
1853
|
-
const key = queryKey()
|
|
1854
|
-
|
|
1855
|
-
let count = 0
|
|
1856
|
-
const results: Array<string> = []
|
|
1857
|
-
|
|
1858
|
-
const queryObserver = new QueryObserver(queryClient, {
|
|
1859
|
-
queryKey: key,
|
|
1860
|
-
queryFn: async () => {
|
|
1861
|
-
count++
|
|
1862
|
-
results.push('data' + count)
|
|
1863
|
-
await sleep(10)
|
|
1864
|
-
return 'data' + count
|
|
1865
|
-
},
|
|
1866
|
-
})
|
|
1867
|
-
|
|
1868
|
-
const unsubscribe = queryObserver.subscribe(() => undefined)
|
|
1869
|
-
|
|
1870
|
-
await waitFor(() => {
|
|
1871
|
-
expect(queryClient.getQueryData(key)).toBe('data1')
|
|
1872
|
-
})
|
|
1873
|
-
|
|
1874
|
-
onlineManager.setOnline(false)
|
|
1875
|
-
|
|
1876
|
-
const observer = new MutationObserver(queryClient, {
|
|
1877
|
-
mutationFn: async () => {
|
|
1878
|
-
results.push('mutation1-start')
|
|
1879
|
-
await sleep(50)
|
|
1880
|
-
results.push('mutation1-end')
|
|
1881
|
-
return 1
|
|
1882
|
-
},
|
|
1883
|
-
})
|
|
1884
|
-
|
|
1885
|
-
void observer.mutate()
|
|
1886
|
-
|
|
1887
|
-
const observer2 = new MutationObserver(queryClient, {
|
|
1888
|
-
scope: {
|
|
1889
|
-
id: 'scope',
|
|
1890
|
-
},
|
|
1891
|
-
mutationFn: async () => {
|
|
1892
|
-
results.push('mutation2-start')
|
|
1893
|
-
await sleep(50)
|
|
1894
|
-
results.push('mutation2-end')
|
|
1895
|
-
return 2
|
|
1896
|
-
},
|
|
1897
|
-
})
|
|
1898
|
-
|
|
1899
|
-
void observer2.mutate()
|
|
1900
|
-
|
|
1901
|
-
const observer3 = new MutationObserver(queryClient, {
|
|
1902
|
-
scope: {
|
|
1903
|
-
id: 'scope',
|
|
1904
|
-
},
|
|
1905
|
-
mutationFn: async () => {
|
|
1906
|
-
results.push('mutation3-start')
|
|
1907
|
-
await sleep(50)
|
|
1908
|
-
results.push('mutation3-end')
|
|
1909
|
-
return 3
|
|
1910
|
-
},
|
|
1911
|
-
})
|
|
1912
|
-
|
|
1913
|
-
void observer3.mutate()
|
|
1914
|
-
|
|
1915
|
-
await waitFor(() =>
|
|
1916
|
-
expect(observer.getCurrentResult().isPaused).toBeTruthy(),
|
|
1917
|
-
)
|
|
1918
|
-
await waitFor(() =>
|
|
1919
|
-
expect(observer2.getCurrentResult().isPaused).toBeTruthy(),
|
|
1920
|
-
)
|
|
1921
|
-
await waitFor(() =>
|
|
1922
|
-
expect(observer3.getCurrentResult().isPaused).toBeTruthy(),
|
|
1923
|
-
)
|
|
1924
|
-
|
|
1925
|
-
onlineManager.setOnline(true)
|
|
1926
|
-
|
|
1927
|
-
await waitFor(() => {
|
|
1928
|
-
expect(queryClient.getQueryData(key)).toBe('data2')
|
|
1929
|
-
})
|
|
1930
|
-
|
|
1931
|
-
// refetch from coming online should happen after mutations have finished
|
|
1932
|
-
expect(results).toStrictEqual([
|
|
1933
|
-
'data1',
|
|
1934
|
-
'mutation1-start',
|
|
1935
|
-
'mutation2-start',
|
|
1936
|
-
'mutation1-end',
|
|
1937
|
-
'mutation2-end',
|
|
1938
|
-
'mutation3-start', // 3 starts after 2 because they are in the same scope
|
|
1939
|
-
'mutation3-end',
|
|
1940
|
-
'data2',
|
|
1941
|
-
])
|
|
1942
|
-
|
|
1943
|
-
unsubscribe()
|
|
1944
|
-
})
|
|
1945
|
-
|
|
1946
|
-
test('should notify queryCache and mutationCache after multiple mounts and single unmount', async () => {
|
|
1947
|
-
const testClient = createQueryClient()
|
|
1948
|
-
testClient.mount()
|
|
1949
|
-
testClient.mount()
|
|
1950
|
-
testClient.unmount()
|
|
1951
|
-
|
|
1952
|
-
const queryCacheOnFocusSpy = vi.spyOn(
|
|
1953
|
-
testClient.getQueryCache(),
|
|
1954
|
-
'onFocus',
|
|
1955
|
-
)
|
|
1956
|
-
const queryCacheOnOnlineSpy = vi.spyOn(
|
|
1957
|
-
testClient.getQueryCache(),
|
|
1958
|
-
'onOnline',
|
|
1959
|
-
)
|
|
1960
|
-
const mutationCacheResumePausedMutationsSpy = vi.spyOn(
|
|
1961
|
-
testClient.getMutationCache(),
|
|
1962
|
-
'resumePausedMutations',
|
|
1963
|
-
)
|
|
1964
|
-
|
|
1965
|
-
onlineManager.setOnline(false)
|
|
1966
|
-
onlineManager.setOnline(true)
|
|
1967
|
-
await waitFor(() =>
|
|
1968
|
-
expect(queryCacheOnOnlineSpy).toHaveBeenCalledTimes(1),
|
|
1969
|
-
)
|
|
1970
|
-
expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(1)
|
|
1971
|
-
|
|
1972
|
-
focusManager.setFocused(true)
|
|
1973
|
-
await waitFor(() => expect(queryCacheOnFocusSpy).toHaveBeenCalledTimes(1))
|
|
1974
|
-
expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(2)
|
|
1975
|
-
|
|
1976
|
-
queryCacheOnFocusSpy.mockRestore()
|
|
1977
|
-
queryCacheOnOnlineSpy.mockRestore()
|
|
1978
|
-
mutationCacheResumePausedMutationsSpy.mockRestore()
|
|
1979
|
-
focusManager.setFocused(undefined)
|
|
1980
|
-
onlineManager.setOnline(true)
|
|
1981
|
-
})
|
|
1982
|
-
|
|
1983
|
-
test('should not notify queryCache and mutationCache after multiple mounts/unmounts', async () => {
|
|
1984
|
-
const testClient = createQueryClient()
|
|
1985
|
-
testClient.mount()
|
|
1986
|
-
testClient.mount()
|
|
1987
|
-
testClient.unmount()
|
|
1988
|
-
testClient.unmount()
|
|
1989
|
-
|
|
1990
|
-
const queryCacheOnFocusSpy = vi.spyOn(
|
|
1991
|
-
testClient.getQueryCache(),
|
|
1992
|
-
'onFocus',
|
|
1993
|
-
)
|
|
1994
|
-
const queryCacheOnOnlineSpy = vi.spyOn(
|
|
1995
|
-
testClient.getQueryCache(),
|
|
1996
|
-
'onOnline',
|
|
1997
|
-
)
|
|
1998
|
-
const mutationCacheResumePausedMutationsSpy = vi.spyOn(
|
|
1999
|
-
testClient.getMutationCache(),
|
|
2000
|
-
'resumePausedMutations',
|
|
2001
|
-
)
|
|
2002
|
-
|
|
2003
|
-
onlineManager.setOnline(true)
|
|
2004
|
-
expect(queryCacheOnOnlineSpy).not.toHaveBeenCalled()
|
|
2005
|
-
expect(mutationCacheResumePausedMutationsSpy).not.toHaveBeenCalled()
|
|
2006
|
-
|
|
2007
|
-
focusManager.setFocused(true)
|
|
2008
|
-
expect(queryCacheOnFocusSpy).not.toHaveBeenCalled()
|
|
2009
|
-
expect(mutationCacheResumePausedMutationsSpy).not.toHaveBeenCalled()
|
|
2010
|
-
|
|
2011
|
-
queryCacheOnFocusSpy.mockRestore()
|
|
2012
|
-
queryCacheOnOnlineSpy.mockRestore()
|
|
2013
|
-
mutationCacheResumePausedMutationsSpy.mockRestore()
|
|
2014
|
-
focusManager.setFocused(undefined)
|
|
2015
|
-
onlineManager.setOnline(true)
|
|
2016
|
-
})
|
|
2017
|
-
})
|
|
2018
|
-
|
|
2019
|
-
describe('setMutationDefaults', () => {
|
|
2020
|
-
test('should update existing mutation defaults', () => {
|
|
2021
|
-
const key = queryKey()
|
|
2022
|
-
const mutationOptions1 = { mutationFn: async () => 'data' }
|
|
2023
|
-
const mutationOptions2 = { retry: false }
|
|
2024
|
-
queryClient.setMutationDefaults(key, mutationOptions1)
|
|
2025
|
-
queryClient.setMutationDefaults(key, mutationOptions2)
|
|
2026
|
-
expect(queryClient.getMutationDefaults(key)).toMatchObject(
|
|
2027
|
-
mutationOptions2,
|
|
2028
|
-
)
|
|
2029
|
-
})
|
|
2030
|
-
})
|
|
2031
|
-
})
|