@tanstack/solid-query 5.0.0-alpha.5 → 5.0.0-alpha.50
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 +90 -30
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.js +91 -33
- package/build/esm/index.js.map +1 -1
- package/build/source/QueryClient.js +6 -0
- package/build/source/__tests__/QueryClientProvider.test.jsx +2 -3
- package/build/source/__tests__/createInfiniteQuery.test.jsx +58 -13
- package/build/source/__tests__/createMutation.test.jsx +5 -5
- package/build/source/__tests__/createQueries.test.jsx +6 -77
- package/build/source/__tests__/createQuery.test.jsx +51 -261
- package/build/source/__tests__/createQuery.types.test.jsx +19 -1
- package/build/source/__tests__/suspense.test.jsx +7 -69
- package/build/source/__tests__/transition.test.jsx +1 -1
- package/build/source/__tests__/useIsFetching.test.jsx +1 -1
- package/build/source/__tests__/useIsMutating.test.jsx +5 -7
- package/build/source/__tests__/utils.jsx +1 -1
- package/build/source/createBaseQuery.js +49 -23
- package/build/source/createMutation.js +1 -1
- package/build/source/createQueries.js +13 -7
- package/build/source/createQuery.js +3 -0
- package/build/source/index.js +2 -1
- package/build/types/QueryClient.d.ts +30 -0
- package/build/types/QueryClient.d.ts.map +1 -0
- package/build/types/QueryClientProvider.d.ts +3 -2
- package/build/types/QueryClientProvider.d.ts.map +1 -0
- package/build/types/__tests__/QueryClientProvider.test.d.ts +1 -0
- package/build/types/__tests__/QueryClientProvider.test.d.ts.map +1 -0
- package/build/types/__tests__/createInfiniteQuery.test.d.ts +1 -0
- package/build/types/__tests__/createInfiniteQuery.test.d.ts.map +1 -0
- package/build/types/__tests__/createMutation.test.d.ts +1 -0
- package/build/types/__tests__/createMutation.test.d.ts.map +1 -0
- package/build/types/__tests__/createQueries.test.d.ts +1 -0
- package/build/types/__tests__/createQueries.test.d.ts.map +1 -0
- package/build/types/__tests__/createQuery.test.d.ts +1 -0
- package/build/types/__tests__/createQuery.test.d.ts.map +1 -0
- package/build/types/__tests__/createQuery.types.test.d.ts +3 -2
- package/build/types/__tests__/createQuery.types.test.d.ts.map +1 -0
- package/build/types/__tests__/suspense.test.d.ts +1 -0
- package/build/types/__tests__/suspense.test.d.ts.map +1 -0
- package/build/types/__tests__/transition.test.d.ts +1 -0
- package/build/types/__tests__/transition.test.d.ts.map +1 -0
- package/build/types/__tests__/useIsFetching.test.d.ts +1 -0
- package/build/types/__tests__/useIsFetching.test.d.ts.map +1 -0
- package/build/types/__tests__/useIsMutating.test.d.ts +1 -0
- package/build/types/__tests__/useIsMutating.test.d.ts.map +1 -0
- package/build/types/__tests__/utils.d.ts +4 -3
- package/build/types/__tests__/utils.d.ts.map +1 -0
- package/build/types/createBaseQuery.d.ts +3 -1
- package/build/types/createBaseQuery.d.ts.map +1 -0
- package/build/types/createInfiniteQuery.d.ts +3 -1
- package/build/types/createInfiniteQuery.d.ts.map +1 -0
- package/build/types/createMutation.d.ts +3 -1
- package/build/types/createMutation.d.ts.map +1 -0
- package/build/types/createQueries.d.ts +12 -9
- package/build/types/createQueries.d.ts.map +1 -0
- package/build/types/createQuery.d.ts +7 -3
- package/build/types/createQuery.d.ts.map +1 -0
- package/build/types/index.d.ts +4 -1
- package/build/types/index.d.ts.map +1 -0
- package/build/types/setBatchUpdatesFn.d.ts +1 -0
- package/build/types/setBatchUpdatesFn.d.ts.map +1 -0
- package/build/types/types.d.ts +17 -15
- package/build/types/types.d.ts.map +1 -0
- package/build/types/useIsFetching.d.ts +3 -1
- package/build/types/useIsFetching.d.ts.map +1 -0
- package/build/types/useIsMutating.d.ts +3 -1
- package/build/types/useIsMutating.d.ts.map +1 -0
- package/build/types/utils.d.ts +1 -0
- package/build/types/utils.d.ts.map +1 -0
- package/package.json +12 -11
- package/src/QueryClient.ts +84 -0
- package/src/QueryClientProvider.tsx +1 -1
- package/src/__tests__/QueryClientProvider.test.tsx +2 -3
- package/src/__tests__/createInfiniteQuery.test.tsx +83 -19
- package/src/__tests__/createMutation.test.tsx +5 -5
- package/src/__tests__/createQueries.test.tsx +6 -78
- package/src/__tests__/createQuery.test.tsx +66 -334
- package/src/__tests__/createQuery.types.test.tsx +21 -1
- package/src/__tests__/suspense.test.tsx +7 -90
- package/src/__tests__/transition.test.tsx +1 -1
- package/src/__tests__/useIsFetching.test.tsx +1 -1
- package/src/__tests__/useIsMutating.test.tsx +5 -7
- package/src/__tests__/utils.tsx +1 -1
- package/src/createBaseQuery.ts +73 -28
- package/src/createInfiniteQuery.ts +1 -1
- package/src/createMutation.ts +3 -2
- package/src/createQueries.ts +32 -14
- package/src/createQuery.ts +24 -1
- package/src/index.ts +8 -1
- package/src/types.ts +4 -2
- package/src/useIsFetching.ts +2 -1
- package/src/useIsMutating.ts +2 -1
- package/build/umd/index.js +0 -2
- package/build/umd/index.js.map +0 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import '@testing-library/jest-dom';
|
|
2
2
|
import { createEffect, createMemo, createRenderEffect, createSignal, ErrorBoundary, Match, on, Switch, } from 'solid-js';
|
|
3
|
-
import { fireEvent, render, screen, waitFor } from '
|
|
3
|
+
import { fireEvent, render, screen, waitFor } from '@solidjs/testing-library';
|
|
4
4
|
import { createQuery, QueryCache, QueryClientProvider, keepPreviousData, } from '..';
|
|
5
5
|
import { Blink, createQueryClient, expectType, mockNavigatorOnLine, mockVisibilityState, queryKey, setActTimeout, sleep, } from './utils';
|
|
6
6
|
import { vi } from 'vitest';
|
|
7
|
+
import { reconcile } from 'solid-js/store';
|
|
7
8
|
describe('createQuery', () => {
|
|
8
9
|
const queryCache = new QueryCache();
|
|
9
10
|
const queryClient = createQueryClient({ queryCache });
|
|
@@ -41,20 +42,16 @@ describe('createQuery', () => {
|
|
|
41
42
|
createQuery(() => ({
|
|
42
43
|
queryKey: [key],
|
|
43
44
|
queryFn: async () => true,
|
|
44
|
-
onSuccess: (data) => expectType(data),
|
|
45
|
-
onSettled: (data) => expectType(data),
|
|
46
45
|
}));
|
|
47
46
|
// it should be possible to specify a union type as result type
|
|
48
47
|
const unionTypeSync = createQuery(() => ({
|
|
49
48
|
queryKey: key,
|
|
50
49
|
queryFn: () => (Math.random() > 0.5 ? 'a' : 'b'),
|
|
51
|
-
onSuccess: (data) => expectType(data),
|
|
52
50
|
}));
|
|
53
51
|
expectType(unionTypeSync.data);
|
|
54
52
|
const unionTypeAsync = createQuery(() => ({
|
|
55
53
|
queryKey: key,
|
|
56
54
|
queryFn: () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'),
|
|
57
|
-
onSuccess: (data) => expectType(data),
|
|
58
55
|
}));
|
|
59
56
|
expectType(unionTypeAsync.data);
|
|
60
57
|
// should error when the query function result does not match with the specified type
|
|
@@ -359,189 +356,6 @@ describe('createQuery', () => {
|
|
|
359
356
|
isFetchedAfterMount: true,
|
|
360
357
|
});
|
|
361
358
|
});
|
|
362
|
-
it('should call onSuccess after a query has been fetched', async () => {
|
|
363
|
-
const key = queryKey();
|
|
364
|
-
const states = [];
|
|
365
|
-
const onSuccess = vi.fn();
|
|
366
|
-
function Page() {
|
|
367
|
-
const state = createQuery(() => ({
|
|
368
|
-
queryKey: key,
|
|
369
|
-
queryFn: async () => {
|
|
370
|
-
await sleep(10);
|
|
371
|
-
return 'data';
|
|
372
|
-
},
|
|
373
|
-
onSuccess,
|
|
374
|
-
}));
|
|
375
|
-
createRenderEffect(() => {
|
|
376
|
-
states.push({ ...state });
|
|
377
|
-
});
|
|
378
|
-
return <div>data: {state.data}</div>;
|
|
379
|
-
}
|
|
380
|
-
render(() => (<QueryClientProvider client={queryClient}>
|
|
381
|
-
<Page />
|
|
382
|
-
</QueryClientProvider>));
|
|
383
|
-
await screen.findByText('data: data');
|
|
384
|
-
expect(states.length).toBe(2);
|
|
385
|
-
expect(onSuccess).toHaveBeenCalledTimes(1);
|
|
386
|
-
expect(onSuccess).toHaveBeenCalledWith('data');
|
|
387
|
-
});
|
|
388
|
-
it('should call onSuccess after a disabled query has been fetched', async () => {
|
|
389
|
-
const key = queryKey();
|
|
390
|
-
const states = [];
|
|
391
|
-
const onSuccess = vi.fn();
|
|
392
|
-
function Page() {
|
|
393
|
-
const state = createQuery(() => ({
|
|
394
|
-
queryKey: key,
|
|
395
|
-
queryFn: () => 'data',
|
|
396
|
-
enabled: false,
|
|
397
|
-
onSuccess,
|
|
398
|
-
}));
|
|
399
|
-
createRenderEffect(() => {
|
|
400
|
-
states.push({ ...state });
|
|
401
|
-
});
|
|
402
|
-
createEffect(() => {
|
|
403
|
-
const refetch = state.refetch;
|
|
404
|
-
setActTimeout(() => {
|
|
405
|
-
refetch();
|
|
406
|
-
}, 10);
|
|
407
|
-
});
|
|
408
|
-
return null;
|
|
409
|
-
}
|
|
410
|
-
render(() => (<QueryClientProvider client={queryClient}>
|
|
411
|
-
<Page />
|
|
412
|
-
</QueryClientProvider>));
|
|
413
|
-
await sleep(50);
|
|
414
|
-
expect(onSuccess).toHaveBeenCalledTimes(1);
|
|
415
|
-
expect(onSuccess).toHaveBeenCalledWith('data');
|
|
416
|
-
});
|
|
417
|
-
it('should not call onSuccess if a component has unmounted', async () => {
|
|
418
|
-
const key = queryKey();
|
|
419
|
-
const states = [];
|
|
420
|
-
const onSuccess = vi.fn();
|
|
421
|
-
function Page() {
|
|
422
|
-
const [show, setShow] = createSignal(true);
|
|
423
|
-
createEffect(() => {
|
|
424
|
-
setShow(false);
|
|
425
|
-
});
|
|
426
|
-
return <>{show() && <Component />}</>;
|
|
427
|
-
}
|
|
428
|
-
function Component() {
|
|
429
|
-
const state = createQuery(() => ({
|
|
430
|
-
queryKey: key,
|
|
431
|
-
queryFn: async () => {
|
|
432
|
-
await sleep(10);
|
|
433
|
-
return 'data';
|
|
434
|
-
},
|
|
435
|
-
onSuccess,
|
|
436
|
-
}));
|
|
437
|
-
createRenderEffect(() => {
|
|
438
|
-
states.push({ ...state });
|
|
439
|
-
});
|
|
440
|
-
return null;
|
|
441
|
-
}
|
|
442
|
-
render(() => (<QueryClientProvider client={queryClient}>
|
|
443
|
-
<Page />
|
|
444
|
-
</QueryClientProvider>));
|
|
445
|
-
await sleep(50);
|
|
446
|
-
expect(states.length).toBe(1);
|
|
447
|
-
expect(onSuccess).toHaveBeenCalledTimes(0);
|
|
448
|
-
});
|
|
449
|
-
it('should call onError after a query has been fetched with an error', async () => {
|
|
450
|
-
const key = queryKey();
|
|
451
|
-
const states = [];
|
|
452
|
-
const onError = vi.fn();
|
|
453
|
-
function Page() {
|
|
454
|
-
const state = createQuery(() => ({
|
|
455
|
-
queryKey: key,
|
|
456
|
-
queryFn: () => Promise.reject(new Error('error')),
|
|
457
|
-
retry: false,
|
|
458
|
-
onError,
|
|
459
|
-
}));
|
|
460
|
-
createRenderEffect(() => {
|
|
461
|
-
states.push({ ...state });
|
|
462
|
-
});
|
|
463
|
-
return null;
|
|
464
|
-
}
|
|
465
|
-
render(() => (<QueryClientProvider client={queryClient}>
|
|
466
|
-
<Page />
|
|
467
|
-
</QueryClientProvider>));
|
|
468
|
-
await sleep(10);
|
|
469
|
-
expect(states.length).toBe(2);
|
|
470
|
-
expect(onError).toHaveBeenCalledTimes(1);
|
|
471
|
-
expect(onError).toHaveBeenCalledWith(new Error('error'));
|
|
472
|
-
});
|
|
473
|
-
it('should not call onError when receiving a CancelledError', async () => {
|
|
474
|
-
const key = queryKey();
|
|
475
|
-
const onError = vi.fn();
|
|
476
|
-
function Page() {
|
|
477
|
-
const state = createQuery(() => ({
|
|
478
|
-
queryKey: key,
|
|
479
|
-
queryFn: async () => {
|
|
480
|
-
await sleep(10);
|
|
481
|
-
return 23;
|
|
482
|
-
},
|
|
483
|
-
onError,
|
|
484
|
-
}));
|
|
485
|
-
return (<span>
|
|
486
|
-
status: {state.status}, fetchStatus: {state.fetchStatus}
|
|
487
|
-
</span>);
|
|
488
|
-
}
|
|
489
|
-
render(() => (<QueryClientProvider client={queryClient}>
|
|
490
|
-
<Page />
|
|
491
|
-
</QueryClientProvider>));
|
|
492
|
-
await sleep(5);
|
|
493
|
-
await queryClient.cancelQueries({ queryKey: key });
|
|
494
|
-
// query cancellation will reset the query to it's initial state
|
|
495
|
-
await waitFor(() => screen.getByText('status: pending, fetchStatus: idle'));
|
|
496
|
-
expect(onError).not.toHaveBeenCalled();
|
|
497
|
-
});
|
|
498
|
-
it('should call onSettled after a query has been fetched', async () => {
|
|
499
|
-
const key = queryKey();
|
|
500
|
-
const states = [];
|
|
501
|
-
const onSettled = vi.fn();
|
|
502
|
-
function Page() {
|
|
503
|
-
const state = createQuery(() => ({
|
|
504
|
-
queryKey: key,
|
|
505
|
-
queryFn: () => 'data',
|
|
506
|
-
onSettled,
|
|
507
|
-
}));
|
|
508
|
-
createRenderEffect(() => {
|
|
509
|
-
states.push({ ...state });
|
|
510
|
-
});
|
|
511
|
-
return null;
|
|
512
|
-
}
|
|
513
|
-
render(() => (<QueryClientProvider client={queryClient}>
|
|
514
|
-
<Page />
|
|
515
|
-
</QueryClientProvider>));
|
|
516
|
-
await sleep(10);
|
|
517
|
-
expect(states.length).toBe(2);
|
|
518
|
-
expect(onSettled).toHaveBeenCalledTimes(1);
|
|
519
|
-
expect(onSettled).toHaveBeenCalledWith('data', null);
|
|
520
|
-
});
|
|
521
|
-
it('should call onSettled after a query has been fetched with an error', async () => {
|
|
522
|
-
const key = queryKey();
|
|
523
|
-
const states = [];
|
|
524
|
-
const onSettled = vi.fn();
|
|
525
|
-
function Page() {
|
|
526
|
-
const state = createQuery(() => ({
|
|
527
|
-
queryKey: key,
|
|
528
|
-
queryFn: () => Promise.reject('error'),
|
|
529
|
-
retry: false,
|
|
530
|
-
onSettled,
|
|
531
|
-
}));
|
|
532
|
-
createRenderEffect(() => {
|
|
533
|
-
states.push({ ...state });
|
|
534
|
-
});
|
|
535
|
-
return null;
|
|
536
|
-
}
|
|
537
|
-
render(() => (<QueryClientProvider client={queryClient}>
|
|
538
|
-
<Page />
|
|
539
|
-
</QueryClientProvider>));
|
|
540
|
-
await sleep(10);
|
|
541
|
-
expect(states.length).toBe(2);
|
|
542
|
-
expect(onSettled).toHaveBeenCalledTimes(1);
|
|
543
|
-
expect(onSettled).toHaveBeenCalledWith(undefined, 'error');
|
|
544
|
-
});
|
|
545
359
|
it('should not cancel an ongoing fetch when refetch is called with cancelRefetch=false if we have data already', async () => {
|
|
546
360
|
const key = queryKey();
|
|
547
361
|
let fetchCount = 0;
|
|
@@ -965,7 +779,6 @@ describe('createQuery', () => {
|
|
|
965
779
|
count++;
|
|
966
780
|
return count === 1 ? result1 : result2;
|
|
967
781
|
},
|
|
968
|
-
notifyOnChangeProps: 'all',
|
|
969
782
|
}));
|
|
970
783
|
createRenderEffect(() => {
|
|
971
784
|
states.push({ ...state });
|
|
@@ -992,9 +805,8 @@ describe('createQuery', () => {
|
|
|
992
805
|
const newTodo2 = newTodos?.[1];
|
|
993
806
|
expect(todos).toEqual(result1);
|
|
994
807
|
expect(newTodos).toEqual(result2);
|
|
995
|
-
expect(newTodos).not.toBe(todos);
|
|
996
808
|
expect(newTodo1).toBe(todo1);
|
|
997
|
-
expect(newTodo2).
|
|
809
|
+
expect(newTodo2).toBe(todo2);
|
|
998
810
|
return null;
|
|
999
811
|
});
|
|
1000
812
|
it('should use query function from hook when the existing query does not have a query function', async () => {
|
|
@@ -1752,45 +1564,6 @@ describe('createQuery', () => {
|
|
|
1752
1564
|
// There wiil only be one pass
|
|
1753
1565
|
expect(renders).toBe(1);
|
|
1754
1566
|
});
|
|
1755
|
-
it('should batch re-renders including hook callbacks', async () => {
|
|
1756
|
-
const key = queryKey();
|
|
1757
|
-
let renders = 0;
|
|
1758
|
-
let callbackCount = 0;
|
|
1759
|
-
const queryFn = async () => {
|
|
1760
|
-
await sleep(10);
|
|
1761
|
-
return 'data';
|
|
1762
|
-
};
|
|
1763
|
-
function Page() {
|
|
1764
|
-
const [count, setCount] = createSignal(0);
|
|
1765
|
-
createQuery(() => ({
|
|
1766
|
-
queryKey: key,
|
|
1767
|
-
queryFn,
|
|
1768
|
-
onSuccess: () => {
|
|
1769
|
-
setCount((x) => x + 1);
|
|
1770
|
-
},
|
|
1771
|
-
}));
|
|
1772
|
-
createQuery(() => ({
|
|
1773
|
-
queryKey: key,
|
|
1774
|
-
queryFn,
|
|
1775
|
-
onSuccess: () => {
|
|
1776
|
-
setCount((x) => x + 1);
|
|
1777
|
-
},
|
|
1778
|
-
}));
|
|
1779
|
-
createEffect(() => {
|
|
1780
|
-
renders++;
|
|
1781
|
-
callbackCount = count();
|
|
1782
|
-
});
|
|
1783
|
-
return <div>count: {count()}</div>;
|
|
1784
|
-
}
|
|
1785
|
-
render(() => (<QueryClientProvider client={queryClient}>
|
|
1786
|
-
<Page />
|
|
1787
|
-
</QueryClientProvider>));
|
|
1788
|
-
await waitFor(() => screen.getByText('count: 2'));
|
|
1789
|
-
// Should be 3 instead of 5
|
|
1790
|
-
expect(renders).toBe(3);
|
|
1791
|
-
// Both callbacks should have been executed
|
|
1792
|
-
expect(callbackCount).toBe(2);
|
|
1793
|
-
});
|
|
1794
1567
|
it('should render latest data even if react has discarded certain renders', async () => {
|
|
1795
1568
|
const key = queryKey();
|
|
1796
1569
|
function Page() {
|
|
@@ -2144,14 +1917,14 @@ describe('createQuery', () => {
|
|
|
2144
1917
|
await waitFor(() => screen.getByText('error'));
|
|
2145
1918
|
await waitFor(() => screen.getByText('Error test jaylen'));
|
|
2146
1919
|
});
|
|
2147
|
-
it('should throw error if queryFn throws and
|
|
1920
|
+
it('should throw error if queryFn throws and throwOnError is in use', async () => {
|
|
2148
1921
|
const key = queryKey();
|
|
2149
1922
|
function Page() {
|
|
2150
1923
|
const state = createQuery(() => ({
|
|
2151
1924
|
queryKey: key,
|
|
2152
1925
|
queryFn: () => Promise.reject(new Error('Error test jaylen')),
|
|
2153
1926
|
retry: false,
|
|
2154
|
-
|
|
1927
|
+
throwOnError: true,
|
|
2155
1928
|
}));
|
|
2156
1929
|
return (<div>
|
|
2157
1930
|
<h1>{state.status}</h1>
|
|
@@ -2165,14 +1938,14 @@ describe('createQuery', () => {
|
|
|
2165
1938
|
</QueryClientProvider>));
|
|
2166
1939
|
await waitFor(() => screen.getByText('error boundary'));
|
|
2167
1940
|
});
|
|
2168
|
-
it('should update with data if we observe no properties and
|
|
1941
|
+
it('should update with data if we observe no properties and throwOnError', async () => {
|
|
2169
1942
|
const key = queryKey();
|
|
2170
1943
|
let result;
|
|
2171
1944
|
function Page() {
|
|
2172
1945
|
const query = createQuery(() => ({
|
|
2173
1946
|
queryKey: key,
|
|
2174
1947
|
queryFn: () => Promise.resolve('data'),
|
|
2175
|
-
|
|
1948
|
+
throwOnError: true,
|
|
2176
1949
|
}));
|
|
2177
1950
|
createEffect(() => {
|
|
2178
1951
|
result = query;
|
|
@@ -2192,7 +1965,7 @@ describe('createQuery', () => {
|
|
|
2192
1965
|
queryKey: key,
|
|
2193
1966
|
queryFn: () => Promise.reject(new Error('Local Error')),
|
|
2194
1967
|
retry: false,
|
|
2195
|
-
|
|
1968
|
+
throwOnError: (err) => err.message !== 'Local Error',
|
|
2196
1969
|
}));
|
|
2197
1970
|
return (<div>
|
|
2198
1971
|
<h1>{state.status}</h1>
|
|
@@ -2214,7 +1987,7 @@ describe('createQuery', () => {
|
|
|
2214
1987
|
queryKey: key,
|
|
2215
1988
|
queryFn: () => Promise.reject(new Error('Remote Error')),
|
|
2216
1989
|
retry: false,
|
|
2217
|
-
|
|
1990
|
+
throwOnError: (err) => err.message !== 'Local Error',
|
|
2218
1991
|
}));
|
|
2219
1992
|
return (<div>
|
|
2220
1993
|
<h1>{state.status}</h1>
|
|
@@ -2501,6 +2274,7 @@ describe('createQuery', () => {
|
|
|
2501
2274
|
queryFn: () => ({ count: 10 }),
|
|
2502
2275
|
staleTime: Infinity,
|
|
2503
2276
|
initialData: () => ({ count: count() }),
|
|
2277
|
+
reconcile: false,
|
|
2504
2278
|
}));
|
|
2505
2279
|
createRenderEffect(() => {
|
|
2506
2280
|
states.push({ ...state });
|
|
@@ -3503,6 +3277,47 @@ describe('createQuery', () => {
|
|
|
3503
3277
|
// effect should not be triggered again due to structural sharing
|
|
3504
3278
|
expect(states).toHaveLength(1);
|
|
3505
3279
|
});
|
|
3280
|
+
it('The reconcile fn callback should correctly maintain referential equality', async () => {
|
|
3281
|
+
const key1 = queryKey();
|
|
3282
|
+
const states = [];
|
|
3283
|
+
function Page() {
|
|
3284
|
+
const [forceValue, setForceValue] = createSignal(1);
|
|
3285
|
+
const state = createQuery(() => ({
|
|
3286
|
+
queryKey: key1,
|
|
3287
|
+
queryFn: async () => {
|
|
3288
|
+
await sleep(10);
|
|
3289
|
+
return [1, 2];
|
|
3290
|
+
},
|
|
3291
|
+
select: (res) => res.map((x) => x + 1),
|
|
3292
|
+
reconcile(oldData, newData) {
|
|
3293
|
+
return reconcile(newData)(oldData);
|
|
3294
|
+
},
|
|
3295
|
+
}));
|
|
3296
|
+
createEffect(() => {
|
|
3297
|
+
if (state.data) {
|
|
3298
|
+
states.push(state.data);
|
|
3299
|
+
}
|
|
3300
|
+
});
|
|
3301
|
+
const forceUpdate = () => {
|
|
3302
|
+
setForceValue((prev) => prev + 1);
|
|
3303
|
+
};
|
|
3304
|
+
return (<div>
|
|
3305
|
+
<h2>Data: {JSON.stringify(state.data)}</h2>
|
|
3306
|
+
<h2>forceValue: {forceValue}</h2>
|
|
3307
|
+
<button onClick={forceUpdate}>forceUpdate</button>
|
|
3308
|
+
</div>);
|
|
3309
|
+
}
|
|
3310
|
+
render(() => (<QueryClientProvider client={queryClient}>
|
|
3311
|
+
<Page />
|
|
3312
|
+
</QueryClientProvider>));
|
|
3313
|
+
await waitFor(() => screen.getByText('Data: [2,3]'));
|
|
3314
|
+
expect(states).toHaveLength(1);
|
|
3315
|
+
fireEvent.click(screen.getByRole('button', { name: /forceUpdate/i }));
|
|
3316
|
+
await waitFor(() => screen.getByText('forceValue: 2'));
|
|
3317
|
+
await waitFor(() => screen.getByText('Data: [2,3]'));
|
|
3318
|
+
// effect should not be triggered again due to structural sharing
|
|
3319
|
+
expect(states).toHaveLength(1);
|
|
3320
|
+
});
|
|
3506
3321
|
it('should cancel the query function when there are no more subscriptions', async () => {
|
|
3507
3322
|
const key = queryKey();
|
|
3508
3323
|
let cancelFn = vi.fn();
|
|
@@ -4513,31 +4328,6 @@ describe('createQuery', () => {
|
|
|
4513
4328
|
error,
|
|
4514
4329
|
});
|
|
4515
4330
|
});
|
|
4516
|
-
it('setQueryData - should not call onSuccess callback of active observers', async () => {
|
|
4517
|
-
const key = queryKey();
|
|
4518
|
-
const onSuccess = vi.fn();
|
|
4519
|
-
function Page() {
|
|
4520
|
-
const state = createQuery(() => ({
|
|
4521
|
-
queryKey: key,
|
|
4522
|
-
queryFn: () => 'data',
|
|
4523
|
-
onSuccess,
|
|
4524
|
-
}));
|
|
4525
|
-
return (<div>
|
|
4526
|
-
<div>data: {state.data}</div>
|
|
4527
|
-
<button onClick={() => queryClient.setQueryData(key, 'newData')}>
|
|
4528
|
-
setQueryData
|
|
4529
|
-
</button>
|
|
4530
|
-
</div>);
|
|
4531
|
-
}
|
|
4532
|
-
render(() => (<QueryClientProvider client={queryClient}>
|
|
4533
|
-
<Page />
|
|
4534
|
-
</QueryClientProvider>));
|
|
4535
|
-
await waitFor(() => screen.getByText('data: data'));
|
|
4536
|
-
fireEvent.click(screen.getByRole('button', { name: /setQueryData/i }));
|
|
4537
|
-
await waitFor(() => screen.getByText('data: newData'));
|
|
4538
|
-
expect(onSuccess).toHaveBeenCalledTimes(1);
|
|
4539
|
-
expect(onSuccess).toHaveBeenCalledWith('data');
|
|
4540
|
-
});
|
|
4541
4331
|
it('setQueryData - should respect updatedAt', async () => {
|
|
4542
4332
|
const key = queryKey();
|
|
4543
4333
|
function Page() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createQuery } from '../index';
|
|
1
|
+
import { createQuery, queryOptions } from '../index';
|
|
2
2
|
const doNotExecute = (_func) => true;
|
|
3
3
|
describe('initialData', () => {
|
|
4
4
|
describe('Config object overload', () => {
|
|
@@ -19,6 +19,24 @@ describe('initialData', () => {
|
|
|
19
19
|
return result;
|
|
20
20
|
});
|
|
21
21
|
});
|
|
22
|
+
it('TData should be defined when passed through queryOptions', () => {
|
|
23
|
+
doNotExecute(() => {
|
|
24
|
+
const options = queryOptions(() => ({
|
|
25
|
+
queryKey: ['key'],
|
|
26
|
+
queryFn: () => {
|
|
27
|
+
return {
|
|
28
|
+
wow: true,
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
initialData: {
|
|
32
|
+
wow: true,
|
|
33
|
+
},
|
|
34
|
+
}));
|
|
35
|
+
const { data } = createQuery(options);
|
|
36
|
+
const result = true;
|
|
37
|
+
return result;
|
|
38
|
+
});
|
|
39
|
+
});
|
|
22
40
|
it('TData should always be defined when initialData is provided as a function which ALWAYS returns the data', () => {
|
|
23
41
|
doNotExecute(() => {
|
|
24
42
|
const { data } = createQuery(() => ({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fireEvent, render, screen, waitFor } from '
|
|
1
|
+
import { fireEvent, render, screen, waitFor } from '@solidjs/testing-library';
|
|
2
2
|
import { createRenderEffect, createSignal, ErrorBoundary, on, Show, Suspense, } from 'solid-js';
|
|
3
3
|
import { createInfiniteQuery, createQuery, QueryCache, QueryClientProvider, } from '..';
|
|
4
4
|
import { createQueryClient, queryKey, sleep } from './utils';
|
|
@@ -140,68 +140,6 @@ describe("useQuery's in Suspense mode", () => {
|
|
|
140
140
|
expect(screen.queryByText('rendered')).toBeNull();
|
|
141
141
|
expect(queryCache.find({ queryKey: key })?.getObserversCount()).toBe(0);
|
|
142
142
|
});
|
|
143
|
-
it('should call onSuccess on the first successful call', async () => {
|
|
144
|
-
const key = queryKey();
|
|
145
|
-
const successFn = vi.fn();
|
|
146
|
-
function Page() {
|
|
147
|
-
createQuery(() => ({
|
|
148
|
-
queryKey: [key],
|
|
149
|
-
queryFn: async () => {
|
|
150
|
-
await sleep(10);
|
|
151
|
-
return key;
|
|
152
|
-
},
|
|
153
|
-
suspense: true,
|
|
154
|
-
select: () => 'selected',
|
|
155
|
-
onSuccess: successFn,
|
|
156
|
-
}));
|
|
157
|
-
return <>rendered</>;
|
|
158
|
-
}
|
|
159
|
-
render(() => (<QueryClientProvider client={queryClient}>
|
|
160
|
-
<Suspense fallback="loading">
|
|
161
|
-
<Page />
|
|
162
|
-
</Suspense>
|
|
163
|
-
</QueryClientProvider>));
|
|
164
|
-
await waitFor(() => screen.getByText('rendered'));
|
|
165
|
-
await waitFor(() => expect(successFn).toHaveBeenCalledTimes(1));
|
|
166
|
-
await waitFor(() => expect(successFn).toHaveBeenCalledWith('selected'));
|
|
167
|
-
});
|
|
168
|
-
it('should call every onSuccess handler within a suspense boundary', async () => {
|
|
169
|
-
const key = queryKey();
|
|
170
|
-
const successFn1 = vi.fn();
|
|
171
|
-
const successFn2 = vi.fn();
|
|
172
|
-
function FirstComponent() {
|
|
173
|
-
createQuery(() => ({
|
|
174
|
-
queryKey: key,
|
|
175
|
-
queryFn: () => {
|
|
176
|
-
sleep(10);
|
|
177
|
-
return 'data';
|
|
178
|
-
},
|
|
179
|
-
onSuccess: successFn1,
|
|
180
|
-
}));
|
|
181
|
-
return <span>first</span>;
|
|
182
|
-
}
|
|
183
|
-
function SecondComponent() {
|
|
184
|
-
createQuery(() => ({
|
|
185
|
-
queryKey: key,
|
|
186
|
-
queryFn: () => {
|
|
187
|
-
sleep(10);
|
|
188
|
-
return 'data';
|
|
189
|
-
},
|
|
190
|
-
onSuccess: successFn2,
|
|
191
|
-
}));
|
|
192
|
-
return <span>second</span>;
|
|
193
|
-
}
|
|
194
|
-
render(() => (<QueryClientProvider client={queryClient}>
|
|
195
|
-
<Suspense fallback="loading">
|
|
196
|
-
<FirstComponent />
|
|
197
|
-
<SecondComponent />
|
|
198
|
-
</Suspense>
|
|
199
|
-
,
|
|
200
|
-
</QueryClientProvider>));
|
|
201
|
-
await waitFor(() => screen.getByText('second'));
|
|
202
|
-
await waitFor(() => expect(successFn1).toHaveBeenCalledTimes(1));
|
|
203
|
-
await waitFor(() => expect(successFn2).toHaveBeenCalledTimes(1));
|
|
204
|
-
});
|
|
205
143
|
// https://github.com/tannerlinsley/react-query/issues/468
|
|
206
144
|
it('should reset error state if new component instances are mounted', async () => {
|
|
207
145
|
const key = queryKey();
|
|
@@ -410,7 +348,7 @@ describe("useQuery's in Suspense mode", () => {
|
|
|
410
348
|
await waitFor(() => screen.getByText('Loading...'));
|
|
411
349
|
await waitFor(() => screen.getByText('error boundary'));
|
|
412
350
|
});
|
|
413
|
-
it('should not throw errors to the error boundary when
|
|
351
|
+
it('should not throw errors to the error boundary when throwOnError: false', async () => {
|
|
414
352
|
const key = queryKey();
|
|
415
353
|
function Page() {
|
|
416
354
|
const state = createQuery(() => ({
|
|
@@ -420,7 +358,7 @@ describe("useQuery's in Suspense mode", () => {
|
|
|
420
358
|
throw new Error('Suspense Error a2x');
|
|
421
359
|
},
|
|
422
360
|
retry: false,
|
|
423
|
-
|
|
361
|
+
throwOnError: false,
|
|
424
362
|
}));
|
|
425
363
|
// read state.data to trigger suspense.
|
|
426
364
|
createRenderEffect(() => {
|
|
@@ -444,7 +382,7 @@ describe("useQuery's in Suspense mode", () => {
|
|
|
444
382
|
await waitFor(() => screen.getByText('Loading...'));
|
|
445
383
|
await waitFor(() => screen.getByText('rendered'));
|
|
446
384
|
});
|
|
447
|
-
it('should throw errors to the error boundary when a
|
|
385
|
+
it('should throw errors to the error boundary when a throwOnError function returns true', async () => {
|
|
448
386
|
const key = queryKey();
|
|
449
387
|
function Page() {
|
|
450
388
|
const state = createQuery(() => ({
|
|
@@ -454,7 +392,7 @@ describe("useQuery's in Suspense mode", () => {
|
|
|
454
392
|
return Promise.reject(new Error('Remote Error'));
|
|
455
393
|
},
|
|
456
394
|
retry: false,
|
|
457
|
-
|
|
395
|
+
throwOnError: (err) => err.message !== 'Local Error',
|
|
458
396
|
}));
|
|
459
397
|
// read state.data to trigger suspense.
|
|
460
398
|
createRenderEffect(() => {
|
|
@@ -478,7 +416,7 @@ describe("useQuery's in Suspense mode", () => {
|
|
|
478
416
|
await waitFor(() => screen.getByText('Loading...'));
|
|
479
417
|
await waitFor(() => screen.getByText('error boundary'));
|
|
480
418
|
});
|
|
481
|
-
it('should not throw errors to the error boundary when a
|
|
419
|
+
it('should not throw errors to the error boundary when a throwOnError function returns false', async () => {
|
|
482
420
|
const key = queryKey();
|
|
483
421
|
function Page() {
|
|
484
422
|
const state = createQuery(() => ({
|
|
@@ -489,7 +427,7 @@ describe("useQuery's in Suspense mode", () => {
|
|
|
489
427
|
},
|
|
490
428
|
retry: false,
|
|
491
429
|
suspense: true,
|
|
492
|
-
|
|
430
|
+
throwOnError: (err) => err.message !== 'Local Error',
|
|
493
431
|
}));
|
|
494
432
|
// read state.data to trigger suspense.
|
|
495
433
|
createRenderEffect(() => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fireEvent, render, screen, waitFor } from '
|
|
1
|
+
import { fireEvent, render, screen, waitFor } from '@solidjs/testing-library';
|
|
2
2
|
import { createSignal, Show, startTransition, Suspense } from 'solid-js';
|
|
3
3
|
import { createQuery, QueryCache, QueryClientProvider } from '..';
|
|
4
4
|
import { createQueryClient, queryKey, sleep } from './utils';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fireEvent, render, screen, waitFor } from '
|
|
1
|
+
import { fireEvent, render, screen, waitFor } from '@solidjs/testing-library';
|
|
2
2
|
import { createEffect, createRenderEffect, createSignal, Show } from 'solid-js';
|
|
3
3
|
import { createQuery, QueryCache, QueryClientProvider, useIsFetching } from '..';
|
|
4
4
|
import { createQueryClient, queryKey, setActTimeout, sleep } from './utils';
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { fireEvent, screen, waitFor } from '
|
|
1
|
+
import { fireEvent, render, screen, waitFor } from '@solidjs/testing-library';
|
|
2
2
|
import { createMutation, QueryClientProvider, useIsMutating } from '..';
|
|
3
|
-
import { createQueryClient, sleep } from './utils';
|
|
3
|
+
import { createQueryClient, sleep, setActTimeout } from './utils';
|
|
4
4
|
import { createEffect, createRenderEffect, createSignal, Show } from 'solid-js';
|
|
5
|
-
import
|
|
6
|
-
import * as MutationCacheModule from '../../../query-core/src/mutationCache';
|
|
7
|
-
import { setActTimeout } from './utils';
|
|
5
|
+
import * as QueryCore from '@tanstack/query-core';
|
|
8
6
|
import { vi } from 'vitest';
|
|
9
7
|
describe('useIsMutating', () => {
|
|
10
8
|
it('should return the number of fetching mutations', async () => {
|
|
@@ -151,14 +149,14 @@ describe('useIsMutating', () => {
|
|
|
151
149
|
it('should not change state if unmounted', async () => {
|
|
152
150
|
// We have to mock the MutationCache to not unsubscribe
|
|
153
151
|
// the listener when the component is unmounted
|
|
154
|
-
class MutationCacheMock extends
|
|
152
|
+
class MutationCacheMock extends QueryCore.MutationCache {
|
|
155
153
|
subscribe(listener) {
|
|
156
154
|
super.subscribe(listener);
|
|
157
155
|
return () => void 0;
|
|
158
156
|
}
|
|
159
157
|
}
|
|
160
158
|
const MutationCacheSpy = vi
|
|
161
|
-
.spyOn(
|
|
159
|
+
.spyOn(QueryCore, 'MutationCache')
|
|
162
160
|
.mockImplementation((fn) => {
|
|
163
161
|
return new MutationCacheMock(fn);
|
|
164
162
|
});
|