@tanstack/solid-query 4.24.10 → 5.0.0-alpha.0
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/cjs/index.js +298 -0
- package/build/cjs/index.js.map +1 -0
- package/build/esm/index.js +283 -0
- package/build/esm/index.js.map +1 -0
- package/build/source/QueryClientProvider.jsx +21 -0
- package/build/source/__tests__/QueryClientProvider.test.jsx +120 -0
- package/build/{solid → source}/__tests__/createInfiniteQuery.test.jsx +228 -372
- package/build/{solid → source}/__tests__/createMutation.test.jsx +174 -165
- package/build/{solid → source}/__tests__/createQueries.test.jsx +86 -367
- package/build/{solid → source}/__tests__/createQuery.test.jsx +991 -943
- package/build/{solid → source}/__tests__/createQuery.types.test.jsx +35 -24
- package/build/{solid → source}/__tests__/suspense.test.jsx +177 -148
- package/build/{solid → source}/__tests__/transition.test.jsx +7 -4
- package/build/{solid → source}/__tests__/useIsFetching.test.jsx +68 -85
- package/build/{solid → source}/__tests__/useIsMutating.test.jsx +78 -93
- package/build/{solid → source}/__tests__/utils.jsx +3 -9
- package/build/source/createBaseQuery.js +147 -0
- package/build/source/createInfiniteQuery.js +6 -0
- package/build/{solid → source}/createMutation.js +7 -9
- package/build/source/createQueries.js +32 -0
- package/build/source/createQuery.js +6 -0
- package/build/{solid → source}/index.js +5 -3
- package/build/source/setBatchUpdatesFn.js +3 -0
- package/build/source/useIsFetching.js +12 -0
- package/build/source/useIsMutating.js +12 -0
- package/build/source/utils.js +7 -0
- package/build/types/QueryClientProvider.d.ts +9 -0
- package/build/{lib → types}/__tests__/utils.d.ts +3 -8
- package/build/types/createBaseQuery.d.ts +4 -0
- package/build/types/createInfiniteQuery.d.ts +3 -0
- package/build/types/createMutation.d.ts +3 -0
- package/build/{lib → types}/createQueries.d.ts +10 -8
- package/build/types/createQuery.d.ts +11 -0
- package/build/{lib → types}/index.d.ts +4 -3
- package/build/types/setBatchUpdatesFn.d.ts +1 -0
- package/build/types/types.d.ts +33 -0
- package/build/types/useIsFetching.d.ts +8 -0
- package/build/types/useIsMutating.d.ts +8 -0
- package/build/types/utils.d.ts +1 -0
- package/build/umd/index.js +2 -0
- package/build/umd/index.js.map +1 -0
- package/package.json +25 -17
- package/src/QueryClientProvider.tsx +17 -86
- package/src/__tests__/QueryClientProvider.test.tsx +37 -140
- package/src/__tests__/createInfiniteQuery.test.tsx +277 -508
- package/src/__tests__/createMutation.test.tsx +177 -225
- package/src/__tests__/createQueries.test.tsx +180 -528
- package/src/__tests__/createQuery.test.tsx +970 -1200
- package/src/__tests__/createQuery.types.test.tsx +30 -25
- package/src/__tests__/suspense.test.tsx +141 -178
- package/src/__tests__/transition.test.tsx +7 -4
- package/src/__tests__/useIsFetching.test.tsx +77 -122
- package/src/__tests__/useIsMutating.test.tsx +83 -128
- package/src/__tests__/utils.tsx +4 -11
- package/src/createBaseQuery.ts +148 -60
- package/src/createInfiniteQuery.ts +15 -94
- package/src/createMutation.ts +9 -63
- package/src/createQueries.ts +44 -55
- package/src/createQuery.ts +42 -127
- package/src/index.ts +6 -3
- package/src/setBatchUpdatesFn.ts +4 -0
- package/src/types.ts +81 -75
- package/src/useIsFetching.ts +12 -44
- package/src/useIsMutating.ts +13 -29
- package/src/utils.ts +5 -79
- package/build/lib/QueryClientProvider.d.ts +0 -24
- package/build/lib/QueryClientProvider.esm.js +0 -74
- package/build/lib/QueryClientProvider.esm.js.map +0 -1
- package/build/lib/QueryClientProvider.js +0 -80
- package/build/lib/QueryClientProvider.js.map +0 -1
- package/build/lib/QueryClientProvider.mjs +0 -74
- package/build/lib/QueryClientProvider.mjs.map +0 -1
- package/build/lib/createBaseQuery.d.ts +0 -4
- package/build/lib/createBaseQuery.esm.js +0 -93
- package/build/lib/createBaseQuery.esm.js.map +0 -1
- package/build/lib/createBaseQuery.js +0 -97
- package/build/lib/createBaseQuery.js.map +0 -1
- package/build/lib/createBaseQuery.mjs +0 -93
- package/build/lib/createBaseQuery.mjs.map +0 -1
- package/build/lib/createInfiniteQuery.d.ts +0 -5
- package/build/lib/createInfiniteQuery.esm.js +0 -20
- package/build/lib/createInfiniteQuery.esm.js.map +0 -1
- package/build/lib/createInfiniteQuery.js +0 -24
- package/build/lib/createInfiniteQuery.js.map +0 -1
- package/build/lib/createInfiniteQuery.mjs +0 -20
- package/build/lib/createInfiniteQuery.mjs.map +0 -1
- package/build/lib/createMutation.d.ts +0 -6
- package/build/lib/createMutation.esm.js +0 -45
- package/build/lib/createMutation.esm.js.map +0 -1
- package/build/lib/createMutation.js +0 -49
- package/build/lib/createMutation.js.map +0 -1
- package/build/lib/createMutation.mjs +0 -45
- package/build/lib/createMutation.mjs.map +0 -1
- package/build/lib/createQueries.esm.js +0 -54
- package/build/lib/createQueries.esm.js.map +0 -1
- package/build/lib/createQueries.js +0 -58
- package/build/lib/createQueries.js.map +0 -1
- package/build/lib/createQueries.mjs +0 -54
- package/build/lib/createQueries.mjs.map +0 -1
- package/build/lib/createQuery.d.ts +0 -23
- package/build/lib/createQuery.esm.js +0 -25
- package/build/lib/createQuery.esm.js.map +0 -1
- package/build/lib/createQuery.js +0 -29
- package/build/lib/createQuery.js.map +0 -1
- package/build/lib/createQuery.mjs +0 -25
- package/build/lib/createQuery.mjs.map +0 -1
- package/build/lib/index.esm.js +0 -9
- package/build/lib/index.esm.js.map +0 -1
- package/build/lib/index.js +0 -31
- package/build/lib/index.js.map +0 -1
- package/build/lib/index.mjs +0 -9
- package/build/lib/index.mjs.map +0 -1
- package/build/lib/types.d.ts +0 -47
- package/build/lib/useIsFetching.d.ts +0 -7
- package/build/lib/useIsFetching.esm.js +0 -29
- package/build/lib/useIsFetching.esm.js.map +0 -1
- package/build/lib/useIsFetching.js +0 -33
- package/build/lib/useIsFetching.js.map +0 -1
- package/build/lib/useIsFetching.mjs +0 -29
- package/build/lib/useIsFetching.mjs.map +0 -1
- package/build/lib/useIsMutating.d.ts +0 -8
- package/build/lib/useIsMutating.esm.js +0 -22
- package/build/lib/useIsMutating.esm.js.map +0 -1
- package/build/lib/useIsMutating.js +0 -26
- package/build/lib/useIsMutating.js.map +0 -1
- package/build/lib/useIsMutating.mjs +0 -22
- package/build/lib/useIsMutating.mjs.map +0 -1
- package/build/lib/utils.d.ts +0 -14
- package/build/lib/utils.esm.js +0 -63
- package/build/lib/utils.esm.js.map +0 -1
- package/build/lib/utils.js +0 -72
- package/build/lib/utils.js.map +0 -1
- package/build/lib/utils.mjs +0 -63
- package/build/lib/utils.mjs.map +0 -1
- package/build/solid/QueryClientProvider.jsx +0 -49
- package/build/solid/__tests__/QueryClientProvider.test.jsx +0 -185
- package/build/solid/createBaseQuery.js +0 -81
- package/build/solid/createInfiniteQuery.js +0 -16
- package/build/solid/createQueries.js +0 -39
- package/build/solid/createQuery.js +0 -16
- package/build/solid/useIsFetching.js +0 -23
- package/build/solid/useIsMutating.js +0 -16
- package/build/solid/utils.js +0 -45
- package/build/umd/index.development.js +0 -3577
- package/build/umd/index.development.js.map +0 -1
- package/build/umd/index.production.js +0 -2
- package/build/umd/index.production.js.map +0 -1
- /package/build/{solid → source}/types.js +0 -0
- /package/build/{lib → types}/__tests__/QueryClientProvider.test.d.ts +0 -0
- /package/build/{lib → types}/__tests__/createInfiniteQuery.test.d.ts +0 -0
- /package/build/{lib → types}/__tests__/createMutation.test.d.ts +0 -0
- /package/build/{lib → types}/__tests__/createQueries.test.d.ts +0 -0
- /package/build/{lib → types}/__tests__/createQuery.test.d.ts +0 -0
- /package/build/{lib → types}/__tests__/createQuery.types.test.d.ts +0 -0
- /package/build/{lib → types}/__tests__/suspense.test.d.ts +0 -0
- /package/build/{lib → types}/__tests__/transition.test.d.ts +0 -0
- /package/build/{lib → types}/__tests__/useIsFetching.test.d.ts +0 -0
- /package/build/{lib → types}/__tests__/useIsMutating.test.d.ts +0 -0
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import '@testing-library/jest-dom';
|
|
2
|
-
import {
|
|
2
|
+
import { createEffect, createRenderEffect, createSignal, ErrorBoundary, } from 'solid-js';
|
|
3
3
|
import { fireEvent, render, screen, waitFor } from 'solid-testing-library';
|
|
4
4
|
import { createMutation, MutationCache, QueryCache, QueryClientProvider, } from '..';
|
|
5
5
|
import { createQueryClient, mockNavigatorOnLine, queryKey, setActTimeout, sleep, } from './utils';
|
|
6
|
-
describe('
|
|
6
|
+
describe('createMutation', () => {
|
|
7
7
|
const queryCache = new QueryCache();
|
|
8
8
|
const mutationCache = new MutationCache();
|
|
9
9
|
const queryClient = createQueryClient({ queryCache, mutationCache });
|
|
10
10
|
it('should be able to reset `data`', async () => {
|
|
11
11
|
function Page() {
|
|
12
|
-
const mutation = createMutation(() =>
|
|
12
|
+
const mutation = createMutation(() => ({
|
|
13
|
+
mutationFn: () => Promise.resolve('mutation'),
|
|
14
|
+
}));
|
|
13
15
|
return (<div>
|
|
14
16
|
<h1>{mutation.data ?? 'empty'}</h1>
|
|
15
17
|
<button onClick={() => mutation.reset()}>reset</button>
|
|
@@ -31,11 +33,13 @@ describe('useMutation', () => {
|
|
|
31
33
|
});
|
|
32
34
|
it('should be able to reset `error`', async () => {
|
|
33
35
|
function Page() {
|
|
34
|
-
const mutation = createMutation(() => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
const mutation = createMutation(() => ({
|
|
37
|
+
mutationFn: () => {
|
|
38
|
+
const err = new Error('Expected mock error. All is well!');
|
|
39
|
+
err.stack = '';
|
|
40
|
+
return Promise.reject(err);
|
|
41
|
+
},
|
|
42
|
+
}));
|
|
39
43
|
return (<div>
|
|
40
44
|
{mutation.error && <h1>{mutation.error.message}</h1>}
|
|
41
45
|
<button onClick={() => mutation.reset()}>reset</button>
|
|
@@ -62,14 +66,15 @@ describe('useMutation', () => {
|
|
|
62
66
|
const onSuccessMock = jest.fn();
|
|
63
67
|
const onSettledMock = jest.fn();
|
|
64
68
|
function Page() {
|
|
65
|
-
const mutation = createMutation((
|
|
69
|
+
const mutation = createMutation(() => ({
|
|
70
|
+
mutationFn: (vars) => Promise.resolve(vars.count),
|
|
66
71
|
onSuccess: (data) => {
|
|
67
72
|
onSuccessMock(data);
|
|
68
73
|
},
|
|
69
74
|
onSettled: (data) => {
|
|
70
75
|
onSettledMock(data);
|
|
71
76
|
},
|
|
72
|
-
});
|
|
77
|
+
}));
|
|
73
78
|
return (<div>
|
|
74
79
|
<h1>{count()}</h1>
|
|
75
80
|
<button onClick={() => {
|
|
@@ -107,19 +112,21 @@ describe('useMutation', () => {
|
|
|
107
112
|
const [count, setCount] = createSignal(0);
|
|
108
113
|
const mutateFn = jest.fn();
|
|
109
114
|
mutateFn.mockImplementationOnce(() => {
|
|
110
|
-
return Promise.reject('Error test Jonas');
|
|
115
|
+
return Promise.reject(new Error('Error test Jonas'));
|
|
111
116
|
});
|
|
112
117
|
mutateFn.mockImplementation(async (value) => {
|
|
113
118
|
await sleep(10);
|
|
114
119
|
return Promise.resolve(value);
|
|
115
120
|
});
|
|
116
121
|
function Page() {
|
|
117
|
-
const mutation = createMutation(
|
|
122
|
+
const mutation = createMutation(() => ({
|
|
123
|
+
mutationFn: mutateFn,
|
|
124
|
+
}));
|
|
118
125
|
return (<div>
|
|
119
126
|
<h1>Data {mutation.data?.count}</h1>
|
|
120
127
|
<h2>Status {mutation.status}</h2>
|
|
121
128
|
<h2>Failed {mutation.failureCount} times</h2>
|
|
122
|
-
<h2>Failed because {mutation.failureReason ?? 'null'}</h2>
|
|
129
|
+
<h2>Failed because {mutation.failureReason?.message ?? 'null'}</h2>
|
|
123
130
|
<button onClick={() => {
|
|
124
131
|
setCount((c) => c + 1);
|
|
125
132
|
return mutation.mutate({ count: count() });
|
|
@@ -138,7 +145,7 @@ describe('useMutation', () => {
|
|
|
138
145
|
await waitFor(() => screen.getByText('Failed 1 times'));
|
|
139
146
|
await waitFor(() => screen.getByText('Failed because Error test Jonas'));
|
|
140
147
|
fireEvent.click(screen.getByRole('button', { name: /mutate/i }));
|
|
141
|
-
await waitFor(() => screen.getByText('Status
|
|
148
|
+
await waitFor(() => screen.getByText('Status pending'));
|
|
142
149
|
await waitFor(() => screen.getByText('Status success'));
|
|
143
150
|
await waitFor(() => screen.getByText('Data 2'));
|
|
144
151
|
await waitFor(() => screen.getByText('Failed 0 times'));
|
|
@@ -149,18 +156,19 @@ describe('useMutation', () => {
|
|
|
149
156
|
const onSettledMock = jest.fn();
|
|
150
157
|
const [count, setCount] = createSignal(0);
|
|
151
158
|
function Page() {
|
|
152
|
-
const mutation = createMutation((
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
159
|
+
const mutation = createMutation(() => ({
|
|
160
|
+
mutationFn: (vars) => {
|
|
161
|
+
const error = new Error(`Expected mock error. All is well! ${vars.count}`);
|
|
162
|
+
error.stack = '';
|
|
163
|
+
return Promise.reject(error);
|
|
164
|
+
},
|
|
157
165
|
onError: (error) => {
|
|
158
166
|
onErrorMock(error.message);
|
|
159
167
|
},
|
|
160
168
|
onSettled: (_data, error) => {
|
|
161
169
|
onSettledMock(error?.message);
|
|
162
170
|
},
|
|
163
|
-
});
|
|
171
|
+
}));
|
|
164
172
|
return (<div>
|
|
165
173
|
<h1>{count()}</h1>
|
|
166
174
|
<button onClick={() => {
|
|
@@ -197,14 +205,15 @@ describe('useMutation', () => {
|
|
|
197
205
|
it('should be able to override the useMutation success callbacks', async () => {
|
|
198
206
|
const callbacks = [];
|
|
199
207
|
function Page() {
|
|
200
|
-
const mutation = createMutation(
|
|
208
|
+
const mutation = createMutation(() => ({
|
|
209
|
+
mutationFn: async (text) => text,
|
|
201
210
|
onSuccess: async () => {
|
|
202
211
|
callbacks.push('useMutation.onSuccess');
|
|
203
212
|
},
|
|
204
213
|
onSettled: async () => {
|
|
205
214
|
callbacks.push('useMutation.onSettled');
|
|
206
215
|
},
|
|
207
|
-
});
|
|
216
|
+
}));
|
|
208
217
|
createEffect(() => {
|
|
209
218
|
const { mutateAsync } = mutation;
|
|
210
219
|
setActTimeout(async () => {
|
|
@@ -239,14 +248,15 @@ describe('useMutation', () => {
|
|
|
239
248
|
it('should be able to override the error callbacks when using mutateAsync', async () => {
|
|
240
249
|
const callbacks = [];
|
|
241
250
|
function Page() {
|
|
242
|
-
const mutation = createMutation(
|
|
251
|
+
const mutation = createMutation(() => ({
|
|
252
|
+
mutationFn: async (_text) => Promise.reject(new Error('oops')),
|
|
243
253
|
onError: async () => {
|
|
244
254
|
callbacks.push('useMutation.onError');
|
|
245
255
|
},
|
|
246
256
|
onSettled: async () => {
|
|
247
257
|
callbacks.push('useMutation.onSettled');
|
|
248
258
|
},
|
|
249
|
-
});
|
|
259
|
+
}));
|
|
250
260
|
createEffect(() => {
|
|
251
261
|
const { mutateAsync } = mutation;
|
|
252
262
|
setActTimeout(async () => {
|
|
@@ -261,7 +271,7 @@ describe('useMutation', () => {
|
|
|
261
271
|
});
|
|
262
272
|
}
|
|
263
273
|
catch (error) {
|
|
264
|
-
callbacks.push(`mutateAsync.error:${error}`);
|
|
274
|
+
callbacks.push(`mutateAsync.error:${error.message}`);
|
|
265
275
|
}
|
|
266
276
|
}, 10);
|
|
267
277
|
});
|
|
@@ -281,7 +291,7 @@ describe('useMutation', () => {
|
|
|
281
291
|
});
|
|
282
292
|
it('should be able to use mutation defaults', async () => {
|
|
283
293
|
const key = queryKey();
|
|
284
|
-
queryClient.setMutationDefaults(key
|
|
294
|
+
queryClient.setMutationDefaults(key, {
|
|
285
295
|
mutationFn: async (text) => {
|
|
286
296
|
await sleep(10);
|
|
287
297
|
return text;
|
|
@@ -289,7 +299,9 @@ describe('useMutation', () => {
|
|
|
289
299
|
});
|
|
290
300
|
const states = [];
|
|
291
301
|
function Page() {
|
|
292
|
-
const mutation = createMutation(
|
|
302
|
+
const mutation = createMutation(() => ({
|
|
303
|
+
mutationKey: key,
|
|
304
|
+
}));
|
|
293
305
|
createRenderEffect(() => {
|
|
294
306
|
states.push({ ...mutation });
|
|
295
307
|
});
|
|
@@ -306,20 +318,21 @@ describe('useMutation', () => {
|
|
|
306
318
|
</QueryClientProvider>));
|
|
307
319
|
await sleep(100);
|
|
308
320
|
expect(states.length).toBe(3);
|
|
309
|
-
expect(states[0]).toMatchObject({ data: undefined,
|
|
310
|
-
expect(states[1]).toMatchObject({ data: undefined,
|
|
311
|
-
expect(states[2]).toMatchObject({ data: 'todo',
|
|
321
|
+
expect(states[0]).toMatchObject({ data: undefined, isPending: false });
|
|
322
|
+
expect(states[1]).toMatchObject({ data: undefined, isPending: true });
|
|
323
|
+
expect(states[2]).toMatchObject({ data: 'todo', isPending: false });
|
|
312
324
|
});
|
|
313
325
|
it('should be able to retry a failed mutation', async () => {
|
|
314
326
|
let count = 0;
|
|
315
327
|
function Page() {
|
|
316
|
-
const mutation = createMutation((
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
328
|
+
const mutation = createMutation(() => ({
|
|
329
|
+
mutationFn: (_text) => {
|
|
330
|
+
count++;
|
|
331
|
+
return Promise.reject(new Error('oops'));
|
|
332
|
+
},
|
|
320
333
|
retry: 1,
|
|
321
334
|
retryDelay: 5,
|
|
322
|
-
});
|
|
335
|
+
}));
|
|
323
336
|
createEffect(() => {
|
|
324
337
|
const { mutate } = mutation;
|
|
325
338
|
setActTimeout(() => {
|
|
@@ -338,13 +351,14 @@ describe('useMutation', () => {
|
|
|
338
351
|
const onlineMock = mockNavigatorOnLine(false);
|
|
339
352
|
let count = 0;
|
|
340
353
|
function Page() {
|
|
341
|
-
const mutation = createMutation((
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
354
|
+
const mutation = createMutation(() => ({
|
|
355
|
+
mutationFn: (_text) => {
|
|
356
|
+
count++;
|
|
357
|
+
return Promise.reject(new Error('oops'));
|
|
358
|
+
},
|
|
345
359
|
retry: 1,
|
|
346
360
|
retryDelay: 5,
|
|
347
|
-
});
|
|
361
|
+
}));
|
|
348
362
|
return (<div>
|
|
349
363
|
<button onClick={() => mutation.mutate('todo')}>mutate</button>
|
|
350
364
|
<div>
|
|
@@ -360,7 +374,7 @@ describe('useMutation', () => {
|
|
|
360
374
|
});
|
|
361
375
|
fireEvent.click(screen.getByRole('button', { name: /mutate/i }));
|
|
362
376
|
await waitFor(() => {
|
|
363
|
-
expect(screen.getByText('error: null, status:
|
|
377
|
+
expect(screen.getByText('error: null, status: pending, isPaused: true')).toBeInTheDocument();
|
|
364
378
|
});
|
|
365
379
|
expect(count).toBe(0);
|
|
366
380
|
onlineMock.mockReturnValue(true);
|
|
@@ -377,13 +391,14 @@ describe('useMutation', () => {
|
|
|
377
391
|
const onMutate = jest.fn();
|
|
378
392
|
let count = 0;
|
|
379
393
|
function Page() {
|
|
380
|
-
const mutation = createMutation(
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
394
|
+
const mutation = createMutation(() => ({
|
|
395
|
+
mutationFn: async (_text) => {
|
|
396
|
+
count++;
|
|
397
|
+
await sleep(10);
|
|
398
|
+
return count;
|
|
399
|
+
},
|
|
385
400
|
onMutate,
|
|
386
|
-
});
|
|
401
|
+
}));
|
|
387
402
|
return (<div>
|
|
388
403
|
<button onClick={() => mutation.mutate('todo')}>mutate</button>
|
|
389
404
|
<div>
|
|
@@ -397,7 +412,7 @@ describe('useMutation', () => {
|
|
|
397
412
|
</QueryClientProvider>));
|
|
398
413
|
await screen.findByText('data: null, status: idle, isPaused: false');
|
|
399
414
|
fireEvent.click(screen.getByRole('button', { name: /mutate/i }));
|
|
400
|
-
await screen.findByText('data: null, status:
|
|
415
|
+
await screen.findByText('data: null, status: pending, isPaused: true');
|
|
401
416
|
expect(onMutate).toHaveBeenCalledTimes(1);
|
|
402
417
|
expect(onMutate).toHaveBeenCalledWith('todo');
|
|
403
418
|
onlineMock.mockReturnValue(true);
|
|
@@ -412,11 +427,13 @@ describe('useMutation', () => {
|
|
|
412
427
|
let count = 0;
|
|
413
428
|
const states = [];
|
|
414
429
|
function Page() {
|
|
415
|
-
const mutation = createMutation(
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
430
|
+
const mutation = createMutation(() => ({
|
|
431
|
+
mutationFn: async (_text) => {
|
|
432
|
+
count++;
|
|
433
|
+
await sleep(10);
|
|
434
|
+
return count;
|
|
435
|
+
},
|
|
436
|
+
}));
|
|
420
437
|
createRenderEffect(() => {
|
|
421
438
|
states.push(`${mutation.status}, ${mutation.isPaused}`);
|
|
422
439
|
});
|
|
@@ -433,10 +450,10 @@ describe('useMutation', () => {
|
|
|
433
450
|
</QueryClientProvider>));
|
|
434
451
|
await screen.findByText('data: null, status: idle, isPaused: false');
|
|
435
452
|
fireEvent.click(screen.getByRole('button', { name: /mutate/i }));
|
|
436
|
-
await screen.findByText('data: null, status:
|
|
437
|
-
// no intermediate '
|
|
453
|
+
await screen.findByText('data: null, status: pending, isPaused: true');
|
|
454
|
+
// no intermediate 'pending, false' state is expected because we don't start mutating!
|
|
438
455
|
expect(states[0]).toBe('idle, false');
|
|
439
|
-
expect(states[1]).toBe('
|
|
456
|
+
expect(states[1]).toBe('pending, true');
|
|
440
457
|
onlineMock.mockReturnValue(true);
|
|
441
458
|
window.dispatchEvent(new Event('online'));
|
|
442
459
|
await screen.findByText('data: 1, status: success, isPaused: false');
|
|
@@ -447,15 +464,18 @@ describe('useMutation', () => {
|
|
|
447
464
|
let count = 0;
|
|
448
465
|
const states = [];
|
|
449
466
|
function Page() {
|
|
450
|
-
const mutation = createMutation(
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
467
|
+
const mutation = createMutation(() => ({
|
|
468
|
+
mutationFn: async (_text) => {
|
|
469
|
+
await sleep(1);
|
|
470
|
+
count++;
|
|
471
|
+
return count > 1
|
|
472
|
+
? Promise.resolve('data')
|
|
473
|
+
: Promise.reject(new Error('oops'));
|
|
474
|
+
},
|
|
455
475
|
retry: 1,
|
|
456
476
|
retryDelay: 5,
|
|
457
477
|
networkMode: 'offlineFirst',
|
|
458
|
-
});
|
|
478
|
+
}));
|
|
459
479
|
createRenderEffect(() => {
|
|
460
480
|
states.push({ ...mutation });
|
|
461
481
|
});
|
|
@@ -473,41 +493,41 @@ describe('useMutation', () => {
|
|
|
473
493
|
await sleep(50);
|
|
474
494
|
expect(states.length).toBe(4);
|
|
475
495
|
expect(states[0]).toMatchObject({
|
|
476
|
-
|
|
496
|
+
isPending: false,
|
|
477
497
|
isPaused: false,
|
|
478
498
|
failureCount: 0,
|
|
479
499
|
failureReason: null,
|
|
480
500
|
});
|
|
481
501
|
expect(states[1]).toMatchObject({
|
|
482
|
-
|
|
502
|
+
isPending: true,
|
|
483
503
|
isPaused: false,
|
|
484
504
|
failureCount: 0,
|
|
485
505
|
failureReason: null,
|
|
486
506
|
});
|
|
487
507
|
expect(states[2]).toMatchObject({
|
|
488
|
-
|
|
508
|
+
isPending: true,
|
|
489
509
|
isPaused: false,
|
|
490
510
|
failureCount: 1,
|
|
491
|
-
failureReason: 'oops',
|
|
511
|
+
failureReason: new Error('oops'),
|
|
492
512
|
});
|
|
493
513
|
expect(states[3]).toMatchObject({
|
|
494
|
-
|
|
514
|
+
isPending: true,
|
|
495
515
|
isPaused: true,
|
|
496
516
|
failureCount: 1,
|
|
497
|
-
failureReason: 'oops',
|
|
517
|
+
failureReason: new Error('oops'),
|
|
498
518
|
});
|
|
499
519
|
onlineMock.mockReturnValue(true);
|
|
500
520
|
window.dispatchEvent(new Event('online'));
|
|
501
521
|
await sleep(50);
|
|
502
522
|
expect(states.length).toBe(6);
|
|
503
523
|
expect(states[4]).toMatchObject({
|
|
504
|
-
|
|
524
|
+
isPending: true,
|
|
505
525
|
isPaused: false,
|
|
506
526
|
failureCount: 1,
|
|
507
|
-
failureReason: 'oops',
|
|
527
|
+
failureReason: new Error('oops'),
|
|
508
528
|
});
|
|
509
529
|
expect(states[5]).toMatchObject({
|
|
510
|
-
|
|
530
|
+
isPending: false,
|
|
511
531
|
isPaused: false,
|
|
512
532
|
failureCount: 0,
|
|
513
533
|
failureReason: null,
|
|
@@ -517,7 +537,7 @@ describe('useMutation', () => {
|
|
|
517
537
|
});
|
|
518
538
|
it('should not change state if unmounted', async () => {
|
|
519
539
|
function Mutates() {
|
|
520
|
-
const mutation = createMutation(() => sleep(10));
|
|
540
|
+
const mutation = createMutation(() => ({ mutationFn: () => sleep(10) }));
|
|
521
541
|
return <button onClick={() => mutation.mutate()}>mutate</button>;
|
|
522
542
|
}
|
|
523
543
|
function Page() {
|
|
@@ -533,13 +553,16 @@ describe('useMutation', () => {
|
|
|
533
553
|
fireEvent.click(screen.getByText('mutate'));
|
|
534
554
|
fireEvent.click(screen.getByText('unmount'));
|
|
535
555
|
});
|
|
536
|
-
it('should be able to throw an error when
|
|
556
|
+
it('should be able to throw an error when throwErrors is set to true', async () => {
|
|
537
557
|
function Page() {
|
|
538
|
-
const mutation = createMutation(() => {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
558
|
+
const mutation = createMutation(() => ({
|
|
559
|
+
mutationFn: () => {
|
|
560
|
+
const err = new Error('Expected mock error. All is well!');
|
|
561
|
+
err.stack = '';
|
|
562
|
+
return Promise.reject(err);
|
|
563
|
+
},
|
|
564
|
+
throwErrors: true,
|
|
565
|
+
}));
|
|
543
566
|
return (<div>
|
|
544
567
|
<button onClick={() => mutation.mutate()}>mutate</button>
|
|
545
568
|
</div>);
|
|
@@ -556,19 +579,20 @@ describe('useMutation', () => {
|
|
|
556
579
|
expect(screen.queryByText('error')).not.toBeNull();
|
|
557
580
|
});
|
|
558
581
|
});
|
|
559
|
-
it('should be able to throw an error when
|
|
582
|
+
it('should be able to throw an error when throwErrors is a function that returns true', async () => {
|
|
560
583
|
let boundary = false;
|
|
561
584
|
function Page() {
|
|
562
|
-
const mutation = createMutation(() => {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
585
|
+
const mutation = createMutation(() => ({
|
|
586
|
+
mutationFn: () => {
|
|
587
|
+
const err = new Error('mock error');
|
|
588
|
+
err.stack = '';
|
|
589
|
+
return Promise.reject(err);
|
|
590
|
+
},
|
|
591
|
+
throwErrors: () => {
|
|
568
592
|
boundary = !boundary;
|
|
569
593
|
return !boundary;
|
|
570
594
|
},
|
|
571
|
-
});
|
|
595
|
+
}));
|
|
572
596
|
return (<div>
|
|
573
597
|
<button onClick={() => mutation.mutate()}>mutate</button>
|
|
574
598
|
{mutation.error && mutation.error.message}
|
|
@@ -608,14 +632,16 @@ describe('useMutation', () => {
|
|
|
608
632
|
const metaSuccessMessage = 'mutation succeeded';
|
|
609
633
|
const metaErrorMessage = 'mutation failed';
|
|
610
634
|
function Page() {
|
|
611
|
-
const mutationSucceed = createMutation(
|
|
635
|
+
const mutationSucceed = createMutation(() => ({
|
|
636
|
+
mutationFn: async () => '',
|
|
612
637
|
meta: { metaSuccessMessage },
|
|
613
|
-
});
|
|
614
|
-
const mutationError = createMutation(
|
|
615
|
-
|
|
616
|
-
|
|
638
|
+
}));
|
|
639
|
+
const mutationError = createMutation(() => ({
|
|
640
|
+
mutationFn: async () => {
|
|
641
|
+
throw new Error('');
|
|
642
|
+
},
|
|
617
643
|
meta: { metaErrorMessage },
|
|
618
|
-
});
|
|
644
|
+
}));
|
|
619
645
|
return (<div>
|
|
620
646
|
<button onClick={() => mutationSucceed.mutate()}>succeed</button>
|
|
621
647
|
<button onClick={() => mutationError.mutate()}>error</button>
|
|
@@ -652,16 +678,17 @@ describe('useMutation', () => {
|
|
|
652
678
|
</div>);
|
|
653
679
|
}
|
|
654
680
|
function Component() {
|
|
655
|
-
const mutation = createMutation(
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
681
|
+
const mutation = createMutation(() => ({
|
|
682
|
+
mutationFn: async (_text) => {
|
|
683
|
+
count++;
|
|
684
|
+
await sleep(10);
|
|
685
|
+
return count;
|
|
686
|
+
},
|
|
687
|
+
mutationKey: mutationKey,
|
|
688
|
+
gcTime: 0,
|
|
662
689
|
onSuccess,
|
|
663
690
|
onSettled,
|
|
664
|
-
});
|
|
691
|
+
}));
|
|
665
692
|
return (<div>
|
|
666
693
|
<button onClick={() => mutation.mutate('todo', {
|
|
667
694
|
onSuccess: onSuccessMutate,
|
|
@@ -682,7 +709,7 @@ describe('useMutation', () => {
|
|
|
682
709
|
fireEvent.click(screen.getByRole('button', { name: /mutate/i }));
|
|
683
710
|
fireEvent.click(screen.getByRole('button', { name: /hide/i }));
|
|
684
711
|
await waitFor(() => {
|
|
685
|
-
expect(queryClient.getMutationCache().findAll({ mutationKey: mutationKey
|
|
712
|
+
expect(queryClient.getMutationCache().findAll({ mutationKey: mutationKey })).toHaveLength(0);
|
|
686
713
|
});
|
|
687
714
|
expect(count).toBe(1);
|
|
688
715
|
expect(onSuccess).toHaveBeenCalledTimes(1);
|
|
@@ -690,49 +717,6 @@ describe('useMutation', () => {
|
|
|
690
717
|
expect(onSuccessMutate).toHaveBeenCalledTimes(0);
|
|
691
718
|
expect(onSettledMutate).toHaveBeenCalledTimes(0);
|
|
692
719
|
});
|
|
693
|
-
describe('with custom context', () => {
|
|
694
|
-
it('should be able to reset `data`', async () => {
|
|
695
|
-
const context = createContext(undefined);
|
|
696
|
-
function Page() {
|
|
697
|
-
const mutation = createMutation(() => Promise.resolve('mutation'), {
|
|
698
|
-
context,
|
|
699
|
-
});
|
|
700
|
-
return (<div>
|
|
701
|
-
<h1>{mutation.data ?? 'empty'}</h1>
|
|
702
|
-
<button onClick={() => mutation.reset()}>reset</button>
|
|
703
|
-
<button onClick={() => mutation.mutate()}>mutate</button>
|
|
704
|
-
</div>);
|
|
705
|
-
}
|
|
706
|
-
render(() => (<QueryClientProvider client={queryClient} context={context}>
|
|
707
|
-
<Page />
|
|
708
|
-
</QueryClientProvider>));
|
|
709
|
-
expect(screen.getByRole('heading').textContent).toBe('empty');
|
|
710
|
-
fireEvent.click(screen.getByRole('button', { name: /mutate/i }));
|
|
711
|
-
await waitFor(() => {
|
|
712
|
-
expect(screen.getByRole('heading').textContent).toBe('mutation');
|
|
713
|
-
});
|
|
714
|
-
fireEvent.click(screen.getByRole('button', { name: /reset/i }));
|
|
715
|
-
await waitFor(() => {
|
|
716
|
-
expect(screen.getByRole('heading').textContent).toBe('empty');
|
|
717
|
-
});
|
|
718
|
-
});
|
|
719
|
-
it('should throw if the context is not passed to useMutation', async () => {
|
|
720
|
-
const context = createContext(undefined);
|
|
721
|
-
function Page() {
|
|
722
|
-
const { data = '' } = createMutation(() => Promise.resolve('mutation'));
|
|
723
|
-
return (<div>
|
|
724
|
-
<h1 data-testid="title">{data}</h1>
|
|
725
|
-
</div>);
|
|
726
|
-
}
|
|
727
|
-
render(() => (<QueryClientProvider client={queryClient} context={context}>
|
|
728
|
-
<ErrorBoundary fallback={() => <div>error boundary</div>}>
|
|
729
|
-
<Page />
|
|
730
|
-
</ErrorBoundary>
|
|
731
|
-
,
|
|
732
|
-
</QueryClientProvider>));
|
|
733
|
-
await waitFor(() => screen.getByText('error boundary'));
|
|
734
|
-
});
|
|
735
|
-
});
|
|
736
720
|
it('should call mutate callbacks only for the last observer', async () => {
|
|
737
721
|
const onSuccess = jest.fn();
|
|
738
722
|
const onSuccessMutate = jest.fn();
|
|
@@ -740,14 +724,15 @@ describe('useMutation', () => {
|
|
|
740
724
|
const onSettledMutate = jest.fn();
|
|
741
725
|
let count = 0;
|
|
742
726
|
function Page() {
|
|
743
|
-
const mutation = createMutation(
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
727
|
+
const mutation = createMutation(() => ({
|
|
728
|
+
mutationFn: async (_text) => {
|
|
729
|
+
count++;
|
|
730
|
+
await sleep(10);
|
|
731
|
+
return `result${count}`;
|
|
732
|
+
},
|
|
748
733
|
onSuccess,
|
|
749
734
|
onSettled,
|
|
750
|
-
});
|
|
735
|
+
}));
|
|
751
736
|
return (<div>
|
|
752
737
|
<button onClick={() => mutation.mutate('todo', {
|
|
753
738
|
onSuccess: onSuccessMutate,
|
|
@@ -779,13 +764,14 @@ describe('useMutation', () => {
|
|
|
779
764
|
const error = new Error('error from onSuccess');
|
|
780
765
|
const onError = jest.fn();
|
|
781
766
|
function Page() {
|
|
782
|
-
const mutation = createMutation(
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
767
|
+
const mutation = createMutation(() => ({
|
|
768
|
+
mutationFn: async (_text) => {
|
|
769
|
+
await sleep(10);
|
|
770
|
+
return 'result';
|
|
771
|
+
},
|
|
786
772
|
onSuccess: () => Promise.reject(error),
|
|
787
773
|
onError,
|
|
788
|
-
});
|
|
774
|
+
}));
|
|
789
775
|
return (<div>
|
|
790
776
|
<button onClick={() => mutation.mutate('todo')}>mutate</button>
|
|
791
777
|
<div>status: {mutation.status}</div>
|
|
@@ -803,12 +789,13 @@ describe('useMutation', () => {
|
|
|
803
789
|
const error = new Error('error from onError');
|
|
804
790
|
const mutateFnError = new Error('mutateFnError');
|
|
805
791
|
function Page() {
|
|
806
|
-
const mutation = createMutation(
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
792
|
+
const mutation = createMutation(() => ({
|
|
793
|
+
mutationFn: async (_text) => {
|
|
794
|
+
await sleep(10);
|
|
795
|
+
throw mutateFnError;
|
|
796
|
+
},
|
|
810
797
|
onError: () => Promise.reject(error),
|
|
811
|
-
});
|
|
798
|
+
}));
|
|
812
799
|
return (<div>
|
|
813
800
|
<button onClick={() => mutation.mutate('todo')}>mutate</button>
|
|
814
801
|
<div>
|
|
@@ -830,13 +817,14 @@ describe('useMutation', () => {
|
|
|
830
817
|
const mutateFnError = new Error('mutateFnError');
|
|
831
818
|
const onError = jest.fn();
|
|
832
819
|
function Page() {
|
|
833
|
-
const mutation = createMutation(
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
820
|
+
const mutation = createMutation(() => ({
|
|
821
|
+
mutationFn: async (_text) => {
|
|
822
|
+
await sleep(10);
|
|
823
|
+
throw mutateFnError;
|
|
824
|
+
},
|
|
837
825
|
onSettled: () => Promise.reject(error),
|
|
838
826
|
onError,
|
|
839
|
-
});
|
|
827
|
+
}));
|
|
840
828
|
return (<div>
|
|
841
829
|
<button onClick={() => mutation.mutate('todo')}>mutate</button>
|
|
842
830
|
<div>
|
|
@@ -854,4 +842,25 @@ describe('useMutation', () => {
|
|
|
854
842
|
await screen.findByText('error: mutateFnError, status: error');
|
|
855
843
|
expect(onError).toHaveBeenCalledWith(mutateFnError, 'todo', undefined);
|
|
856
844
|
});
|
|
845
|
+
it('should use provided custom queryClient', async () => {
|
|
846
|
+
function Page() {
|
|
847
|
+
const mutation = createMutation(() => ({
|
|
848
|
+
mutationFn: async (text) => {
|
|
849
|
+
return Promise.resolve(text);
|
|
850
|
+
},
|
|
851
|
+
}), () => queryClient);
|
|
852
|
+
return (<div>
|
|
853
|
+
<button onClick={() => mutation.mutate('custom client')}>
|
|
854
|
+
mutate
|
|
855
|
+
</button>
|
|
856
|
+
<div>
|
|
857
|
+
data: {mutation.data ?? 'null'}, status: {mutation.status}
|
|
858
|
+
</div>
|
|
859
|
+
</div>);
|
|
860
|
+
}
|
|
861
|
+
render(() => <Page></Page>);
|
|
862
|
+
await screen.findByText('data: null, status: idle');
|
|
863
|
+
fireEvent.click(screen.getByRole('button', { name: /mutate/i }));
|
|
864
|
+
await screen.findByText('data: custom client, status: success');
|
|
865
|
+
});
|
|
857
866
|
});
|