@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.
Files changed (30) hide show
  1. package/build/legacy/queriesObserver.cjs +8 -0
  2. package/build/legacy/queriesObserver.cjs.map +1 -1
  3. package/build/legacy/queriesObserver.js +8 -0
  4. package/build/legacy/queriesObserver.js.map +1 -1
  5. package/build/modern/queriesObserver.cjs +8 -0
  6. package/build/modern/queriesObserver.cjs.map +1 -1
  7. package/build/modern/queriesObserver.js +8 -0
  8. package/build/modern/queriesObserver.js.map +1 -1
  9. package/package.json +3 -2
  10. package/src/queriesObserver.ts +9 -0
  11. package/src/__tests__/OmitKeyof.test-d.ts +0 -175
  12. package/src/__tests__/focusManager.test.tsx +0 -163
  13. package/src/__tests__/hydration.test.tsx +0 -1069
  14. package/src/__tests__/infiniteQueryBehavior.test.tsx +0 -427
  15. package/src/__tests__/infiniteQueryObserver.test-d.tsx +0 -64
  16. package/src/__tests__/infiniteQueryObserver.test.tsx +0 -198
  17. package/src/__tests__/mutationCache.test.tsx +0 -376
  18. package/src/__tests__/mutationObserver.test.tsx +0 -326
  19. package/src/__tests__/mutations.test.tsx +0 -603
  20. package/src/__tests__/notifyManager.test.tsx +0 -85
  21. package/src/__tests__/onlineManager.test.tsx +0 -168
  22. package/src/__tests__/queriesObserver.test.tsx +0 -267
  23. package/src/__tests__/query.test.tsx +0 -1049
  24. package/src/__tests__/queryCache.test.tsx +0 -350
  25. package/src/__tests__/queryClient.test-d.tsx +0 -156
  26. package/src/__tests__/queryClient.test.tsx +0 -2031
  27. package/src/__tests__/queryObserver.test-d.tsx +0 -108
  28. package/src/__tests__/queryObserver.test.tsx +0 -1236
  29. package/src/__tests__/utils.test.tsx +0 -468
  30. package/src/__tests__/utils.ts +0 -59
