@tanstack/query-core 5.59.17 → 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/package.json +3 -2
- 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,1069 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test, vi } from 'vitest'
|
|
2
|
-
import { waitFor } from '@testing-library/react'
|
|
3
|
-
import { QueryCache } from '../queryCache'
|
|
4
|
-
import { dehydrate, hydrate } from '../hydration'
|
|
5
|
-
import { MutationCache } from '../mutationCache'
|
|
6
|
-
import {
|
|
7
|
-
createQueryClient,
|
|
8
|
-
executeMutation,
|
|
9
|
-
mockOnlineManagerIsOnline,
|
|
10
|
-
sleep,
|
|
11
|
-
} from './utils'
|
|
12
|
-
|
|
13
|
-
async function fetchData<TData>(value: TData, ms?: number): Promise<TData> {
|
|
14
|
-
await sleep(ms || 0)
|
|
15
|
-
return value
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async function fetchDate(value: string, ms?: number): Promise<Date> {
|
|
19
|
-
await sleep(ms || 0)
|
|
20
|
-
return new Date(value)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
describe('dehydration and rehydration', () => {
|
|
24
|
-
test('should work with serializable values', async () => {
|
|
25
|
-
const queryCache = new QueryCache()
|
|
26
|
-
const queryClient = createQueryClient({ queryCache })
|
|
27
|
-
await queryClient.prefetchQuery({
|
|
28
|
-
queryKey: ['string'],
|
|
29
|
-
queryFn: () => fetchData('string'),
|
|
30
|
-
})
|
|
31
|
-
await queryClient.prefetchQuery({
|
|
32
|
-
queryKey: ['number'],
|
|
33
|
-
queryFn: () => fetchData(1),
|
|
34
|
-
})
|
|
35
|
-
await queryClient.prefetchQuery({
|
|
36
|
-
queryKey: ['boolean'],
|
|
37
|
-
queryFn: () => fetchData(true),
|
|
38
|
-
})
|
|
39
|
-
await queryClient.prefetchQuery({
|
|
40
|
-
queryKey: ['null'],
|
|
41
|
-
queryFn: () => fetchData(null),
|
|
42
|
-
})
|
|
43
|
-
await queryClient.prefetchQuery({
|
|
44
|
-
queryKey: ['array'],
|
|
45
|
-
queryFn: () => fetchData(['string', 0]),
|
|
46
|
-
})
|
|
47
|
-
await queryClient.prefetchQuery({
|
|
48
|
-
queryKey: ['nested'],
|
|
49
|
-
queryFn: () => fetchData({ key: [{ nestedKey: 1 }] }),
|
|
50
|
-
})
|
|
51
|
-
const dehydrated = dehydrate(queryClient)
|
|
52
|
-
const stringified = JSON.stringify(dehydrated)
|
|
53
|
-
|
|
54
|
-
// ---
|
|
55
|
-
|
|
56
|
-
const parsed = JSON.parse(stringified)
|
|
57
|
-
const hydrationCache = new QueryCache()
|
|
58
|
-
const hydrationClient = createQueryClient({
|
|
59
|
-
queryCache: hydrationCache,
|
|
60
|
-
})
|
|
61
|
-
hydrate(hydrationClient, parsed)
|
|
62
|
-
expect(hydrationCache.find({ queryKey: ['string'] })?.state.data).toBe(
|
|
63
|
-
'string',
|
|
64
|
-
)
|
|
65
|
-
expect(hydrationCache.find({ queryKey: ['number'] })?.state.data).toBe(1)
|
|
66
|
-
expect(hydrationCache.find({ queryKey: ['boolean'] })?.state.data).toBe(
|
|
67
|
-
true,
|
|
68
|
-
)
|
|
69
|
-
expect(hydrationCache.find({ queryKey: ['null'] })?.state.data).toBe(null)
|
|
70
|
-
expect(hydrationCache.find({ queryKey: ['array'] })?.state.data).toEqual([
|
|
71
|
-
'string',
|
|
72
|
-
0,
|
|
73
|
-
])
|
|
74
|
-
expect(hydrationCache.find({ queryKey: ['nested'] })?.state.data).toEqual({
|
|
75
|
-
key: [{ nestedKey: 1 }],
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
const fetchDataAfterHydration =
|
|
79
|
-
vi.fn<(...args: Array<unknown>) => unknown>()
|
|
80
|
-
await hydrationClient.prefetchQuery({
|
|
81
|
-
queryKey: ['string'],
|
|
82
|
-
queryFn: fetchDataAfterHydration,
|
|
83
|
-
staleTime: 1000,
|
|
84
|
-
})
|
|
85
|
-
await hydrationClient.prefetchQuery({
|
|
86
|
-
queryKey: ['number'],
|
|
87
|
-
queryFn: fetchDataAfterHydration,
|
|
88
|
-
staleTime: 1000,
|
|
89
|
-
})
|
|
90
|
-
await hydrationClient.prefetchQuery({
|
|
91
|
-
queryKey: ['boolean'],
|
|
92
|
-
queryFn: fetchDataAfterHydration,
|
|
93
|
-
staleTime: 1000,
|
|
94
|
-
})
|
|
95
|
-
await hydrationClient.prefetchQuery({
|
|
96
|
-
queryKey: ['null'],
|
|
97
|
-
queryFn: fetchDataAfterHydration,
|
|
98
|
-
staleTime: 1000,
|
|
99
|
-
})
|
|
100
|
-
await hydrationClient.prefetchQuery({
|
|
101
|
-
queryKey: ['array'],
|
|
102
|
-
queryFn: fetchDataAfterHydration,
|
|
103
|
-
staleTime: 1000,
|
|
104
|
-
})
|
|
105
|
-
await hydrationClient.prefetchQuery({
|
|
106
|
-
queryKey: ['nested'],
|
|
107
|
-
queryFn: fetchDataAfterHydration,
|
|
108
|
-
staleTime: 1000,
|
|
109
|
-
})
|
|
110
|
-
expect(fetchDataAfterHydration).toHaveBeenCalledTimes(0)
|
|
111
|
-
|
|
112
|
-
queryClient.clear()
|
|
113
|
-
hydrationClient.clear()
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
test('should not dehydrate queries if dehydrateQueries is set to false', async () => {
|
|
117
|
-
const queryCache = new QueryCache()
|
|
118
|
-
const queryClient = createQueryClient({ queryCache })
|
|
119
|
-
await queryClient.prefetchQuery({
|
|
120
|
-
queryKey: ['string'],
|
|
121
|
-
queryFn: () => fetchData('string'),
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
const dehydrated = dehydrate(queryClient, {
|
|
125
|
-
shouldDehydrateQuery: () => false,
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
expect(dehydrated.queries.length).toBe(0)
|
|
129
|
-
|
|
130
|
-
queryClient.clear()
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
test('should use the garbage collection time from the client', async () => {
|
|
134
|
-
const queryCache = new QueryCache()
|
|
135
|
-
const queryClient = createQueryClient({ queryCache })
|
|
136
|
-
await queryClient.prefetchQuery({
|
|
137
|
-
queryKey: ['string'],
|
|
138
|
-
queryFn: () => fetchData('string'),
|
|
139
|
-
gcTime: 50,
|
|
140
|
-
})
|
|
141
|
-
const dehydrated = dehydrate(queryClient)
|
|
142
|
-
const stringified = JSON.stringify(dehydrated)
|
|
143
|
-
|
|
144
|
-
await sleep(20)
|
|
145
|
-
|
|
146
|
-
// ---
|
|
147
|
-
|
|
148
|
-
const parsed = JSON.parse(stringified)
|
|
149
|
-
const hydrationCache = new QueryCache()
|
|
150
|
-
const hydrationClient = createQueryClient({ queryCache: hydrationCache })
|
|
151
|
-
hydrate(hydrationClient, parsed)
|
|
152
|
-
expect(hydrationCache.find({ queryKey: ['string'] })?.state.data).toBe(
|
|
153
|
-
'string',
|
|
154
|
-
)
|
|
155
|
-
await sleep(100)
|
|
156
|
-
expect(hydrationCache.find({ queryKey: ['string'] })).toBeTruthy()
|
|
157
|
-
|
|
158
|
-
queryClient.clear()
|
|
159
|
-
hydrationClient.clear()
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
test('should be able to provide default options for the hydrated queries', async () => {
|
|
163
|
-
const queryCache = new QueryCache()
|
|
164
|
-
const queryClient = createQueryClient({ queryCache })
|
|
165
|
-
await queryClient.prefetchQuery({
|
|
166
|
-
queryKey: ['string'],
|
|
167
|
-
queryFn: () => fetchData('string'),
|
|
168
|
-
})
|
|
169
|
-
const dehydrated = dehydrate(queryClient)
|
|
170
|
-
const stringified = JSON.stringify(dehydrated)
|
|
171
|
-
const parsed = JSON.parse(stringified)
|
|
172
|
-
const hydrationCache = new QueryCache()
|
|
173
|
-
const hydrationClient = createQueryClient({ queryCache: hydrationCache })
|
|
174
|
-
hydrate(hydrationClient, parsed, {
|
|
175
|
-
defaultOptions: { queries: { retry: 10 } },
|
|
176
|
-
})
|
|
177
|
-
expect(hydrationCache.find({ queryKey: ['string'] })?.options.retry).toBe(
|
|
178
|
-
10,
|
|
179
|
-
)
|
|
180
|
-
queryClient.clear()
|
|
181
|
-
hydrationClient.clear()
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
test('should respect query defaultOptions specified on the QueryClient', async () => {
|
|
185
|
-
const queryCache = new QueryCache()
|
|
186
|
-
const queryClient = createQueryClient({
|
|
187
|
-
queryCache,
|
|
188
|
-
defaultOptions: {
|
|
189
|
-
dehydrate: { shouldDehydrateQuery: () => true },
|
|
190
|
-
},
|
|
191
|
-
})
|
|
192
|
-
await queryClient.prefetchQuery({
|
|
193
|
-
queryKey: ['string'],
|
|
194
|
-
retry: 0,
|
|
195
|
-
queryFn: () => Promise.reject(new Error('error')),
|
|
196
|
-
})
|
|
197
|
-
const dehydrated = dehydrate(queryClient)
|
|
198
|
-
expect(dehydrated.queries.length).toBe(1)
|
|
199
|
-
expect(dehydrated.queries[0]?.state.error).toStrictEqual(new Error('error'))
|
|
200
|
-
const stringified = JSON.stringify(dehydrated)
|
|
201
|
-
const parsed = JSON.parse(stringified)
|
|
202
|
-
const hydrationCache = new QueryCache()
|
|
203
|
-
const hydrationClient = createQueryClient({
|
|
204
|
-
queryCache: hydrationCache,
|
|
205
|
-
defaultOptions: { hydrate: { queries: { retry: 10 } } },
|
|
206
|
-
})
|
|
207
|
-
hydrate(hydrationClient, parsed, {
|
|
208
|
-
defaultOptions: { queries: { gcTime: 10 } },
|
|
209
|
-
})
|
|
210
|
-
expect(hydrationCache.find({ queryKey: ['string'] })?.options.retry).toBe(
|
|
211
|
-
10,
|
|
212
|
-
)
|
|
213
|
-
expect(hydrationCache.find({ queryKey: ['string'] })?.options.gcTime).toBe(
|
|
214
|
-
10,
|
|
215
|
-
)
|
|
216
|
-
queryClient.clear()
|
|
217
|
-
hydrationClient.clear()
|
|
218
|
-
})
|
|
219
|
-
|
|
220
|
-
test('should respect mutation defaultOptions specified on the QueryClient', async () => {
|
|
221
|
-
const mutationCache = new MutationCache()
|
|
222
|
-
const queryClient = createQueryClient({
|
|
223
|
-
mutationCache,
|
|
224
|
-
defaultOptions: {
|
|
225
|
-
dehydrate: {
|
|
226
|
-
shouldDehydrateMutation: (mutation) => mutation.state.data === 'done',
|
|
227
|
-
},
|
|
228
|
-
},
|
|
229
|
-
})
|
|
230
|
-
await executeMutation(
|
|
231
|
-
queryClient,
|
|
232
|
-
{
|
|
233
|
-
mutationKey: ['string'],
|
|
234
|
-
mutationFn: () => Promise.resolve('done'),
|
|
235
|
-
},
|
|
236
|
-
undefined,
|
|
237
|
-
)
|
|
238
|
-
|
|
239
|
-
const dehydrated = dehydrate(queryClient)
|
|
240
|
-
expect(dehydrated.mutations.length).toBe(1)
|
|
241
|
-
expect(dehydrated.mutations[0]?.state.data).toBe('done')
|
|
242
|
-
const stringified = JSON.stringify(dehydrated)
|
|
243
|
-
const parsed = JSON.parse(stringified)
|
|
244
|
-
const hydrationCache = new MutationCache()
|
|
245
|
-
const hydrationClient = createQueryClient({
|
|
246
|
-
mutationCache: hydrationCache,
|
|
247
|
-
defaultOptions: { hydrate: { mutations: { retry: 10 } } },
|
|
248
|
-
})
|
|
249
|
-
hydrate(hydrationClient, parsed, {
|
|
250
|
-
defaultOptions: { mutations: { gcTime: 10 } },
|
|
251
|
-
})
|
|
252
|
-
expect(
|
|
253
|
-
hydrationCache.find({ mutationKey: ['string'] })?.options.retry,
|
|
254
|
-
).toBe(10)
|
|
255
|
-
expect(
|
|
256
|
-
hydrationCache.find({ mutationKey: ['string'] })?.options.gcTime,
|
|
257
|
-
).toBe(10)
|
|
258
|
-
queryClient.clear()
|
|
259
|
-
hydrationClient.clear()
|
|
260
|
-
})
|
|
261
|
-
|
|
262
|
-
test('should work with complex keys', async () => {
|
|
263
|
-
const queryCache = new QueryCache()
|
|
264
|
-
const queryClient = createQueryClient({ queryCache })
|
|
265
|
-
await queryClient.prefetchQuery({
|
|
266
|
-
queryKey: ['string', { key: ['string'], key2: 0 }],
|
|
267
|
-
queryFn: () => fetchData('string'),
|
|
268
|
-
})
|
|
269
|
-
const dehydrated = dehydrate(queryClient)
|
|
270
|
-
const stringified = JSON.stringify(dehydrated)
|
|
271
|
-
|
|
272
|
-
// ---
|
|
273
|
-
|
|
274
|
-
const parsed = JSON.parse(stringified)
|
|
275
|
-
const hydrationCache = new QueryCache()
|
|
276
|
-
const hydrationClient = createQueryClient({ queryCache: hydrationCache })
|
|
277
|
-
hydrate(hydrationClient, parsed)
|
|
278
|
-
expect(
|
|
279
|
-
hydrationCache.find({
|
|
280
|
-
queryKey: ['string', { key: ['string'], key2: 0 }],
|
|
281
|
-
})?.state.data,
|
|
282
|
-
).toBe('string')
|
|
283
|
-
|
|
284
|
-
const fetchDataAfterHydration =
|
|
285
|
-
vi.fn<(...args: Array<unknown>) => unknown>()
|
|
286
|
-
await hydrationClient.prefetchQuery({
|
|
287
|
-
queryKey: ['string', { key: ['string'], key2: 0 }],
|
|
288
|
-
queryFn: fetchDataAfterHydration,
|
|
289
|
-
staleTime: 100,
|
|
290
|
-
})
|
|
291
|
-
expect(fetchDataAfterHydration).toHaveBeenCalledTimes(0)
|
|
292
|
-
|
|
293
|
-
queryClient.clear()
|
|
294
|
-
hydrationClient.clear()
|
|
295
|
-
})
|
|
296
|
-
|
|
297
|
-
test('should only hydrate successful queries by default', async () => {
|
|
298
|
-
const consoleMock = vi.spyOn(console, 'error')
|
|
299
|
-
consoleMock.mockImplementation(() => undefined)
|
|
300
|
-
|
|
301
|
-
const queryCache = new QueryCache()
|
|
302
|
-
const queryClient = createQueryClient({ queryCache })
|
|
303
|
-
await queryClient.prefetchQuery({
|
|
304
|
-
queryKey: ['success'],
|
|
305
|
-
queryFn: () => fetchData('success'),
|
|
306
|
-
})
|
|
307
|
-
queryClient.prefetchQuery({
|
|
308
|
-
queryKey: ['loading'],
|
|
309
|
-
queryFn: () => fetchData('loading', 10000),
|
|
310
|
-
})
|
|
311
|
-
await queryClient.prefetchQuery({
|
|
312
|
-
queryKey: ['error'],
|
|
313
|
-
queryFn: () => {
|
|
314
|
-
throw new Error()
|
|
315
|
-
},
|
|
316
|
-
})
|
|
317
|
-
const dehydrated = dehydrate(queryClient)
|
|
318
|
-
const stringified = JSON.stringify(dehydrated)
|
|
319
|
-
|
|
320
|
-
// ---
|
|
321
|
-
|
|
322
|
-
const parsed = JSON.parse(stringified)
|
|
323
|
-
const hydrationCache = new QueryCache()
|
|
324
|
-
const hydrationClient = createQueryClient({ queryCache: hydrationCache })
|
|
325
|
-
hydrate(hydrationClient, parsed)
|
|
326
|
-
|
|
327
|
-
expect(hydrationCache.find({ queryKey: ['success'] })).toBeTruthy()
|
|
328
|
-
expect(hydrationCache.find({ queryKey: ['loading'] })).toBeFalsy()
|
|
329
|
-
expect(hydrationCache.find({ queryKey: ['error'] })).toBeFalsy()
|
|
330
|
-
|
|
331
|
-
queryClient.clear()
|
|
332
|
-
hydrationClient.clear()
|
|
333
|
-
consoleMock.mockRestore()
|
|
334
|
-
})
|
|
335
|
-
|
|
336
|
-
test('should filter queries via dehydrateQuery', async () => {
|
|
337
|
-
const queryCache = new QueryCache()
|
|
338
|
-
const queryClient = createQueryClient({ queryCache })
|
|
339
|
-
await queryClient.prefetchQuery({
|
|
340
|
-
queryKey: ['string'],
|
|
341
|
-
queryFn: () => fetchData('string'),
|
|
342
|
-
})
|
|
343
|
-
await queryClient.prefetchQuery({
|
|
344
|
-
queryKey: ['number'],
|
|
345
|
-
queryFn: () => fetchData(1),
|
|
346
|
-
})
|
|
347
|
-
const dehydrated = dehydrate(queryClient, {
|
|
348
|
-
shouldDehydrateQuery: (query) => query.queryKey[0] !== 'string',
|
|
349
|
-
})
|
|
350
|
-
|
|
351
|
-
// This is testing implementation details that can change and are not
|
|
352
|
-
// part of the public API, but is important for keeping the payload small
|
|
353
|
-
const dehydratedQuery = dehydrated.queries.find(
|
|
354
|
-
(query) => query.queryKey[0] === 'string',
|
|
355
|
-
)
|
|
356
|
-
expect(dehydratedQuery).toBeUndefined()
|
|
357
|
-
|
|
358
|
-
const stringified = JSON.stringify(dehydrated)
|
|
359
|
-
|
|
360
|
-
// ---
|
|
361
|
-
|
|
362
|
-
const parsed = JSON.parse(stringified)
|
|
363
|
-
const hydrationCache = new QueryCache()
|
|
364
|
-
const hydrationClient = createQueryClient({ queryCache: hydrationCache })
|
|
365
|
-
hydrate(hydrationClient, parsed)
|
|
366
|
-
expect(hydrationCache.find({ queryKey: ['string'] })).toBeUndefined()
|
|
367
|
-
expect(hydrationCache.find({ queryKey: ['number'] })?.state.data).toBe(1)
|
|
368
|
-
|
|
369
|
-
queryClient.clear()
|
|
370
|
-
hydrationClient.clear()
|
|
371
|
-
})
|
|
372
|
-
|
|
373
|
-
test('should not overwrite query in cache if hydrated query is older', async () => {
|
|
374
|
-
const queryCache = new QueryCache()
|
|
375
|
-
const queryClient = createQueryClient({ queryCache })
|
|
376
|
-
await queryClient.prefetchQuery({
|
|
377
|
-
queryKey: ['string'],
|
|
378
|
-
queryFn: () => fetchData('string-older', 5),
|
|
379
|
-
})
|
|
380
|
-
const dehydrated = dehydrate(queryClient)
|
|
381
|
-
const stringified = JSON.stringify(dehydrated)
|
|
382
|
-
|
|
383
|
-
// ---
|
|
384
|
-
|
|
385
|
-
const parsed = JSON.parse(stringified)
|
|
386
|
-
const hydrationCache = new QueryCache()
|
|
387
|
-
const hydrationClient = createQueryClient({ queryCache: hydrationCache })
|
|
388
|
-
await hydrationClient.prefetchQuery({
|
|
389
|
-
queryKey: ['string'],
|
|
390
|
-
queryFn: () => fetchData('string-newer', 5),
|
|
391
|
-
})
|
|
392
|
-
|
|
393
|
-
hydrate(hydrationClient, parsed)
|
|
394
|
-
expect(hydrationCache.find({ queryKey: ['string'] })?.state.data).toBe(
|
|
395
|
-
'string-newer',
|
|
396
|
-
)
|
|
397
|
-
|
|
398
|
-
queryClient.clear()
|
|
399
|
-
hydrationClient.clear()
|
|
400
|
-
})
|
|
401
|
-
|
|
402
|
-
test('should overwrite query in cache if hydrated query is newer', async () => {
|
|
403
|
-
const hydrationCache = new QueryCache()
|
|
404
|
-
const hydrationClient = createQueryClient({ queryCache: hydrationCache })
|
|
405
|
-
await hydrationClient.prefetchQuery({
|
|
406
|
-
queryKey: ['string'],
|
|
407
|
-
queryFn: () => fetchData('string-older', 5),
|
|
408
|
-
})
|
|
409
|
-
|
|
410
|
-
// ---
|
|
411
|
-
|
|
412
|
-
const queryCache = new QueryCache()
|
|
413
|
-
const queryClient = createQueryClient({ queryCache })
|
|
414
|
-
await queryClient.prefetchQuery({
|
|
415
|
-
queryKey: ['string'],
|
|
416
|
-
queryFn: () => fetchData('string-newer', 5),
|
|
417
|
-
})
|
|
418
|
-
const dehydrated = dehydrate(queryClient)
|
|
419
|
-
const stringified = JSON.stringify(dehydrated)
|
|
420
|
-
|
|
421
|
-
// ---
|
|
422
|
-
|
|
423
|
-
const parsed = JSON.parse(stringified)
|
|
424
|
-
hydrate(hydrationClient, parsed)
|
|
425
|
-
expect(hydrationCache.find({ queryKey: ['string'] })?.state.data).toBe(
|
|
426
|
-
'string-newer',
|
|
427
|
-
)
|
|
428
|
-
|
|
429
|
-
queryClient.clear()
|
|
430
|
-
hydrationClient.clear()
|
|
431
|
-
})
|
|
432
|
-
|
|
433
|
-
test('should be able to dehydrate mutations and continue on hydration', async () => {
|
|
434
|
-
const consoleMock = vi.spyOn(console, 'error')
|
|
435
|
-
consoleMock.mockImplementation(() => undefined)
|
|
436
|
-
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
437
|
-
|
|
438
|
-
const serverAddTodo = vi
|
|
439
|
-
.fn()
|
|
440
|
-
.mockImplementation(() => Promise.reject(new Error('offline')))
|
|
441
|
-
const serverOnMutate = vi.fn().mockImplementation((variables) => {
|
|
442
|
-
const optimisticTodo = { id: 1, text: variables.text }
|
|
443
|
-
return { optimisticTodo }
|
|
444
|
-
})
|
|
445
|
-
const serverOnSuccess = vi.fn()
|
|
446
|
-
|
|
447
|
-
const serverClient = createQueryClient()
|
|
448
|
-
|
|
449
|
-
serverClient.setMutationDefaults(['addTodo'], {
|
|
450
|
-
mutationFn: serverAddTodo,
|
|
451
|
-
onMutate: serverOnMutate,
|
|
452
|
-
onSuccess: serverOnSuccess,
|
|
453
|
-
retry: 3,
|
|
454
|
-
retryDelay: 10,
|
|
455
|
-
})
|
|
456
|
-
|
|
457
|
-
executeMutation(
|
|
458
|
-
serverClient,
|
|
459
|
-
{
|
|
460
|
-
mutationKey: ['addTodo'],
|
|
461
|
-
},
|
|
462
|
-
{ text: 'text' },
|
|
463
|
-
).catch(() => undefined)
|
|
464
|
-
|
|
465
|
-
await sleep(50)
|
|
466
|
-
|
|
467
|
-
const dehydrated = dehydrate(serverClient)
|
|
468
|
-
const stringified = JSON.stringify(dehydrated)
|
|
469
|
-
|
|
470
|
-
serverClient.clear()
|
|
471
|
-
|
|
472
|
-
// ---
|
|
473
|
-
|
|
474
|
-
onlineMock.mockReturnValue(true)
|
|
475
|
-
|
|
476
|
-
const parsed = JSON.parse(stringified)
|
|
477
|
-
const client = createQueryClient()
|
|
478
|
-
|
|
479
|
-
const clientAddTodo = vi.fn().mockImplementation((variables) => {
|
|
480
|
-
return { id: 2, text: variables.text }
|
|
481
|
-
})
|
|
482
|
-
const clientOnMutate = vi.fn().mockImplementation((variables) => {
|
|
483
|
-
const optimisticTodo = { id: 1, text: variables.text }
|
|
484
|
-
return { optimisticTodo }
|
|
485
|
-
})
|
|
486
|
-
const clientOnSuccess = vi.fn()
|
|
487
|
-
|
|
488
|
-
client.setMutationDefaults(['addTodo'], {
|
|
489
|
-
mutationFn: clientAddTodo,
|
|
490
|
-
onMutate: clientOnMutate,
|
|
491
|
-
onSuccess: clientOnSuccess,
|
|
492
|
-
retry: 3,
|
|
493
|
-
retryDelay: 10,
|
|
494
|
-
})
|
|
495
|
-
|
|
496
|
-
hydrate(client, parsed)
|
|
497
|
-
|
|
498
|
-
await client.resumePausedMutations()
|
|
499
|
-
|
|
500
|
-
expect(clientAddTodo).toHaveBeenCalledTimes(1)
|
|
501
|
-
expect(clientOnMutate).not.toHaveBeenCalled()
|
|
502
|
-
expect(clientOnSuccess).toHaveBeenCalledTimes(1)
|
|
503
|
-
expect(clientOnSuccess).toHaveBeenCalledWith(
|
|
504
|
-
{ id: 2, text: 'text' },
|
|
505
|
-
{ text: 'text' },
|
|
506
|
-
{ optimisticTodo: { id: 1, text: 'text' } },
|
|
507
|
-
)
|
|
508
|
-
|
|
509
|
-
client.clear()
|
|
510
|
-
consoleMock.mockRestore()
|
|
511
|
-
onlineMock.mockRestore()
|
|
512
|
-
})
|
|
513
|
-
|
|
514
|
-
test('should not dehydrate mutations if dehydrateMutations is set to false', async () => {
|
|
515
|
-
const consoleMock = vi.spyOn(console, 'error')
|
|
516
|
-
consoleMock.mockImplementation(() => undefined)
|
|
517
|
-
|
|
518
|
-
const serverAddTodo = vi
|
|
519
|
-
.fn()
|
|
520
|
-
.mockImplementation(() => Promise.reject(new Error('offline')))
|
|
521
|
-
|
|
522
|
-
const queryClient = createQueryClient()
|
|
523
|
-
|
|
524
|
-
queryClient.setMutationDefaults(['addTodo'], {
|
|
525
|
-
mutationFn: serverAddTodo,
|
|
526
|
-
retry: false,
|
|
527
|
-
})
|
|
528
|
-
|
|
529
|
-
executeMutation(
|
|
530
|
-
queryClient,
|
|
531
|
-
{
|
|
532
|
-
mutationKey: ['addTodo'],
|
|
533
|
-
},
|
|
534
|
-
{ text: 'text' },
|
|
535
|
-
).catch(() => undefined)
|
|
536
|
-
|
|
537
|
-
await sleep(1)
|
|
538
|
-
const dehydrated = dehydrate(queryClient, {
|
|
539
|
-
shouldDehydrateMutation: () => false,
|
|
540
|
-
})
|
|
541
|
-
|
|
542
|
-
expect(dehydrated.mutations.length).toBe(0)
|
|
543
|
-
|
|
544
|
-
queryClient.clear()
|
|
545
|
-
consoleMock.mockRestore()
|
|
546
|
-
})
|
|
547
|
-
|
|
548
|
-
test('should not dehydrate mutation if mutation state is set to pause', async () => {
|
|
549
|
-
const consoleMock = vi.spyOn(console, 'error')
|
|
550
|
-
consoleMock.mockImplementation(() => undefined)
|
|
551
|
-
|
|
552
|
-
const serverAddTodo = vi
|
|
553
|
-
.fn()
|
|
554
|
-
.mockImplementation(() => Promise.reject(new Error('offline')))
|
|
555
|
-
|
|
556
|
-
const queryClient = createQueryClient()
|
|
557
|
-
|
|
558
|
-
queryClient.setMutationDefaults(['addTodo'], {
|
|
559
|
-
mutationFn: serverAddTodo,
|
|
560
|
-
retry: 1,
|
|
561
|
-
retryDelay: 20,
|
|
562
|
-
})
|
|
563
|
-
|
|
564
|
-
executeMutation(
|
|
565
|
-
queryClient,
|
|
566
|
-
{
|
|
567
|
-
mutationKey: ['addTodo'],
|
|
568
|
-
},
|
|
569
|
-
{ text: 'text' },
|
|
570
|
-
).catch(() => undefined)
|
|
571
|
-
|
|
572
|
-
// Dehydrate mutation between retries
|
|
573
|
-
await sleep(1)
|
|
574
|
-
const dehydrated = dehydrate(queryClient)
|
|
575
|
-
|
|
576
|
-
expect(dehydrated.mutations.length).toBe(0)
|
|
577
|
-
|
|
578
|
-
await sleep(30)
|
|
579
|
-
queryClient.clear()
|
|
580
|
-
consoleMock.mockRestore()
|
|
581
|
-
})
|
|
582
|
-
|
|
583
|
-
test('should not hydrate if the hydratedState is null or is not an object', async () => {
|
|
584
|
-
const queryCache = new QueryCache()
|
|
585
|
-
const queryClient = createQueryClient({ queryCache })
|
|
586
|
-
|
|
587
|
-
expect(() => hydrate(queryClient, null)).not.toThrow()
|
|
588
|
-
expect(() => hydrate(queryClient, 'invalid')).not.toThrow()
|
|
589
|
-
|
|
590
|
-
queryClient.clear()
|
|
591
|
-
})
|
|
592
|
-
|
|
593
|
-
test('should support hydratedState with undefined queries and mutations', async () => {
|
|
594
|
-
const queryCache = new QueryCache()
|
|
595
|
-
const queryClient = createQueryClient({ queryCache })
|
|
596
|
-
|
|
597
|
-
expect(() => hydrate(queryClient, {})).not.toThrow()
|
|
598
|
-
expect(() => hydrate(queryClient, {})).not.toThrow()
|
|
599
|
-
|
|
600
|
-
queryClient.clear()
|
|
601
|
-
})
|
|
602
|
-
|
|
603
|
-
test('should set the fetchStatus to idle when creating a query with dehydrate', async () => {
|
|
604
|
-
const queryCache = new QueryCache()
|
|
605
|
-
const queryClient = createQueryClient({ queryCache })
|
|
606
|
-
|
|
607
|
-
let isInitialFetch = true
|
|
608
|
-
let resolvePromise: (value: unknown) => void = () => undefined
|
|
609
|
-
|
|
610
|
-
const customFetchData = () => {
|
|
611
|
-
const promise = new Promise((resolve) => {
|
|
612
|
-
resolvePromise = resolve
|
|
613
|
-
})
|
|
614
|
-
// Resolve the promise in initial fetch
|
|
615
|
-
// because we are awaiting the query first time
|
|
616
|
-
if (isInitialFetch) {
|
|
617
|
-
resolvePromise('string')
|
|
618
|
-
}
|
|
619
|
-
isInitialFetch = false
|
|
620
|
-
return promise
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
await queryClient.prefetchQuery({
|
|
624
|
-
queryKey: ['string'],
|
|
625
|
-
queryFn: () => customFetchData(),
|
|
626
|
-
})
|
|
627
|
-
|
|
628
|
-
queryClient.refetchQueries({ queryKey: ['string'] })
|
|
629
|
-
|
|
630
|
-
const dehydrated = dehydrate(queryClient)
|
|
631
|
-
resolvePromise('string')
|
|
632
|
-
expect(
|
|
633
|
-
dehydrated.queries.find((q) => q.queryHash === '["string"]')?.state
|
|
634
|
-
.fetchStatus,
|
|
635
|
-
).toBe('fetching')
|
|
636
|
-
const stringified = JSON.stringify(dehydrated)
|
|
637
|
-
|
|
638
|
-
// ---
|
|
639
|
-
const parsed = JSON.parse(stringified)
|
|
640
|
-
const hydrationCache = new QueryCache()
|
|
641
|
-
const hydrationClient = createQueryClient({ queryCache: hydrationCache })
|
|
642
|
-
hydrate(hydrationClient, parsed)
|
|
643
|
-
expect(
|
|
644
|
-
hydrationCache.find({ queryKey: ['string'] })?.state.fetchStatus,
|
|
645
|
-
).toBe('idle')
|
|
646
|
-
})
|
|
647
|
-
|
|
648
|
-
test('should dehydrate and hydrate meta for queries', async () => {
|
|
649
|
-
const queryCache = new QueryCache()
|
|
650
|
-
const queryClient = createQueryClient({ queryCache })
|
|
651
|
-
await queryClient.prefetchQuery({
|
|
652
|
-
queryKey: ['meta'],
|
|
653
|
-
queryFn: () => Promise.resolve('meta'),
|
|
654
|
-
meta: {
|
|
655
|
-
some: 'meta',
|
|
656
|
-
},
|
|
657
|
-
})
|
|
658
|
-
await queryClient.prefetchQuery({
|
|
659
|
-
queryKey: ['no-meta'],
|
|
660
|
-
queryFn: () => Promise.resolve('no-meta'),
|
|
661
|
-
})
|
|
662
|
-
|
|
663
|
-
const dehydrated = dehydrate(queryClient)
|
|
664
|
-
|
|
665
|
-
expect(
|
|
666
|
-
dehydrated.queries.find((q) => q.queryHash === '["meta"]')?.meta,
|
|
667
|
-
).toEqual({
|
|
668
|
-
some: 'meta',
|
|
669
|
-
})
|
|
670
|
-
|
|
671
|
-
expect(
|
|
672
|
-
dehydrated.queries.find((q) => q.queryHash === '["no-meta"]')?.meta,
|
|
673
|
-
).toEqual(undefined)
|
|
674
|
-
|
|
675
|
-
expect(
|
|
676
|
-
Object.keys(
|
|
677
|
-
dehydrated.queries.find((q) => q.queryHash === '["no-meta"]')!,
|
|
678
|
-
),
|
|
679
|
-
).not.toEqual(expect.arrayContaining(['meta']))
|
|
680
|
-
|
|
681
|
-
const stringified = JSON.stringify(dehydrated)
|
|
682
|
-
|
|
683
|
-
// ---
|
|
684
|
-
|
|
685
|
-
const parsed = JSON.parse(stringified)
|
|
686
|
-
const hydrationCache = new QueryCache()
|
|
687
|
-
const hydrationClient = createQueryClient({
|
|
688
|
-
queryCache: hydrationCache,
|
|
689
|
-
})
|
|
690
|
-
hydrate(hydrationClient, parsed)
|
|
691
|
-
expect(hydrationCache.find({ queryKey: ['meta'] })?.meta).toEqual({
|
|
692
|
-
some: 'meta',
|
|
693
|
-
})
|
|
694
|
-
expect(hydrationCache.find({ queryKey: ['no-meta'] })?.meta).toEqual(
|
|
695
|
-
undefined,
|
|
696
|
-
)
|
|
697
|
-
})
|
|
698
|
-
|
|
699
|
-
test('should dehydrate and hydrate meta for mutations', async () => {
|
|
700
|
-
const mutationCache = new MutationCache()
|
|
701
|
-
const queryClient = createQueryClient({ mutationCache })
|
|
702
|
-
|
|
703
|
-
await executeMutation(
|
|
704
|
-
queryClient,
|
|
705
|
-
{
|
|
706
|
-
mutationKey: ['meta'],
|
|
707
|
-
mutationFn: () => Promise.resolve('meta'),
|
|
708
|
-
meta: {
|
|
709
|
-
some: 'meta',
|
|
710
|
-
},
|
|
711
|
-
},
|
|
712
|
-
undefined,
|
|
713
|
-
)
|
|
714
|
-
|
|
715
|
-
await executeMutation(
|
|
716
|
-
queryClient,
|
|
717
|
-
{
|
|
718
|
-
mutationKey: ['no-meta'],
|
|
719
|
-
mutationFn: () => Promise.resolve('no-meta'),
|
|
720
|
-
},
|
|
721
|
-
undefined,
|
|
722
|
-
)
|
|
723
|
-
|
|
724
|
-
const dehydrated = dehydrate(queryClient, {
|
|
725
|
-
shouldDehydrateMutation: () => true,
|
|
726
|
-
})
|
|
727
|
-
|
|
728
|
-
expect(Object.keys(dehydrated.mutations[0]!)).toEqual(
|
|
729
|
-
expect.arrayContaining(['meta']),
|
|
730
|
-
)
|
|
731
|
-
expect(dehydrated.mutations[0]?.meta).toEqual({
|
|
732
|
-
some: 'meta',
|
|
733
|
-
})
|
|
734
|
-
|
|
735
|
-
expect(Object.keys(dehydrated.mutations[1]!)).not.toEqual(
|
|
736
|
-
expect.arrayContaining(['meta']),
|
|
737
|
-
)
|
|
738
|
-
expect(dehydrated.mutations[1]?.meta).toEqual(undefined)
|
|
739
|
-
|
|
740
|
-
const stringified = JSON.stringify(dehydrated)
|
|
741
|
-
|
|
742
|
-
// ---
|
|
743
|
-
|
|
744
|
-
const parsed = JSON.parse(stringified)
|
|
745
|
-
const hydrationCache = new MutationCache()
|
|
746
|
-
const hydrationClient = createQueryClient({
|
|
747
|
-
mutationCache: hydrationCache,
|
|
748
|
-
})
|
|
749
|
-
hydrate(hydrationClient, parsed)
|
|
750
|
-
expect(hydrationCache.find({ mutationKey: ['meta'] })?.meta).toEqual({
|
|
751
|
-
some: 'meta',
|
|
752
|
-
})
|
|
753
|
-
expect(hydrationCache.find({ mutationKey: ['no-meta'] })?.meta).toEqual(
|
|
754
|
-
undefined,
|
|
755
|
-
)
|
|
756
|
-
})
|
|
757
|
-
|
|
758
|
-
test('should not change fetchStatus when updating a query with dehydrate', async () => {
|
|
759
|
-
const queryClient = createQueryClient()
|
|
760
|
-
|
|
761
|
-
const options = {
|
|
762
|
-
queryKey: ['string'],
|
|
763
|
-
queryFn: async () => {
|
|
764
|
-
await sleep(10)
|
|
765
|
-
return 'string'
|
|
766
|
-
},
|
|
767
|
-
} as const
|
|
768
|
-
|
|
769
|
-
await queryClient.prefetchQuery(options)
|
|
770
|
-
|
|
771
|
-
const dehydrated = dehydrate(queryClient)
|
|
772
|
-
expect(
|
|
773
|
-
dehydrated.queries.find((q) => q.queryHash === '["string"]')?.state
|
|
774
|
-
.fetchStatus,
|
|
775
|
-
).toBe('idle')
|
|
776
|
-
const stringified = JSON.stringify(dehydrated)
|
|
777
|
-
|
|
778
|
-
// ---
|
|
779
|
-
const parsed = JSON.parse(stringified)
|
|
780
|
-
const hydrationCache = new QueryCache()
|
|
781
|
-
const hydrationClient = createQueryClient({ queryCache: hydrationCache })
|
|
782
|
-
|
|
783
|
-
const promise = hydrationClient.prefetchQuery(options)
|
|
784
|
-
hydrate(hydrationClient, parsed)
|
|
785
|
-
expect(
|
|
786
|
-
hydrationCache.find({ queryKey: ['string'] })?.state.fetchStatus,
|
|
787
|
-
).toBe('fetching')
|
|
788
|
-
await promise
|
|
789
|
-
expect(
|
|
790
|
-
hydrationCache.find({ queryKey: ['string'] })?.state.fetchStatus,
|
|
791
|
-
).toBe('idle')
|
|
792
|
-
})
|
|
793
|
-
|
|
794
|
-
test('should dehydrate and hydrate mutation scopes', async () => {
|
|
795
|
-
const queryClient = createQueryClient()
|
|
796
|
-
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
797
|
-
|
|
798
|
-
void executeMutation(
|
|
799
|
-
queryClient,
|
|
800
|
-
{
|
|
801
|
-
mutationKey: ['mutation'],
|
|
802
|
-
mutationFn: async () => {
|
|
803
|
-
return 'mutation'
|
|
804
|
-
},
|
|
805
|
-
scope: {
|
|
806
|
-
id: 'scope',
|
|
807
|
-
},
|
|
808
|
-
},
|
|
809
|
-
'vars',
|
|
810
|
-
)
|
|
811
|
-
|
|
812
|
-
const dehydrated = dehydrate(queryClient)
|
|
813
|
-
expect(dehydrated.mutations[0]?.scope?.id).toBe('scope')
|
|
814
|
-
const stringified = JSON.stringify(dehydrated)
|
|
815
|
-
|
|
816
|
-
// ---
|
|
817
|
-
const parsed = JSON.parse(stringified)
|
|
818
|
-
const hydrationCache = new MutationCache()
|
|
819
|
-
const hydrationClient = createQueryClient({ mutationCache: hydrationCache })
|
|
820
|
-
|
|
821
|
-
hydrate(hydrationClient, parsed)
|
|
822
|
-
|
|
823
|
-
expect(dehydrated.mutations[0]?.scope?.id).toBe('scope')
|
|
824
|
-
|
|
825
|
-
onlineMock.mockRestore()
|
|
826
|
-
})
|
|
827
|
-
|
|
828
|
-
test('should dehydrate promises for pending queries', async () => {
|
|
829
|
-
const queryCache = new QueryCache()
|
|
830
|
-
const queryClient = createQueryClient({
|
|
831
|
-
queryCache,
|
|
832
|
-
defaultOptions: { dehydrate: { shouldDehydrateQuery: () => true } },
|
|
833
|
-
})
|
|
834
|
-
await queryClient.prefetchQuery({
|
|
835
|
-
queryKey: ['success'],
|
|
836
|
-
queryFn: () => fetchData('success'),
|
|
837
|
-
})
|
|
838
|
-
|
|
839
|
-
const promise = queryClient.prefetchQuery({
|
|
840
|
-
queryKey: ['pending'],
|
|
841
|
-
queryFn: () => fetchData('pending', 10),
|
|
842
|
-
})
|
|
843
|
-
const dehydrated = dehydrate(queryClient)
|
|
844
|
-
|
|
845
|
-
expect(dehydrated.queries[0]?.promise).toBeUndefined()
|
|
846
|
-
expect(dehydrated.queries[1]?.promise).toBeInstanceOf(Promise)
|
|
847
|
-
|
|
848
|
-
await promise
|
|
849
|
-
queryClient.clear()
|
|
850
|
-
})
|
|
851
|
-
|
|
852
|
-
test('should hydrate promises even without observers', async () => {
|
|
853
|
-
const queryCache = new QueryCache()
|
|
854
|
-
const queryClient = createQueryClient({
|
|
855
|
-
queryCache,
|
|
856
|
-
defaultOptions: { dehydrate: { shouldDehydrateQuery: () => true } },
|
|
857
|
-
})
|
|
858
|
-
await queryClient.prefetchQuery({
|
|
859
|
-
queryKey: ['success'],
|
|
860
|
-
queryFn: () => fetchData('success'),
|
|
861
|
-
})
|
|
862
|
-
|
|
863
|
-
void queryClient.prefetchQuery({
|
|
864
|
-
queryKey: ['pending'],
|
|
865
|
-
queryFn: () => fetchData('pending', 20),
|
|
866
|
-
})
|
|
867
|
-
const dehydrated = dehydrate(queryClient)
|
|
868
|
-
// no stringify/parse here because promises can't be serialized to json
|
|
869
|
-
// but nextJs still can do it
|
|
870
|
-
|
|
871
|
-
const hydrationCache = new QueryCache()
|
|
872
|
-
const hydrationClient = createQueryClient({
|
|
873
|
-
queryCache: hydrationCache,
|
|
874
|
-
})
|
|
875
|
-
|
|
876
|
-
hydrate(hydrationClient, dehydrated)
|
|
877
|
-
|
|
878
|
-
expect(hydrationCache.find({ queryKey: ['success'] })?.state.data).toBe(
|
|
879
|
-
'success',
|
|
880
|
-
)
|
|
881
|
-
|
|
882
|
-
expect(hydrationCache.find({ queryKey: ['pending'] })?.state).toMatchObject(
|
|
883
|
-
{
|
|
884
|
-
data: undefined,
|
|
885
|
-
dataUpdateCount: 0,
|
|
886
|
-
dataUpdatedAt: 0,
|
|
887
|
-
error: null,
|
|
888
|
-
errorUpdateCount: 0,
|
|
889
|
-
errorUpdatedAt: 0,
|
|
890
|
-
fetchFailureCount: 0,
|
|
891
|
-
fetchFailureReason: null,
|
|
892
|
-
fetchMeta: null,
|
|
893
|
-
fetchStatus: 'fetching',
|
|
894
|
-
isInvalidated: false,
|
|
895
|
-
status: 'pending',
|
|
896
|
-
},
|
|
897
|
-
)
|
|
898
|
-
|
|
899
|
-
await waitFor(() =>
|
|
900
|
-
expect(
|
|
901
|
-
hydrationCache.find({ queryKey: ['pending'] })?.state,
|
|
902
|
-
).toMatchObject({
|
|
903
|
-
data: 'pending',
|
|
904
|
-
dataUpdateCount: 1,
|
|
905
|
-
dataUpdatedAt: expect.any(Number),
|
|
906
|
-
error: null,
|
|
907
|
-
errorUpdateCount: 0,
|
|
908
|
-
errorUpdatedAt: 0,
|
|
909
|
-
fetchFailureCount: 0,
|
|
910
|
-
fetchFailureReason: null,
|
|
911
|
-
fetchMeta: null,
|
|
912
|
-
fetchStatus: 'idle',
|
|
913
|
-
isInvalidated: false,
|
|
914
|
-
status: 'success',
|
|
915
|
-
}),
|
|
916
|
-
)
|
|
917
|
-
})
|
|
918
|
-
|
|
919
|
-
test('should transform promise result', async () => {
|
|
920
|
-
const queryClient = createQueryClient({
|
|
921
|
-
defaultOptions: {
|
|
922
|
-
dehydrate: {
|
|
923
|
-
shouldDehydrateQuery: () => true,
|
|
924
|
-
serializeData: (data) => data.toISOString(),
|
|
925
|
-
},
|
|
926
|
-
},
|
|
927
|
-
})
|
|
928
|
-
|
|
929
|
-
const promise = queryClient.prefetchQuery({
|
|
930
|
-
queryKey: ['transformedStringToDate'],
|
|
931
|
-
queryFn: () => fetchDate('2024-01-01T00:00:00.000Z', 20),
|
|
932
|
-
})
|
|
933
|
-
const dehydrated = dehydrate(queryClient)
|
|
934
|
-
expect(dehydrated.queries[0]?.promise).toBeInstanceOf(Promise)
|
|
935
|
-
|
|
936
|
-
const hydrationClient = createQueryClient({
|
|
937
|
-
defaultOptions: {
|
|
938
|
-
hydrate: {
|
|
939
|
-
deserializeData: (data) => new Date(data),
|
|
940
|
-
},
|
|
941
|
-
},
|
|
942
|
-
})
|
|
943
|
-
|
|
944
|
-
hydrate(hydrationClient, dehydrated)
|
|
945
|
-
await promise
|
|
946
|
-
await waitFor(() =>
|
|
947
|
-
expect(
|
|
948
|
-
hydrationClient.getQueryData(['transformedStringToDate']),
|
|
949
|
-
).toBeInstanceOf(Date),
|
|
950
|
-
)
|
|
951
|
-
|
|
952
|
-
queryClient.clear()
|
|
953
|
-
})
|
|
954
|
-
|
|
955
|
-
test('should transform query data if promise is already resolved', async () => {
|
|
956
|
-
const queryClient = createQueryClient({
|
|
957
|
-
defaultOptions: {
|
|
958
|
-
dehydrate: {
|
|
959
|
-
shouldDehydrateQuery: () => true,
|
|
960
|
-
serializeData: (data) => data.toISOString(),
|
|
961
|
-
},
|
|
962
|
-
},
|
|
963
|
-
})
|
|
964
|
-
|
|
965
|
-
const promise = queryClient.prefetchQuery({
|
|
966
|
-
queryKey: ['transformedStringToDate'],
|
|
967
|
-
queryFn: () => fetchDate('2024-01-01T00:00:00.000Z', 0),
|
|
968
|
-
})
|
|
969
|
-
await sleep(20)
|
|
970
|
-
const dehydrated = dehydrate(queryClient)
|
|
971
|
-
|
|
972
|
-
const hydrationClient = createQueryClient({
|
|
973
|
-
defaultOptions: {
|
|
974
|
-
hydrate: {
|
|
975
|
-
deserializeData: (data) => new Date(data),
|
|
976
|
-
},
|
|
977
|
-
},
|
|
978
|
-
})
|
|
979
|
-
|
|
980
|
-
hydrate(hydrationClient, dehydrated)
|
|
981
|
-
await promise
|
|
982
|
-
await waitFor(() =>
|
|
983
|
-
expect(
|
|
984
|
-
hydrationClient.getQueryData(['transformedStringToDate']),
|
|
985
|
-
).toBeInstanceOf(Date),
|
|
986
|
-
)
|
|
987
|
-
|
|
988
|
-
queryClient.clear()
|
|
989
|
-
})
|
|
990
|
-
|
|
991
|
-
test('should overwrite query in cache if hydrated query is newer (with transformation)', async () => {
|
|
992
|
-
const hydrationClient = createQueryClient({
|
|
993
|
-
defaultOptions: {
|
|
994
|
-
hydrate: {
|
|
995
|
-
deserializeData: (data) => new Date(data),
|
|
996
|
-
},
|
|
997
|
-
},
|
|
998
|
-
})
|
|
999
|
-
await hydrationClient.prefetchQuery({
|
|
1000
|
-
queryKey: ['date'],
|
|
1001
|
-
queryFn: () => fetchDate('2024-01-01T00:00:00.000Z', 5),
|
|
1002
|
-
})
|
|
1003
|
-
|
|
1004
|
-
// ---
|
|
1005
|
-
|
|
1006
|
-
const queryClient = createQueryClient({
|
|
1007
|
-
defaultOptions: {
|
|
1008
|
-
dehydrate: {
|
|
1009
|
-
shouldDehydrateQuery: () => true,
|
|
1010
|
-
serializeData: (data) => data.toISOString(),
|
|
1011
|
-
},
|
|
1012
|
-
},
|
|
1013
|
-
})
|
|
1014
|
-
await queryClient.prefetchQuery({
|
|
1015
|
-
queryKey: ['date'],
|
|
1016
|
-
queryFn: () => fetchDate('2024-01-02T00:00:00.000Z', 10),
|
|
1017
|
-
})
|
|
1018
|
-
const dehydrated = dehydrate(queryClient)
|
|
1019
|
-
|
|
1020
|
-
// ---
|
|
1021
|
-
|
|
1022
|
-
hydrate(hydrationClient, dehydrated)
|
|
1023
|
-
|
|
1024
|
-
expect(hydrationClient.getQueryData(['date'])).toStrictEqual(
|
|
1025
|
-
new Date('2024-01-02T00:00:00.000Z'),
|
|
1026
|
-
)
|
|
1027
|
-
|
|
1028
|
-
queryClient.clear()
|
|
1029
|
-
hydrationClient.clear()
|
|
1030
|
-
})
|
|
1031
|
-
|
|
1032
|
-
test('should overwrite query in cache if hydrated query is newer (with promise)', async () => {
|
|
1033
|
-
// --- server ---
|
|
1034
|
-
|
|
1035
|
-
const serverQueryClient = createQueryClient({
|
|
1036
|
-
defaultOptions: {
|
|
1037
|
-
dehydrate: {
|
|
1038
|
-
shouldDehydrateQuery: () => true,
|
|
1039
|
-
},
|
|
1040
|
-
},
|
|
1041
|
-
})
|
|
1042
|
-
|
|
1043
|
-
const promise = serverQueryClient.prefetchQuery({
|
|
1044
|
-
queryKey: ['data'],
|
|
1045
|
-
queryFn: async () => {
|
|
1046
|
-
await sleep(10)
|
|
1047
|
-
return 'server data'
|
|
1048
|
-
},
|
|
1049
|
-
})
|
|
1050
|
-
|
|
1051
|
-
const dehydrated = dehydrate(serverQueryClient)
|
|
1052
|
-
|
|
1053
|
-
// --- client ---
|
|
1054
|
-
|
|
1055
|
-
const clientQueryClient = createQueryClient()
|
|
1056
|
-
|
|
1057
|
-
clientQueryClient.setQueryData(['data'], 'old data', { updatedAt: 10 })
|
|
1058
|
-
|
|
1059
|
-
hydrate(clientQueryClient, dehydrated)
|
|
1060
|
-
|
|
1061
|
-
await promise
|
|
1062
|
-
await waitFor(() =>
|
|
1063
|
-
expect(clientQueryClient.getQueryData(['data'])).toBe('server data'),
|
|
1064
|
-
)
|
|
1065
|
-
|
|
1066
|
-
clientQueryClient.clear()
|
|
1067
|
-
serverQueryClient.clear()
|
|
1068
|
-
})
|
|
1069
|
-
})
|