@@ -1,376 +0,0 @@
1
- import { describe, expect, test, vi } from 'vitest'
2
- import { waitFor } from '@testing-library/react'
3
- import { MutationCache, MutationObserver } from '..'
4
- import { createQueryClient, executeMutation, queryKey, sleep } from './utils'
5
-
6
- describe('mutationCache', () => {
7
- describe('MutationCacheConfig error callbacks', () => {
8
- test('should call onError and onSettled when a mutation errors', async () => {
9
- const key = queryKey()
10
- const onError = vi.fn()
11
- const onSuccess = vi.fn()
12
- const onSettled = vi.fn()
13
- const testCache = new MutationCache({ onError, onSuccess, onSettled })
14
- const testClient = createQueryClient({ mutationCache: testCache })
15
-
16
- try {
17
- await executeMutation(
18
- testClient,
19
- {
20
- mutationKey: key,
21
- mutationFn: () => Promise.reject(new Error('error')),
22
- onMutate: () => 'context',
23
- },
24
- 'vars',
25
- )
26
- } catch {}
27
-
28
- const mutation = testCache.getAll()[0]
29
- expect(onError).toHaveBeenCalledTimes(1)
30
- expect(onError).toHaveBeenCalledWith(
31
- new Error('error'),
32
- 'vars',
33
- 'context',
34
- mutation,
35
- )
36
- expect(onSuccess).not.toHaveBeenCalled()
37
- expect(onSettled).toHaveBeenCalledTimes(1)
38
- expect(onSettled).toHaveBeenCalledWith(
39
- undefined,
40
- new Error('error'),
41
- 'vars',
42
- 'context',
43
- mutation,
44
- )
45
- })
46
-
47
- test('should be awaited', async () => {
48
- const key = queryKey()
49
- const states: Array<number> = []
50
- const onError = async () => {
51
- states.push(1)
52
- await sleep(1)
53
- states.push(2)
54
- }
55
- const onSettled = async () => {
56
- states.push(5)
57
- await sleep(1)
58
- states.push(6)
59
- }
60
- const testCache = new MutationCache({ onError, onSettled })
61
- const testClient = createQueryClient({ mutationCache: testCache })
62
-
63
- try {
64
- await executeMutation(
65
- testClient,
66
- {
67
- mutationKey: key,
68
- mutationFn: () => Promise.reject(new Error('error')),
69
- onError: async () => {
70
- states.push(3)
71
- await sleep(1)
72
- states.push(4)
73
- },
74
- onSettled: async () => {
75
- states.push(7)
76
- await sleep(1)
77
- states.push(8)
78
- },
79
- },
80
- 'vars',
81
- )
82
- } catch {}
83
-
84
- expect(states).toEqual([1, 2, 3, 4, 5, 6, 7, 8])
85
- })
86
- })
87
- describe('MutationCacheConfig success callbacks', () => {
88
- test('should call onSuccess and onSettled when a mutation is successful', async () => {
89
- const key = queryKey()
90
- const onError = vi.fn()
91
- const onSuccess = vi.fn()
92
- const onSettled = vi.fn()
93
- const testCache = new MutationCache({ onError, onSuccess, onSettled })
94
- const testClient = createQueryClient({ mutationCache: testCache })
95
-
96
- try {
97
- await executeMutation(
98
- testClient,
99
- {
100
- mutationKey: key,
101
- mutationFn: () => Promise.resolve({ data: 5 }),
102
- onMutate: () => 'context',
103
- },
104
- 'vars',
105
- )
106
- } catch {}
107
-
108
- const mutation = testCache.getAll()[0]
109
- expect(onSuccess).toHaveBeenCalledTimes(1)
110
- expect(onSuccess).toHaveBeenCalledWith(
111
- { data: 5 },
112
- 'vars',
113
- 'context',
114
- mutation,
115
- )
116
- expect(onError).not.toHaveBeenCalled()
117
- expect(onSettled).toHaveBeenCalledTimes(1)
118
- expect(onSettled).toHaveBeenCalledWith(
119
- { data: 5 },
120
- null,
121
- 'vars',
122
- 'context',
123
- mutation,
124
- )
125
- })
126
- test('should be awaited', async () => {
127
- const key = queryKey()
128
- const states: Array<number> = []
129
- const onSuccess = async () => {
130
- states.push(1)
131
- await sleep(1)
132
- states.push(2)
133
- }
134
- const onSettled = async () => {
135
- states.push(5)
136
- await sleep(1)
137
- states.push(6)
138
- }
139
- const testCache = new MutationCache({ onSuccess, onSettled })
140
- const testClient = createQueryClient({ mutationCache: testCache })
141
-
142
- await executeMutation(
143
- testClient,
144
- {
145
- mutationKey: key,
146
- mutationFn: () => Promise.resolve({ data: 5 }),
147
- onSuccess: async () => {
148
- states.push(3)
149
- await sleep(1)
150
- states.push(4)
151
- },
152
- onSettled: async () => {
153
- states.push(7)
154
- await sleep(1)
155
- states.push(8)
156
- },
157
- },
158
- 'vars',
159
- )
160
-
161
- expect(states).toEqual([1, 2, 3, 4, 5, 6, 7, 8])
162
- })
163
- })
164
- describe('MutationCacheConfig.onMutate', () => {
165
- test('should be called before a mutation executes', async () => {
166
- const key = queryKey()
167
- const onMutate = vi.fn()
168
- const testCache = new MutationCache({ onMutate })
169
- const testClient = createQueryClient({ mutationCache: testCache })
170
-
171
- try {
172
- await executeMutation(
173
- testClient,
174
- {
175
- mutationKey: key,
176
- mutationFn: () => Promise.resolve({ data: 5 }),
177
- onMutate: () => 'context',
178
- },
179
- 'vars',
180
- )
181
- } catch {}
182
-
183
- const mutation = testCache.getAll()[0]
184
- expect(onMutate).toHaveBeenCalledWith('vars', mutation)
185
- })
186
-
187
- test('should be awaited', async () => {
188
- const key = queryKey()
189
- const states: Array<number> = []
190
- const onMutate = async () => {
191
- states.push(1)
192
- await sleep(1)
193
- states.push(2)
194
- }
195
- const testCache = new MutationCache({ onMutate })
196
- const testClient = createQueryClient({ mutationCache: testCache })
197
-
198
- await executeMutation(
199
- testClient,
200
- {
201
- mutationKey: key,
202
- mutationFn: () => Promise.resolve({ data: 5 }),
203
- onMutate: async () => {
204
- states.push(3)
205
- await sleep(1)
206
- states.push(4)
207
- },
208
- },
209
- 'vars',
210
- )
211
-
212
- expect(states).toEqual([1, 2, 3, 4])
213
- })
214
- })
215
-
216
- describe('find', () => {
217
- test('should filter correctly', async () => {
218
- const testCache = new MutationCache()
219
- const testClient = createQueryClient({ mutationCache: testCache })
220
- const key = ['mutation', 'vars']
221
- await executeMutation(
222
- testClient,
223
- {
224
- mutationKey: key,
225
- mutationFn: () => Promise.resolve(),
226
- },
227
- 'vars',
228
- )
229
- const [mutation] = testCache.getAll()
230
- expect(testCache.find({ mutationKey: key })).toEqual(mutation)
231
- expect(
232
- testCache.find({ mutationKey: ['mutation'], exact: false }),
233
- ).toEqual(mutation)
234
- expect(testCache.find({ mutationKey: ['unknown'] })).toEqual(undefined)
235
- expect(
236
- testCache.find({
237
- predicate: (m) => m.options.mutationKey?.[0] === key[0],
238
- }),
239
- ).toEqual(mutation)
240
- })
241
- })
242
-
243
- describe('findAll', () => {
244
- test('should filter correctly', async () => {
245
- const testCache = new MutationCache()
246
- const testClient = createQueryClient({ mutationCache: testCache })
247
- await executeMutation(
248
- testClient,
249
- {
250
- mutationKey: ['a', 1],
251
- mutationFn: () => Promise.resolve(),
252
- },
253
- 1,
254
- )
255
- await executeMutation(
256
- testClient,
257
- {
258
- mutationKey: ['a', 2],
259
- mutationFn: () => Promise.resolve(),
260
- },
261
- 2,
262
- )
263
- await executeMutation(
264
- testClient,
265
- {
266
- mutationKey: ['b'],
267
- mutationFn: () => Promise.resolve(),
268
- },
269
- 3,
270
- )
271
-
272
- const [mutation1, mutation2] = testCache.getAll()
273
- expect(
274
- testCache.findAll({ mutationKey: ['a'], exact: false }),
275
- ).toHaveLength(2)
276
- expect(testCache.find({ mutationKey: ['a', 1] })).toEqual(mutation1)
277
- expect(
278
- testCache.findAll({
279
- predicate: (m) => m.options.mutationKey?.[1] === 2,
280
- }),
281
- ).toEqual([mutation2])
282
- expect(testCache.findAll({ mutationKey: ['unknown'] })).toEqual([])
283
- })
284
- })
285
-
286
- describe('garbage collection', () => {
287
- test('should remove unused mutations after gcTime has elapsed', async () => {
288
- const testCache = new MutationCache()
289
- const testClient = createQueryClient({ mutationCache: testCache })
290
- const onSuccess = vi.fn()
291
- await executeMutation(
292
- testClient,
293
- {
294
- mutationKey: ['a', 1],
295
- gcTime: 10,
296
- mutationFn: () => Promise.resolve(),
297
- onSuccess,
298
- },
299
- 1,
300
- )
301
-
302
- expect(testCache.getAll()).toHaveLength(1)
303
- await sleep(10)
304
- await waitFor(() => {
305
- expect(testCache.getAll()).toHaveLength(0)
306
- })
307
- expect(onSuccess).toHaveBeenCalledTimes(1)
308
- })
309
-
310
- test('should not remove mutations if there are active observers', async () => {
311
- const queryClient = createQueryClient()
312
- const observer = new MutationObserver(queryClient, {
313
- gcTime: 10,
314
- mutationFn: (input: number) => Promise.resolve(input),
315
- })
316
- const unsubscribe = observer.subscribe(() => undefined)
317
-
318
- expect(queryClient.getMutationCache().getAll()).toHaveLength(0)
319
- observer.mutate(1)
320
- expect(queryClient.getMutationCache().getAll()).toHaveLength(1)
321
- await sleep(10)
322
- expect(queryClient.getMutationCache().getAll()).toHaveLength(1)
323
- unsubscribe()
324
- expect(queryClient.getMutationCache().getAll()).toHaveLength(1)
325
- await sleep(10)
326
- await waitFor(() => {
327
- expect(queryClient.getMutationCache().getAll()).toHaveLength(0)
328
- })
329
- })
330
-
331
- test('should be garbage collected later when unsubscribed and mutation is pending', async () => {
332
- const queryClient = createQueryClient()
333
- const onSuccess = vi.fn()
334
- const observer = new MutationObserver(queryClient, {
335
- gcTime: 10,
336
- mutationFn: async () => {
337
- await sleep(20)
338
- return 'data'
339
- },
340
- onSuccess,
341
- })
342
- const unsubscribe = observer.subscribe(() => undefined)
343
- observer.mutate(1)
344
- unsubscribe()
345
- expect(queryClient.getMutationCache().getAll()).toHaveLength(1)
346
- await sleep(10)
347
- // unsubscribe should not remove even though gcTime has elapsed b/c mutation is still pending
348
- expect(queryClient.getMutationCache().getAll()).toHaveLength(1)
349
- await sleep(10)
350
- // should be removed after an additional gcTime wait
351
- await waitFor(() => {
352
- expect(queryClient.getMutationCache().getAll()).toHaveLength(0)
353
- })
354
- expect(onSuccess).toHaveBeenCalledTimes(1)
355
- })
356
-
357
- test('should call callbacks even with gcTime 0 and mutation still pending', async () => {
358
- const queryClient = createQueryClient()
359
- const onSuccess = vi.fn()
360
- const observer = new MutationObserver(queryClient, {
361
- gcTime: 0,
362
- mutationFn: async () => {
363
- return 'data'
364
- },
365
- onSuccess,
366
- })
367
- const unsubscribe = observer.subscribe(() => undefined)
368
- observer.mutate(1)
369
- unsubscribe()
370
- await waitFor(() => {
371
- expect(queryClient.getMutationCache().getAll()).toHaveLength(0)
372
- })
373
- expect(onSuccess).toHaveBeenCalledTimes(1)
374
- })
375
- })
376
- })
@@ -1,326 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
2
- import { waitFor } from '@testing-library/react'
3
- import { MutationObserver } from '..'
4
- import { createQueryClient, queryKey, sleep } from './utils'
5
- import type { QueryClient } from '..'
6
-
7
- describe('mutationObserver', () => {
8
- let queryClient: QueryClient
9
-
10
- beforeEach(() => {
11
- queryClient = createQueryClient()
12
- queryClient.mount()
13
- })
14
-
15
- afterEach(() => {
16
- queryClient.clear()
17
- })
18
-
19
- test('onUnsubscribe should not remove the current mutation observer if there is still a subscription', async () => {
20
- const mutation = new MutationObserver(queryClient, {
21
- mutationFn: async (text: string) => {
22
- await sleep(20)
23
- return text
24
- },
25
- })
26
-
27
- const subscription1Handler = vi.fn()
28
- const subscription2Handler = vi.fn()
29
-
30
- const unsubscribe1 = mutation.subscribe(subscription1Handler)
31
- const unsubscribe2 = mutation.subscribe(subscription2Handler)
32
-
33
- mutation.mutate('input')
34
-
35
- unsubscribe1()
36
-
37
- await waitFor(() => {
38
- // 1 call: loading
39
- expect(subscription1Handler).toBeCalledTimes(1)
40
- // 2 calls: loading, success
41
- expect(subscription2Handler).toBeCalledTimes(2)
42
- })
43
-
44
- // Clean-up
45
- unsubscribe2()
46
- })
47
-
48
- test('unsubscribe should remove observer to trigger GC', async () => {
49
- const mutation = new MutationObserver(queryClient, {
50
- mutationFn: async (text: string) => {
51
- await sleep(5)
52
- return text
53
- },
54
- gcTime: 10,
55
- })
56
-
57
- const subscriptionHandler = vi.fn()
58
-
59
- const unsubscribe = mutation.subscribe(subscriptionHandler)
60
-
61
- await mutation.mutate('input')
62
-
63
- expect(queryClient.getMutationCache().findAll()).toHaveLength(1)
64
-
65
- unsubscribe()
66
-
67
- await waitFor(() =>
68
- expect(queryClient.getMutationCache().findAll()).toHaveLength(0),
69
- )
70
- })
71
-
72
- test('reset should remove observer to trigger GC', async () => {
73
- const mutation = new MutationObserver(queryClient, {
74
- mutationFn: async (text: string) => {
75
- await sleep(5)
76
- return text
77
- },
78
- gcTime: 10,
79
- })
80
-
81
- const subscriptionHandler = vi.fn()
82
-
83
- const unsubscribe = mutation.subscribe(subscriptionHandler)
84
-
85
- await mutation.mutate('input')
86
-
87
- expect(queryClient.getMutationCache().findAll()).toHaveLength(1)
88
-
89
- mutation.reset()
90
-
91
- await waitFor(() =>
92
- expect(queryClient.getMutationCache().findAll()).toHaveLength(0),
93
- )
94
-
95
- unsubscribe()
96
- })
97
-
98
- test('changing mutation keys should reset the observer', async () => {
99
- const key = queryKey()
100
- const mutation = new MutationObserver(queryClient, {
101
- mutationKey: [...key, '1'],
102
- mutationFn: async (text: string) => {
103
- await sleep(5)
104
- return text
105
- },
106
- })
107
-
108
- const subscriptionHandler = vi.fn()
109
-
110
- const unsubscribe = mutation.subscribe(subscriptionHandler)
111
-
112
- await mutation.mutate('input')
113
-
114
- expect(mutation.getCurrentResult()).toMatchObject({
115
- status: 'success',
116
- data: 'input',
117
- })
118
-
119
- mutation.setOptions({
120
- mutationKey: [...key, '2'],
121
- })
122
-
123
- expect(mutation.getCurrentResult()).toMatchObject({
124
- status: 'idle',
125
- })
126
-
127
- unsubscribe()
128
- })
129
-
130
- test('changing mutation keys should not affect already existing mutations', async () => {
131
- const key = queryKey()
132
- const mutationObserver = new MutationObserver(queryClient, {
133
- mutationKey: [...key, '1'],
134
- mutationFn: async (text: string) => {
135
- await sleep(5)
136
- return text
137
- },
138
- })
139
-
140
- const subscriptionHandler = vi.fn()
141
-
142
- const unsubscribe = mutationObserver.subscribe(subscriptionHandler)
143
-
144
- await mutationObserver.mutate('input')
145
-
146
- expect(
147
- queryClient.getMutationCache().find({ mutationKey: [...key, '1'] }),
148
- ).toMatchObject({
149
- options: { mutationKey: [...key, '1'] },
150
- state: {
151
- status: 'success',
152
- data: 'input',
153
- },
154
- })
155
-
156
- mutationObserver.setOptions({
157
- mutationKey: [...key, '2'],
158
- })
159
-
160
- expect(
161
- queryClient.getMutationCache().find({ mutationKey: [...key, '1'] }),
162
- ).toMatchObject({
163
- options: { mutationKey: [...key, '1'] },
164
- state: {
165
- status: 'success',
166
- data: 'input',
167
- },
168
- })
169
-
170
- unsubscribe()
171
- })
172
-
173
- test('changing mutation meta should not affect successful mutations', async () => {
174
- const mutationObserver = new MutationObserver(queryClient, {
175
- meta: { a: 1 },
176
- mutationFn: async (text: string) => {
177
- await sleep(5)
178
- return text
179
- },
180
- })
181
-
182
- const subscriptionHandler = vi.fn()
183
-
184
- const unsubscribe = mutationObserver.subscribe(subscriptionHandler)
185
-
186
- await mutationObserver.mutate('input')
187
-
188
- expect(queryClient.getMutationCache().find({})).toMatchObject({
189
- options: { meta: { a: 1 } },
190
- state: {
191
- status: 'success',
192
- data: 'input',
193
- },
194
- })
195
-
196
- mutationObserver.setOptions({
197
- meta: { a: 2 },
198
- })
199
-
200
- expect(queryClient.getMutationCache().find({})).toMatchObject({
201
- options: { meta: { a: 1 } },
202
- state: {
203
- status: 'success',
204
- data: 'input',
205
- },
206
- })
207
-
208
- unsubscribe()
209
- })
210
-
211
- test('mutation cache should have different meta when updated between mutations', async () => {
212
- const mutationFn = async (text: string) => {
213
- await sleep(5)
214
- return text
215
- }
216
- const mutationObserver = new MutationObserver(queryClient, {
217
- meta: { a: 1 },
218
- mutationFn,
219
- })
220
-
221
- const subscriptionHandler = vi.fn()
222
-
223
- const unsubscribe = mutationObserver.subscribe(subscriptionHandler)
224
-
225
- await mutationObserver.mutate('input')
226
-
227
- mutationObserver.setOptions({
228
- meta: { a: 2 },
229
- mutationFn,
230
- })
231
-
232
- await mutationObserver.mutate('input')
233
-
234
- const mutations = queryClient.getMutationCache().findAll()
235
- expect(mutations[0]).toMatchObject({
236
- options: { meta: { a: 1 } },
237
- state: {
238
- status: 'success',
239
- data: 'input',
240
- },
241
- })
242
- expect(mutations[1]).toMatchObject({
243
- options: { meta: { a: 2 } },
244
- state: {
245
- status: 'success',
246
- data: 'input',
247
- },
248
- })
249
-
250
- unsubscribe()
251
- })
252
-
253
- test('changing mutation meta should not affect rejected mutations', async () => {
254
- const mutationObserver = new MutationObserver(queryClient, {
255
- meta: { a: 1 },
256
- mutationFn: async (_: string) => {
257
- await sleep(5)
258
- return Promise.reject(new Error('err'))
259
- },
260
- })
261
-
262
- const subscriptionHandler = vi.fn()
263
-
264
- const unsubscribe = mutationObserver.subscribe(subscriptionHandler)
265
-
266
- await mutationObserver.mutate('input').catch(() => undefined)
267
-
268
- expect(queryClient.getMutationCache().find({})).toMatchObject({
269
- options: { meta: { a: 1 } },
270
- state: {
271
- status: 'error',
272
- },
273
- })
274
-
275
- mutationObserver.setOptions({
276
- meta: { a: 2 },
277
- })
278
-
279
- expect(queryClient.getMutationCache().find({})).toMatchObject({
280
- options: { meta: { a: 1 } },
281
- state: {
282
- status: 'error',
283
- },
284
- })
285
-
286
- unsubscribe()
287
- })
288
-
289
- test('changing mutation meta should affect pending mutations', async () => {
290
- const mutationObserver = new MutationObserver(queryClient, {
291
- meta: { a: 1 },
292
- mutationFn: async (text: string) => {
293
- await sleep(20)
294
- return text
295
- },
296
- })
297
-
298
- const subscriptionHandler = vi.fn()
299
-
300
- const unsubscribe = mutationObserver.subscribe(subscriptionHandler)
301
-
302
- mutationObserver.mutate('input')
303
-
304
- await sleep(0)
305
-
306
- expect(queryClient.getMutationCache().find({})).toMatchObject({
307
- options: { meta: { a: 1 } },
308
- state: {
309
- status: 'pending',
310
- },
311
- })
312
-
313
- mutationObserver.setOptions({
314
- meta: { a: 2 },
315
- })
316
-
317
- expect(queryClient.getMutationCache().find({})).toMatchObject({
318
- options: { meta: { a: 2 } },
319
- state: {
320
- status: 'pending',
321
- },
322
- })
323
-
324
- unsubscribe()
325
- })
326
- })