@zenstackhq/tanstack-query 3.0.0 → 3.1.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.
Files changed (56) hide show
  1. package/dist/common/client.d.ts +4 -0
  2. package/dist/common/client.js +38 -0
  3. package/dist/common/client.js.map +1 -0
  4. package/dist/common/query-key.d.ts +39 -0
  5. package/dist/common/query-key.js +38 -0
  6. package/dist/common/query-key.js.map +1 -0
  7. package/dist/common/types.d.ts +60 -0
  8. package/dist/common/types.js +2 -0
  9. package/dist/common/types.js.map +1 -0
  10. package/dist/react.d.ts +99 -150
  11. package/dist/react.js +248 -1178
  12. package/dist/react.js.map +1 -1
  13. package/dist/svelte/index.svelte.d.ts +79 -0
  14. package/dist/svelte/index.svelte.js +245 -0
  15. package/dist/vue.d.ts +313 -342
  16. package/dist/vue.js +224 -1138
  17. package/dist/vue.js.map +1 -1
  18. package/package.json +36 -48
  19. package/.turbo/turbo-build.log +0 -47
  20. package/dist/react.cjs +0 -1240
  21. package/dist/react.cjs.map +0 -1
  22. package/dist/react.d.cts +0 -616
  23. package/dist/svelte.cjs +0 -1224
  24. package/dist/svelte.cjs.map +0 -1
  25. package/dist/svelte.d.cts +0 -381
  26. package/dist/svelte.d.ts +0 -381
  27. package/dist/svelte.js +0 -1183
  28. package/dist/svelte.js.map +0 -1
  29. package/dist/types-C8iIZD-7.d.cts +0 -99
  30. package/dist/types-C8iIZD-7.d.ts +0 -99
  31. package/dist/vue.cjs +0 -1192
  32. package/dist/vue.cjs.map +0 -1
  33. package/dist/vue.d.cts +0 -382
  34. package/eslint.config.js +0 -4
  35. package/src/react.ts +0 -562
  36. package/src/svelte.ts +0 -502
  37. package/src/utils/common.ts +0 -448
  38. package/src/utils/mutator.ts +0 -441
  39. package/src/utils/nested-read-visitor.ts +0 -61
  40. package/src/utils/nested-write-visitor.ts +0 -359
  41. package/src/utils/query-analysis.ts +0 -116
  42. package/src/utils/serialization.ts +0 -39
  43. package/src/utils/types.ts +0 -43
  44. package/src/vue.ts +0 -448
  45. package/test/react-query.test.tsx +0 -1787
  46. package/test/react-typing-test.ts +0 -113
  47. package/test/schemas/basic/input.ts +0 -110
  48. package/test/schemas/basic/models.ts +0 -14
  49. package/test/schemas/basic/schema-lite.ts +0 -172
  50. package/test/schemas/basic/schema.zmodel +0 -35
  51. package/test/svelte-typing-test.ts +0 -111
  52. package/test/vue-typing-test.ts +0 -111
  53. package/tsconfig.json +0 -7
  54. package/tsconfig.test.json +0 -8
  55. package/tsup.config.ts +0 -15
  56. package/vitest.config.ts +0 -11
@@ -1,1787 +0,0 @@
1
- /**
2
- * @vitest-environment happy-dom
3
- */
4
-
5
- import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query';
6
- import { act, cleanup, renderHook, waitFor } from '@testing-library/react';
7
- import nock from 'nock';
8
- import React from 'react';
9
- import { afterEach, describe, expect, it } from 'vitest';
10
- import { QuerySettingsProvider, useClientQueries } from '../src/react';
11
- import { getQueryKey } from '../src/utils/common';
12
- import { schema } from './schemas/basic/schema-lite';
13
-
14
- const BASE_URL = 'http://localhost';
15
-
16
- describe('React Query Test', () => {
17
- function createWrapper() {
18
- const queryClient = new QueryClient({
19
- defaultOptions: {
20
- queries: {
21
- retry: false,
22
- },
23
- },
24
- });
25
- const Provider = QuerySettingsProvider;
26
- const wrapper = ({ children }: { children: React.ReactNode }) => (
27
- <QueryClientProvider client={queryClient}>
28
- <Provider value={{ endpoint: `${BASE_URL}/api/model` }}>{children}</Provider>
29
- </QueryClientProvider>
30
- );
31
- return { queryClient, wrapper };
32
- }
33
-
34
- function makeUrl(model: string, operation: string, args?: unknown) {
35
- let r = `${BASE_URL}/api/model/${model}/${operation}`;
36
- if (args) {
37
- r += `?q=${encodeURIComponent(JSON.stringify(args))}`;
38
- }
39
- return r;
40
- }
41
-
42
- afterEach(() => {
43
- nock.cleanAll();
44
- cleanup();
45
- });
46
-
47
- it('works with simple query', async () => {
48
- const { queryClient, wrapper } = createWrapper();
49
-
50
- const queryArgs = { where: { id: '1' } };
51
- const data = { id: '1', name: 'foo' };
52
-
53
- nock(makeUrl('User', 'findUnique', queryArgs))
54
- .get(/.*/)
55
- .reply(200, {
56
- data,
57
- });
58
-
59
- const { result } = renderHook(() => useClientQueries(schema).user.useFindUnique(queryArgs), {
60
- wrapper,
61
- });
62
-
63
- await waitFor(() => {
64
- expect(result.current.isSuccess).toBe(true);
65
- expect(result.current.data).toMatchObject(data);
66
- const cacheData = queryClient.getQueryData(getQueryKey('User', 'findUnique', queryArgs));
67
- expect(cacheData).toMatchObject(data);
68
- });
69
-
70
- nock(makeUrl('User', 'findFirst', queryArgs))
71
- .get(/.*/)
72
- .reply(404, () => {
73
- return { error: 'Not Found' };
74
- });
75
- const { result: errorResult } = renderHook(() => useClientQueries(schema).user.useFindFirst(queryArgs), {
76
- wrapper,
77
- });
78
- await waitFor(() => {
79
- expect(errorResult.current.isError).toBe(true);
80
- });
81
- });
82
-
83
- it('works with suspense query', async () => {
84
- const { queryClient, wrapper } = createWrapper();
85
-
86
- const queryArgs = { where: { id: '1' } };
87
- const data = { id: '1', name: 'foo' };
88
-
89
- nock(makeUrl('User', 'findUnique', queryArgs))
90
- .get(/.*/)
91
- .reply(200, {
92
- data,
93
- });
94
-
95
- const { result } = renderHook(() => useClientQueries(schema).user.useSuspenseFindUnique(queryArgs), {
96
- wrapper,
97
- });
98
-
99
- await waitFor(() => {
100
- expect(result.current.isSuccess).toBe(true);
101
- expect(result.current.data).toMatchObject(data);
102
- const cacheData = queryClient.getQueryData(getQueryKey('User', 'findUnique', queryArgs));
103
- expect(cacheData).toMatchObject(data);
104
- });
105
- });
106
-
107
- it('works with infinite query', async () => {
108
- const { queryClient, wrapper } = createWrapper();
109
-
110
- const queryArgs = { where: { id: '1' } };
111
- const data = [{ id: '1', name: 'foo' }];
112
-
113
- nock(makeUrl('User', 'findMany', queryArgs))
114
- .get(/.*/)
115
- .reply(200, () => ({
116
- data,
117
- }));
118
-
119
- const { result } = renderHook(
120
- () =>
121
- useClientQueries(schema).user.useInfiniteFindMany(queryArgs, {
122
- getNextPageParam: () => null,
123
- }),
124
- {
125
- wrapper,
126
- },
127
- );
128
- await waitFor(() => {
129
- expect(result.current.isSuccess).toBe(true);
130
- const resultData = result.current.data!;
131
- expect(resultData.pages).toHaveLength(1);
132
- expect(resultData.pages[0]).toMatchObject(data);
133
- expect(resultData?.pageParams).toHaveLength(1);
134
- expect(resultData?.pageParams[0]).toMatchObject(queryArgs);
135
- expect(result.current.hasNextPage).toBe(false);
136
- const cacheData: any = queryClient.getQueryData(
137
- getQueryKey('User', 'findMany', queryArgs, { infinite: true, optimisticUpdate: false }),
138
- );
139
- expect(cacheData.pages[0]).toMatchObject(data);
140
- });
141
- });
142
-
143
- it('works with suspense infinite query', async () => {
144
- const { queryClient, wrapper } = createWrapper();
145
-
146
- const queryArgs = { where: { id: '1' } };
147
- const data = [{ id: '1', name: 'foo' }];
148
-
149
- nock(makeUrl('User', 'findMany', queryArgs))
150
- .get(/.*/)
151
- .reply(200, () => ({
152
- data,
153
- }));
154
-
155
- const { result } = renderHook(
156
- () =>
157
- useClientQueries(schema).user.useSuspenseInfiniteFindMany(queryArgs, {
158
- getNextPageParam: () => null,
159
- }),
160
- {
161
- wrapper,
162
- },
163
- );
164
- await waitFor(() => {
165
- expect(result.current.isSuccess).toBe(true);
166
- const resultData = result.current.data!;
167
- expect(resultData.pages).toHaveLength(1);
168
- expect(resultData.pages[0]).toMatchObject(data);
169
- expect(resultData?.pageParams).toHaveLength(1);
170
- expect(resultData?.pageParams[0]).toMatchObject(queryArgs);
171
- expect(result.current.hasNextPage).toBe(false);
172
- const cacheData: any = queryClient.getQueryData(
173
- getQueryKey('User', 'findMany', queryArgs, { infinite: true, optimisticUpdate: false }),
174
- );
175
- expect(cacheData.pages[0]).toMatchObject(data);
176
- });
177
- });
178
-
179
- it('works with independent mutation and query', async () => {
180
- const { wrapper } = createWrapper();
181
-
182
- const queryArgs = { where: { id: '1' } };
183
- const data = { id: '1', name: 'foo' };
184
-
185
- let queryCount = 0;
186
- nock(makeUrl('User', 'findUnique', queryArgs))
187
- .get(/.*/)
188
- .reply(200, () => {
189
- queryCount++;
190
- return { data };
191
- })
192
- .persist();
193
-
194
- const { result } = renderHook(() => useClientQueries(schema).user.useFindUnique(queryArgs), {
195
- wrapper,
196
- });
197
- await waitFor(() => {
198
- expect(result.current.data).toMatchObject({ name: 'foo' });
199
- });
200
-
201
- nock(makeUrl('Post', 'create'))
202
- .post(/.*/)
203
- .reply(200, () => ({
204
- data: { id: '1', title: 'post1' },
205
- }));
206
-
207
- const { result: mutationResult } = renderHook(() => useClientQueries(schema).post.useCreate(), {
208
- wrapper,
209
- });
210
-
211
- act(() => mutationResult.current.mutate({ data: { title: 'post1' } }));
212
-
213
- await waitFor(() => {
214
- // no refetch caused by invalidation
215
- expect(queryCount).toBe(1);
216
- });
217
- });
218
-
219
- it('works with create and invalidation', async () => {
220
- const { queryClient, wrapper } = createWrapper();
221
-
222
- const data: any[] = [];
223
-
224
- nock(makeUrl('User', 'findMany'))
225
- .get(/.*/)
226
- .reply(200, () => ({ data }))
227
- .persist();
228
-
229
- const { result } = renderHook(() => useClientQueries(schema).user.useFindMany(), {
230
- wrapper,
231
- });
232
- await waitFor(() => {
233
- expect(result.current.data).toHaveLength(0);
234
- });
235
-
236
- nock(makeUrl('User', 'create'))
237
- .post(/.*/)
238
- .reply(200, () => {
239
- data.push({ id: '1', email: 'foo' });
240
- return { data: data[0] };
241
- });
242
-
243
- const { result: mutationResult } = renderHook(() => useClientQueries(schema).user.useCreate(), {
244
- wrapper,
245
- });
246
-
247
- act(() => mutationResult.current.mutate({ data: { email: 'foo' } }));
248
-
249
- await waitFor(() => {
250
- const cacheData = queryClient.getQueryData(getQueryKey('User', 'findMany', undefined));
251
- expect(cacheData).toHaveLength(1);
252
- });
253
- });
254
-
255
- it('works with create and no invalidation', async () => {
256
- const { queryClient, wrapper } = createWrapper();
257
-
258
- const data: any[] = [];
259
-
260
- nock(makeUrl('User', 'findMany'))
261
- .get(/.*/)
262
- .reply(200, () => ({ data }))
263
- .persist();
264
-
265
- const { result } = renderHook(() => useClientQueries(schema).user.useFindMany(), {
266
- wrapper,
267
- });
268
- await waitFor(() => {
269
- expect(result.current.data).toHaveLength(0);
270
- });
271
-
272
- nock(makeUrl('User', 'create'))
273
- .post(/.*/)
274
- .reply(200, () => {
275
- data.push({ id: '1', email: 'foo' });
276
- return { data: data[0] };
277
- });
278
-
279
- const { result: mutationResult } = renderHook(() => useClientQueries(schema).user.useCreate(), {
280
- wrapper,
281
- });
282
-
283
- act(() => mutationResult.current.mutate({ data: { email: 'foo' } }));
284
-
285
- await waitFor(() => {
286
- const cacheData = queryClient.getQueryData(getQueryKey('User', 'findMany', undefined));
287
- expect(cacheData).toHaveLength(0);
288
- });
289
- });
290
-
291
- it('works with optimistic create single', async () => {
292
- const { queryClient, wrapper } = createWrapper();
293
-
294
- const data: any[] = [];
295
-
296
- nock(makeUrl('User', 'findMany'))
297
- .get(/.*/)
298
- .reply(200, () => ({ data }))
299
- .persist();
300
-
301
- const { result } = renderHook(
302
- () => useClientQueries(schema).user.useFindMany(undefined, { optimisticUpdate: true }),
303
- {
304
- wrapper,
305
- },
306
- );
307
- await waitFor(() => {
308
- expect(result.current.data).toHaveLength(0);
309
- });
310
-
311
- nock(makeUrl('User', 'create'))
312
- .post(/.*/)
313
- .reply(200, () => ({
314
- data: null,
315
- }));
316
-
317
- const { result: mutationResult } = renderHook(
318
- () =>
319
- useClientQueries(schema).user.useCreate({
320
- optimisticUpdate: true,
321
- invalidateQueries: false,
322
- }),
323
- {
324
- wrapper,
325
- },
326
- );
327
-
328
- act(() => mutationResult.current.mutate({ data: { email: 'foo' } }));
329
-
330
- await waitFor(() => {
331
- const cacheData: any = queryClient.getQueryData(
332
- getQueryKey('User', 'findMany', undefined, { infinite: false, optimisticUpdate: true }),
333
- );
334
- expect(cacheData).toHaveLength(1);
335
- expect(cacheData[0].$optimistic).toBe(true);
336
- expect(cacheData[0].id).toBeTruthy();
337
- expect(cacheData[0].email).toBe('foo');
338
- });
339
- });
340
-
341
- it('works with optimistic create updating nested query', async () => {
342
- const { queryClient, wrapper } = createWrapper();
343
-
344
- const data: any[] = [{ id: '1', name: 'user1', posts: [] }];
345
-
346
- nock(makeUrl('User', 'findMany'))
347
- .get(/.*/)
348
- .reply(200, () => ({ data }))
349
- .persist();
350
-
351
- const { result } = renderHook(
352
- () =>
353
- useClientQueries(schema).user.useFindMany(
354
- {
355
- include: { posts: true },
356
- },
357
- { optimisticUpdate: true },
358
- ),
359
- {
360
- wrapper,
361
- },
362
- );
363
- await waitFor(() => {
364
- expect(result.current.data).toHaveLength(1);
365
- });
366
-
367
- nock(makeUrl('Post', 'create'))
368
- .post(/.*/)
369
- .reply(200, () => ({
370
- data: null,
371
- }));
372
-
373
- const { result: mutationResult } = renderHook(
374
- () =>
375
- useClientQueries(schema).post.useCreate({
376
- optimisticUpdate: true,
377
- invalidateQueries: false,
378
- }),
379
- {
380
- wrapper,
381
- },
382
- );
383
-
384
- act(() => mutationResult.current.mutate({ data: { title: 'post1', owner: { connect: { id: '1' } } } }));
385
-
386
- await waitFor(() => {
387
- const cacheData: any = queryClient.getQueryData(
388
- getQueryKey(
389
- 'User',
390
- 'findMany',
391
- { include: { posts: true } },
392
- { infinite: false, optimisticUpdate: true },
393
- ),
394
- );
395
- const posts = cacheData[0].posts;
396
- expect(posts).toHaveLength(1);
397
- expect(posts[0]).toMatchObject({ $optimistic: true, id: expect.any(String), title: 'post1', ownerId: '1' });
398
- });
399
- });
400
-
401
- it('works with optimistic create updating deeply nested query', async () => {
402
- const { queryClient, wrapper } = createWrapper();
403
-
404
- // populate the cache with a user
405
-
406
- const userData: any[] = [{ id: '1', email: 'user1', posts: [] }];
407
-
408
- nock(BASE_URL)
409
- .get('/api/model/user/findMany')
410
- .query(true)
411
- .reply(200, () => ({ data: userData }))
412
- .persist();
413
-
414
- const { result: userResult } = renderHook(
415
- () =>
416
- useClientQueries(schema).user.useFindMany(
417
- {
418
- include: {
419
- posts: {
420
- include: {
421
- category: true,
422
- },
423
- },
424
- },
425
- },
426
- { optimisticUpdate: true },
427
- ),
428
- {
429
- wrapper,
430
- },
431
- );
432
- await waitFor(() => {
433
- expect(userResult.current.data).toHaveLength(1);
434
- });
435
-
436
- // populate the cache with a category
437
- const categoryData: any[] = [{ id: '1', name: 'category1', posts: [] }];
438
-
439
- nock(BASE_URL)
440
- .get('/api/model/category/findMany')
441
- .query(true)
442
- .reply(200, () => ({ data: categoryData }))
443
- .persist();
444
-
445
- const { result: categoryResult } = renderHook(
446
- () =>
447
- useClientQueries(schema).category.useFindMany(
448
- {
449
- include: {
450
- posts: true,
451
- },
452
- },
453
- { optimisticUpdate: true },
454
- ),
455
- {
456
- wrapper,
457
- },
458
- );
459
- await waitFor(() => {
460
- expect(categoryResult.current.data).toHaveLength(1);
461
- });
462
-
463
- // create a post and connect it to the category
464
- nock(BASE_URL)
465
- .post('/api/model/post/create')
466
- .reply(200, () => ({
467
- data: null,
468
- }));
469
-
470
- const { result: mutationResult } = renderHook(
471
- () =>
472
- useClientQueries(schema).post.useCreate({
473
- optimisticUpdate: true,
474
- invalidateQueries: false,
475
- }),
476
- {
477
- wrapper,
478
- },
479
- );
480
-
481
- act(() =>
482
- mutationResult.current.mutate({
483
- data: { title: 'post1', owner: { connect: { id: '1' } }, category: { connect: { id: '1' } } },
484
- }),
485
- );
486
-
487
- // assert that the post was created and connected to the category
488
- await waitFor(() => {
489
- const cacheData: any = queryClient.getQueryData(
490
- getQueryKey(
491
- 'Category',
492
- 'findMany',
493
- {
494
- include: {
495
- posts: true,
496
- },
497
- },
498
- { infinite: false, optimisticUpdate: true },
499
- ),
500
- );
501
- const posts = cacheData[0].posts;
502
- expect(posts).toHaveLength(1);
503
- expect(posts[0]).toMatchObject({
504
- $optimistic: true,
505
- id: expect.any(String),
506
- title: 'post1',
507
- ownerId: '1',
508
- });
509
- });
510
-
511
- // assert that the post was created and connected to the user, and included the category
512
- await waitFor(() => {
513
- const cacheData: any = queryClient.getQueryData(
514
- getQueryKey(
515
- 'User',
516
- 'findMany',
517
- {
518
- include: {
519
- posts: {
520
- include: {
521
- category: true,
522
- },
523
- },
524
- },
525
- },
526
- { infinite: false, optimisticUpdate: true },
527
- ),
528
- );
529
- const posts = cacheData[0].posts;
530
- expect(posts).toHaveLength(1);
531
- expect(posts[0]).toMatchObject({
532
- $optimistic: true,
533
- id: expect.any(String),
534
- title: 'post1',
535
- ownerId: '1',
536
- categoryId: '1',
537
- // TODO: should this include the category object and not just the foreign key?
538
- // category: { $optimistic: true, id: '1', name: 'category1' },
539
- });
540
- });
541
- });
542
-
543
- it('works with optimistic update with optional one-to-many relationship', async () => {
544
- const { queryClient, wrapper } = createWrapper();
545
-
546
- // populate the cache with a post, with an optional category relationship
547
- const postData: any = {
548
- id: '1',
549
- title: 'post1',
550
- ownerId: '1',
551
- categoryId: null,
552
- category: null,
553
- };
554
-
555
- const data: any[] = [postData];
556
-
557
- nock(makeUrl('Post', 'findMany'))
558
- .get(/.*/)
559
- .query(true)
560
- .reply(200, () => ({
561
- data,
562
- }))
563
- .persist();
564
-
565
- const { result: postResult } = renderHook(
566
- () =>
567
- useClientQueries(schema).post.useFindMany(
568
- {
569
- include: {
570
- category: true,
571
- },
572
- },
573
- { optimisticUpdate: true },
574
- ),
575
- {
576
- wrapper,
577
- },
578
- );
579
- await waitFor(() => {
580
- expect(postResult.current.data).toHaveLength(1);
581
- });
582
-
583
- // mock a put request to update the post title
584
- nock(makeUrl('Post', 'update'))
585
- .put(/.*/)
586
- .reply(200, () => {
587
- postData.title = 'postA';
588
- return { data: postData };
589
- });
590
-
591
- const { result: mutationResult } = renderHook(
592
- () =>
593
- useClientQueries(schema).post.useUpdate({
594
- optimisticUpdate: true,
595
- invalidateQueries: false,
596
- }),
597
- {
598
- wrapper,
599
- },
600
- );
601
-
602
- act(() => mutationResult.current.mutate({ where: { id: '1' }, data: { title: 'postA' } }));
603
-
604
- // assert that the post was updated despite the optional (null) category relationship
605
- await waitFor(() => {
606
- const cacheData: any = queryClient.getQueryData(
607
- getQueryKey(
608
- 'Post',
609
- 'findMany',
610
- {
611
- include: {
612
- category: true,
613
- },
614
- },
615
- { infinite: false, optimisticUpdate: true },
616
- ),
617
- );
618
- const posts = cacheData;
619
- expect(posts).toHaveLength(1);
620
- expect(posts[0]).toMatchObject({
621
- $optimistic: true,
622
- id: expect.any(String),
623
- title: 'postA',
624
- ownerId: '1',
625
- categoryId: null,
626
- category: null,
627
- });
628
- });
629
- });
630
-
631
- it('works with optimistic update with nested optional one-to-many relationship', async () => {
632
- const { queryClient, wrapper } = createWrapper();
633
-
634
- // populate the cache with a user and a post, with an optional category
635
- const postData: any = {
636
- id: '1',
637
- title: 'post1',
638
- ownerId: '1',
639
- categoryId: null,
640
- category: null,
641
- };
642
-
643
- const userData: any[] = [{ id: '1', name: 'user1', posts: [postData] }];
644
-
645
- nock(BASE_URL)
646
- .get('/api/model/user/findMany')
647
- .query(true)
648
- .reply(200, () => {
649
- return { data: userData };
650
- })
651
- .persist();
652
-
653
- const { result: userResult } = renderHook(
654
- () =>
655
- useClientQueries(schema).user.useFindMany(
656
- {
657
- include: {
658
- posts: {
659
- include: {
660
- category: true,
661
- },
662
- },
663
- },
664
- },
665
- { optimisticUpdate: true },
666
- ),
667
- {
668
- wrapper,
669
- },
670
- );
671
- await waitFor(() => {
672
- expect(userResult.current.data).toHaveLength(1);
673
- });
674
-
675
- // mock a put request to update the post title
676
- nock(BASE_URL)
677
- .put('/api/model/post/update')
678
- .reply(200, () => {
679
- postData.title = 'postA';
680
- return { data: postData };
681
- });
682
-
683
- const { result: mutationResult } = renderHook(
684
- () =>
685
- useClientQueries(schema).post.useUpdate({
686
- optimisticUpdate: true,
687
- invalidateQueries: false,
688
- }),
689
- {
690
- wrapper,
691
- },
692
- );
693
-
694
- act(() => mutationResult.current.mutate({ where: { id: '1' }, data: { title: 'postA' } }));
695
-
696
- // assert that the post was updated
697
- await waitFor(() => {
698
- const cacheData: any = queryClient.getQueryData(
699
- getQueryKey(
700
- 'User',
701
- 'findMany',
702
- {
703
- include: {
704
- posts: {
705
- include: {
706
- category: true,
707
- },
708
- },
709
- },
710
- },
711
- { infinite: false, optimisticUpdate: true },
712
- ),
713
- );
714
- const posts = cacheData[0].posts;
715
- expect(posts).toHaveLength(1);
716
- expect(posts[0]).toMatchObject({
717
- $optimistic: true,
718
- id: expect.any(String),
719
- title: 'postA',
720
- ownerId: '1',
721
- categoryId: null,
722
- category: null,
723
- });
724
- });
725
- });
726
-
727
- it('works with optimistic nested create updating query', async () => {
728
- const { queryClient, wrapper } = createWrapper();
729
-
730
- const data: any[] = [];
731
-
732
- nock(makeUrl('Post', 'findMany'))
733
- .get(/.*/)
734
- .reply(200, () => ({
735
- data,
736
- }))
737
- .persist();
738
-
739
- const { result } = renderHook(
740
- () => useClientQueries(schema).post.useFindMany(undefined, { optimisticUpdate: true }),
741
- {
742
- wrapper,
743
- },
744
- );
745
- await waitFor(() => {
746
- expect(result.current.data).toHaveLength(0);
747
- });
748
-
749
- nock(makeUrl('User', 'create'))
750
- .post(/.*/)
751
- .reply(200, () => ({
752
- data: null,
753
- }));
754
-
755
- const { result: mutationResult } = renderHook(
756
- () =>
757
- useClientQueries(schema).user.useCreate({
758
- optimisticUpdate: true,
759
- invalidateQueries: false,
760
- }),
761
- {
762
- wrapper,
763
- },
764
- );
765
-
766
- act(() => mutationResult.current.mutate({ data: { email: 'user1', posts: { create: { title: 'post1' } } } }));
767
-
768
- await waitFor(() => {
769
- const cacheData: any = queryClient.getQueryData(
770
- getQueryKey('Post', 'findMany', undefined, { infinite: false, optimisticUpdate: true }),
771
- );
772
- expect(cacheData).toHaveLength(1);
773
- expect(cacheData[0].$optimistic).toBe(true);
774
- expect(cacheData[0].id).toBeTruthy();
775
- expect(cacheData[0].title).toBe('post1');
776
- });
777
- });
778
-
779
- it('works with optimistic create many', async () => {
780
- const { queryClient, wrapper } = createWrapper();
781
-
782
- const data: any[] = [];
783
-
784
- nock(makeUrl('User', 'findMany'))
785
- .get(/.*/)
786
- .reply(200, () => ({
787
- data,
788
- }))
789
- .persist();
790
-
791
- const { result } = renderHook(
792
- () => useClientQueries(schema).user.useFindMany(undefined, { optimisticUpdate: true }),
793
- {
794
- wrapper,
795
- },
796
- );
797
- await waitFor(() => {
798
- expect(result.current.data).toHaveLength(0);
799
- });
800
-
801
- nock(makeUrl('User', 'createMany'))
802
- .post(/.*/)
803
- .reply(200, () => ({
804
- data: null,
805
- }));
806
-
807
- const { result: mutationResult } = renderHook(
808
- () =>
809
- useClientQueries(schema).user.useCreateMany({
810
- optimisticUpdate: true,
811
- invalidateQueries: false,
812
- }),
813
- {
814
- wrapper,
815
- },
816
- );
817
-
818
- act(() => mutationResult.current.mutate({ data: [{ email: 'foo' }, { email: 'bar' }] }));
819
-
820
- await waitFor(() => {
821
- const cacheData: any = queryClient.getQueryData(
822
- getQueryKey('User', 'findMany', undefined, { infinite: false, optimisticUpdate: true }),
823
- );
824
- expect(cacheData).toHaveLength(2);
825
- });
826
- });
827
-
828
- it('works with update and invalidation', async () => {
829
- const { queryClient, wrapper } = createWrapper();
830
-
831
- const queryArgs = { where: { id: '1' } };
832
- const data = { id: '1', name: 'foo' };
833
-
834
- nock(makeUrl('User', 'findUnique', queryArgs))
835
- .get(/.*/)
836
- .reply(200, () => ({
837
- data,
838
- }))
839
- .persist();
840
-
841
- const { result } = renderHook(() => useClientQueries(schema).user.useFindUnique(queryArgs), {
842
- wrapper,
843
- });
844
- await waitFor(() => {
845
- expect(result.current.data).toMatchObject({ name: 'foo' });
846
- });
847
-
848
- nock(makeUrl('User', 'update'))
849
- .put(/.*/)
850
- .reply(200, () => {
851
- data.name = 'bar';
852
- return data;
853
- });
854
-
855
- const { result: mutationResult } = renderHook(() => useClientQueries(schema).user.useUpdate(), {
856
- wrapper,
857
- });
858
-
859
- act(() => mutationResult.current.mutate({ ...queryArgs, data: { name: 'bar' } }));
860
-
861
- await waitFor(() => {
862
- const cacheData = queryClient.getQueryData(getQueryKey('User', 'findUnique', queryArgs));
863
- expect(cacheData).toMatchObject({ name: 'bar' });
864
- });
865
- });
866
-
867
- it('works with update and no invalidation', async () => {
868
- const { queryClient, wrapper } = createWrapper();
869
-
870
- const queryArgs = { where: { id: '1' } };
871
- const data = { id: '1', name: 'foo' };
872
-
873
- nock(makeUrl('User', 'findUnique', queryArgs))
874
- .get(/.*/)
875
- .reply(200, () => ({ data }))
876
- .persist();
877
-
878
- const { result } = renderHook(() => useClientQueries(schema).user.useFindUnique(queryArgs), {
879
- wrapper,
880
- });
881
- await waitFor(() => {
882
- expect(result.current.data).toMatchObject({ name: 'foo' });
883
- });
884
-
885
- nock(makeUrl('User', 'update'))
886
- .put(/.*/)
887
- .reply(200, () => {
888
- data.name = 'bar';
889
- return data;
890
- });
891
-
892
- const { result: mutationResult } = renderHook(() => useClientQueries(schema).user.useUpdate(), {
893
- wrapper,
894
- });
895
-
896
- act(() => mutationResult.current.mutate({ ...queryArgs, data: { name: 'bar' } }));
897
-
898
- await waitFor(() => {
899
- const cacheData = queryClient.getQueryData(getQueryKey('User', 'findUnique', queryArgs));
900
- expect(cacheData).toMatchObject({ name: 'foo' });
901
- });
902
- });
903
-
904
- it('works with optimistic update simple', async () => {
905
- const { queryClient, wrapper } = createWrapper();
906
-
907
- const queryArgs = { where: { id: '1' } };
908
- const data = { id: '1', name: 'foo' };
909
-
910
- nock(makeUrl('User', 'findUnique', queryArgs))
911
- .get(/.*/)
912
- .reply(200, () => ({
913
- data,
914
- }))
915
- .persist();
916
-
917
- const { result } = renderHook(
918
- () => useClientQueries(schema).user.useFindUnique(queryArgs, { optimisticUpdate: true }),
919
- {
920
- wrapper,
921
- },
922
- );
923
- await waitFor(() => {
924
- expect(result.current.data).toMatchObject({ name: 'foo' });
925
- });
926
-
927
- nock(makeUrl('User', 'update'))
928
- .put(/.*/)
929
- .reply(200, () => data);
930
-
931
- const { result: mutationResult } = renderHook(
932
- () =>
933
- useClientQueries(schema).user.useUpdate({
934
- optimisticUpdate: true,
935
- invalidateQueries: false,
936
- }),
937
- {
938
- wrapper,
939
- },
940
- );
941
-
942
- act(() => mutationResult.current.mutate({ ...queryArgs, data: { name: 'bar' } }));
943
-
944
- await waitFor(() => {
945
- const cacheData = queryClient.getQueryData(
946
- getQueryKey('User', 'findUnique', queryArgs, { infinite: false, optimisticUpdate: true }),
947
- );
948
- expect(cacheData).toMatchObject({ name: 'bar', $optimistic: true });
949
- });
950
- });
951
-
952
- it('works with optimistic update updating nested query', async () => {
953
- const { queryClient, wrapper } = createWrapper();
954
-
955
- const queryArgs = { where: { id: '1' }, include: { posts: true } };
956
- const data = { id: '1', name: 'foo', posts: [{ id: 'p1', title: 'post1' }] };
957
-
958
- nock(makeUrl('User', 'findUnique', queryArgs))
959
- .get(/.*/)
960
- .reply(200, () => ({ data }))
961
- .persist();
962
-
963
- const { result } = renderHook(
964
- () => useClientQueries(schema).user.useFindUnique(queryArgs, { optimisticUpdate: true }),
965
- {
966
- wrapper,
967
- },
968
- );
969
- await waitFor(() => {
970
- expect(result.current.data).toMatchObject({ name: 'foo' });
971
- });
972
-
973
- nock(makeUrl('Post', 'update'))
974
- .put(/.*/)
975
- .reply(200, () => data);
976
-
977
- const { result: mutationResult } = renderHook(
978
- () =>
979
- useClientQueries(schema).post.useUpdate({
980
- optimisticUpdate: true,
981
- invalidateQueries: false,
982
- }),
983
- {
984
- wrapper,
985
- },
986
- );
987
-
988
- act(() =>
989
- mutationResult.current.mutate({
990
- where: { id: 'p1' },
991
- data: { title: 'post2', owner: { connect: { id: '2' } } },
992
- }),
993
- );
994
-
995
- await waitFor(() => {
996
- const cacheData: any = queryClient.getQueryData(
997
- getQueryKey('User', 'findUnique', queryArgs, { infinite: false, optimisticUpdate: true }),
998
- );
999
- expect(cacheData.posts[0]).toMatchObject({ title: 'post2', $optimistic: true, ownerId: '2' });
1000
- });
1001
- });
1002
-
1003
- it('works with optimistic nested update updating query', async () => {
1004
- const { queryClient, wrapper } = createWrapper();
1005
-
1006
- const queryArgs = { where: { id: 'p1' } };
1007
- const data = { id: 'p1', title: 'post1' };
1008
-
1009
- nock(makeUrl('Post', 'findUnique', queryArgs))
1010
- .get(/.*/)
1011
- .reply(200, () => ({ data }))
1012
- .persist();
1013
-
1014
- const { result } = renderHook(
1015
- () => useClientQueries(schema).post.useFindUnique(queryArgs, { optimisticUpdate: true }),
1016
- {
1017
- wrapper,
1018
- },
1019
- );
1020
- await waitFor(() => {
1021
- expect(result.current.data).toMatchObject({ title: 'post1' });
1022
- });
1023
-
1024
- nock(makeUrl('User', 'update'))
1025
- .put(/.*/)
1026
- .reply(200, () => data);
1027
-
1028
- const { result: mutationResult } = renderHook(
1029
- () =>
1030
- useClientQueries(schema).user.useUpdate({
1031
- optimisticUpdate: true,
1032
- invalidateQueries: false,
1033
- }),
1034
- {
1035
- wrapper,
1036
- },
1037
- );
1038
-
1039
- act(() =>
1040
- mutationResult.current.mutate({
1041
- where: { id: '1' },
1042
- data: { posts: { update: { where: { id: 'p1' }, data: { title: 'post2' } } } },
1043
- }),
1044
- );
1045
-
1046
- await waitFor(() => {
1047
- const cacheData: any = queryClient.getQueryData(
1048
- getQueryKey('Post', 'findUnique', queryArgs, { infinite: false, optimisticUpdate: true }),
1049
- );
1050
- expect(cacheData).toMatchObject({ title: 'post2', $optimistic: true });
1051
- });
1052
- });
1053
-
1054
- it('works with optimistic upsert - create simple', async () => {
1055
- const { queryClient, wrapper } = createWrapper();
1056
-
1057
- const data: any[] = [];
1058
-
1059
- nock(makeUrl('User', 'findMany'))
1060
- .get(/.*/)
1061
- .reply(200, () => ({ data }))
1062
- .persist();
1063
-
1064
- const { result } = renderHook(
1065
- () => useClientQueries(schema).user.useFindMany(undefined, { optimisticUpdate: true }),
1066
- {
1067
- wrapper,
1068
- },
1069
- );
1070
- await waitFor(() => {
1071
- expect(result.current.data).toHaveLength(0);
1072
- });
1073
-
1074
- nock(makeUrl('User', 'upsert'))
1075
- .post(/.*/)
1076
- .reply(200, () => ({ data: null }));
1077
-
1078
- const { result: mutationResult } = renderHook(
1079
- () =>
1080
- useClientQueries(schema).user.useUpsert({
1081
- optimisticUpdate: true,
1082
- invalidateQueries: false,
1083
- }),
1084
- {
1085
- wrapper,
1086
- },
1087
- );
1088
-
1089
- act(() =>
1090
- mutationResult.current.mutate({
1091
- where: { id: '1' },
1092
- create: { id: '1', email: 'foo' },
1093
- update: { email: 'bar' },
1094
- }),
1095
- );
1096
-
1097
- await waitFor(() => {
1098
- const cacheData: any = queryClient.getQueryData(
1099
- getQueryKey('User', 'findMany', undefined, { infinite: false, optimisticUpdate: true }),
1100
- );
1101
- expect(cacheData).toHaveLength(1);
1102
- expect(cacheData[0]).toMatchObject({ id: '1', email: 'foo', $optimistic: true });
1103
- });
1104
- });
1105
-
1106
- it('works with optimistic upsert - create updating nested query', async () => {
1107
- const { queryClient, wrapper } = createWrapper();
1108
-
1109
- const data: any = { id: '1', name: 'user1', posts: [{ id: 'p1', title: 'post1' }] };
1110
-
1111
- nock(makeUrl('User', 'findUnique'))
1112
- .get(/.*/)
1113
- .reply(200, () => ({ data }))
1114
- .persist();
1115
-
1116
- const { result } = renderHook(
1117
- () => useClientQueries(schema).user.useFindUnique({ where: { id: '1' } }, { optimisticUpdate: true }),
1118
- {
1119
- wrapper,
1120
- },
1121
- );
1122
- await waitFor(() => {
1123
- expect(result.current.data).toMatchObject({ id: '1' });
1124
- });
1125
-
1126
- nock(makeUrl('Post', 'upsert'))
1127
- .post(/.*/)
1128
- .reply(200, () => ({ data: null }));
1129
-
1130
- const { result: mutationResult } = renderHook(
1131
- () =>
1132
- useClientQueries(schema).post.useUpsert({
1133
- optimisticUpdate: true,
1134
- invalidateQueries: false,
1135
- }),
1136
- {
1137
- wrapper,
1138
- },
1139
- );
1140
-
1141
- act(() =>
1142
- mutationResult.current.mutate({
1143
- where: { id: 'p2' },
1144
- create: { id: 'p2', title: 'post2', owner: { connect: { id: '1' } } },
1145
- update: { title: 'post3' },
1146
- }),
1147
- );
1148
-
1149
- await waitFor(() => {
1150
- const cacheData: any = queryClient.getQueryData(
1151
- getQueryKey('User', 'findUnique', { where: { id: '1' } }, { infinite: false, optimisticUpdate: true }),
1152
- );
1153
- const posts = cacheData.posts;
1154
- expect(posts).toHaveLength(2);
1155
- expect(posts[0]).toMatchObject({ id: 'p2', title: 'post2', ownerId: '1', $optimistic: true });
1156
- });
1157
- });
1158
-
1159
- it('works with optimistic upsert - nested create updating query', async () => {
1160
- const { queryClient, wrapper } = createWrapper();
1161
-
1162
- const data: any = [{ id: 'p1', title: 'post1' }];
1163
-
1164
- nock(makeUrl('Post', 'findMany'))
1165
- .get(/.*/)
1166
- .reply(200, () => ({ data }))
1167
- .persist();
1168
-
1169
- const { result } = renderHook(
1170
- () => useClientQueries(schema).post.useFindMany(undefined, { optimisticUpdate: true }),
1171
- {
1172
- wrapper,
1173
- },
1174
- );
1175
- await waitFor(() => {
1176
- expect(result.current.data).toHaveLength(1);
1177
- });
1178
-
1179
- nock(makeUrl('User', 'update'))
1180
- .post(/.*/)
1181
- .reply(200, () => ({ data: null }));
1182
-
1183
- const { result: mutationResult } = renderHook(
1184
- () =>
1185
- useClientQueries(schema).user.useUpdate({
1186
- optimisticUpdate: true,
1187
- invalidateQueries: false,
1188
- }),
1189
- {
1190
- wrapper,
1191
- },
1192
- );
1193
-
1194
- act(() =>
1195
- mutationResult.current.mutate({
1196
- where: { id: '1' },
1197
- data: {
1198
- posts: {
1199
- upsert: {
1200
- where: { id: 'p2' },
1201
- create: { id: 'p2', title: 'post2' },
1202
- update: { title: 'post3' },
1203
- },
1204
- },
1205
- },
1206
- }),
1207
- );
1208
-
1209
- await waitFor(() => {
1210
- const cacheData: any = queryClient.getQueryData(
1211
- getQueryKey('Post', 'findMany', undefined, { infinite: false, optimisticUpdate: true }),
1212
- );
1213
- expect(cacheData).toHaveLength(2);
1214
- expect(cacheData[0]).toMatchObject({ id: 'p2', title: 'post2', $optimistic: true });
1215
- });
1216
- });
1217
-
1218
- it('works with optimistic upsert - update simple', async () => {
1219
- const { queryClient, wrapper } = createWrapper();
1220
-
1221
- const queryArgs = { where: { id: '1' } };
1222
- const data = { id: '1', name: 'foo' };
1223
-
1224
- nock(makeUrl('User', 'findUnique', queryArgs))
1225
- .get(/.*/)
1226
- .reply(200, () => ({ data }))
1227
- .persist();
1228
-
1229
- const { result } = renderHook(
1230
- () => useClientQueries(schema).user.useFindUnique(queryArgs, { optimisticUpdate: true }),
1231
- {
1232
- wrapper,
1233
- },
1234
- );
1235
- await waitFor(() => {
1236
- expect(result.current.data).toMatchObject({ name: 'foo' });
1237
- });
1238
-
1239
- nock(makeUrl('User', 'upsert'))
1240
- .post(/.*/)
1241
- .reply(200, () => data);
1242
-
1243
- const { result: mutationResult } = renderHook(
1244
- () =>
1245
- useClientQueries(schema).user.useUpsert({
1246
- optimisticUpdate: true,
1247
- invalidateQueries: false,
1248
- }),
1249
- {
1250
- wrapper,
1251
- },
1252
- );
1253
-
1254
- act(() => mutationResult.current.mutate({ ...queryArgs, update: { email: 'bar' }, create: { email: 'zee' } }));
1255
-
1256
- await waitFor(() => {
1257
- const cacheData = queryClient.getQueryData(
1258
- getQueryKey('User', 'findUnique', queryArgs, { infinite: false, optimisticUpdate: true }),
1259
- );
1260
- expect(cacheData).toMatchObject({ email: 'bar', $optimistic: true });
1261
- });
1262
- });
1263
-
1264
- it('works with optimistic upsert - update updating nested query', async () => {
1265
- const { queryClient, wrapper } = createWrapper();
1266
-
1267
- const data: any = { id: '1', name: 'user1', posts: [{ id: 'p1', title: 'post1' }] };
1268
-
1269
- nock(makeUrl('User', 'findUnique'))
1270
- .get(/.*/)
1271
- .reply(200, () => ({ data }))
1272
- .persist();
1273
-
1274
- const { result } = renderHook(
1275
- () => useClientQueries(schema).user.useFindUnique({ where: { id: '1' } }, { optimisticUpdate: true }),
1276
- {
1277
- wrapper,
1278
- },
1279
- );
1280
- await waitFor(() => {
1281
- expect(result.current.data).toMatchObject({ id: '1' });
1282
- });
1283
-
1284
- nock(makeUrl('Post', 'upsert'))
1285
- .post(/.*/)
1286
- .reply(200, () => ({ data: null }));
1287
-
1288
- const { result: mutationResult } = renderHook(
1289
- () =>
1290
- useClientQueries(schema).post.useUpsert({
1291
- optimisticUpdate: true,
1292
- invalidateQueries: false,
1293
- }),
1294
- {
1295
- wrapper,
1296
- },
1297
- );
1298
-
1299
- act(() =>
1300
- mutationResult.current.mutate({
1301
- where: { id: 'p1' },
1302
- create: { id: 'p1', title: 'post1' },
1303
- update: { title: 'post2' },
1304
- }),
1305
- );
1306
-
1307
- await waitFor(() => {
1308
- const cacheData: any = queryClient.getQueryData(
1309
- getQueryKey('User', 'findUnique', { where: { id: '1' } }, { infinite: false, optimisticUpdate: true }),
1310
- );
1311
- const posts = cacheData.posts;
1312
- expect(posts).toHaveLength(1);
1313
- expect(posts[0]).toMatchObject({ id: 'p1', title: 'post2', $optimistic: true });
1314
- });
1315
- });
1316
-
1317
- it('works with optimistic upsert - nested update updating query', async () => {
1318
- const { queryClient, wrapper } = createWrapper();
1319
-
1320
- const data: any = [{ id: 'p1', title: 'post1' }];
1321
-
1322
- nock(makeUrl('Post', 'findMany'))
1323
- .get(/.*/)
1324
- .reply(200, () => ({ data }))
1325
- .persist();
1326
-
1327
- const { result } = renderHook(
1328
- () => useClientQueries(schema).post.useFindMany(undefined, { optimisticUpdate: true }),
1329
- {
1330
- wrapper,
1331
- },
1332
- );
1333
- await waitFor(() => {
1334
- expect(result.current.data).toHaveLength(1);
1335
- });
1336
-
1337
- nock(makeUrl('User', 'update'))
1338
- .post(/.*/)
1339
- .reply(200, () => ({ data: null }));
1340
-
1341
- const { result: mutationResult } = renderHook(
1342
- () =>
1343
- useClientQueries(schema).user.useUpdate({
1344
- optimisticUpdate: true,
1345
- invalidateQueries: false,
1346
- }),
1347
- {
1348
- wrapper,
1349
- },
1350
- );
1351
-
1352
- act(() =>
1353
- mutationResult.current.mutate({
1354
- where: { id: '1' },
1355
- data: {
1356
- posts: {
1357
- upsert: {
1358
- where: { id: 'p1' },
1359
- create: { id: 'p1', title: 'post1' },
1360
- update: { title: 'post2' },
1361
- },
1362
- },
1363
- },
1364
- }),
1365
- );
1366
-
1367
- await waitFor(() => {
1368
- const cacheData: any = queryClient.getQueryData(
1369
- getQueryKey('Post', 'findMany', undefined, { infinite: false, optimisticUpdate: true }),
1370
- );
1371
- expect(cacheData).toHaveLength(1);
1372
- expect(cacheData[0]).toMatchObject({ id: 'p1', title: 'post2', $optimistic: true });
1373
- });
1374
- });
1375
-
1376
- it('works with delete and invalidation', async () => {
1377
- const { queryClient, wrapper } = createWrapper();
1378
-
1379
- const data: any[] = [{ id: '1', name: 'foo' }];
1380
-
1381
- nock(makeUrl('User', 'findMany'))
1382
- .get(/.*/)
1383
- .reply(200, () => ({ data }))
1384
- .persist();
1385
-
1386
- const { result } = renderHook(() => useClientQueries(schema).user.useFindMany(), {
1387
- wrapper,
1388
- });
1389
- await waitFor(() => {
1390
- expect(result.current.data).toHaveLength(1);
1391
- });
1392
-
1393
- nock(makeUrl('User', 'delete'))
1394
- .delete(/.*/)
1395
- .reply(200, () => {
1396
- data.splice(0, 1);
1397
- return { data: [] };
1398
- });
1399
-
1400
- const { result: mutationResult } = renderHook(() => useClientQueries(schema).user.useDelete(), {
1401
- wrapper,
1402
- });
1403
-
1404
- act(() => mutationResult.current.mutate({ where: { id: '1' } }));
1405
-
1406
- await waitFor(() => {
1407
- const cacheData = queryClient.getQueryData(getQueryKey('User', 'findMany', undefined));
1408
- expect(cacheData).toHaveLength(0);
1409
- });
1410
- });
1411
-
1412
- it('works with optimistic delete simple', async () => {
1413
- const { queryClient, wrapper } = createWrapper();
1414
-
1415
- const data: any[] = [{ id: '1', name: 'foo' }];
1416
-
1417
- nock(makeUrl('User', 'findMany'))
1418
- .get(/.*/)
1419
- .reply(200, () => ({ data }))
1420
- .persist();
1421
-
1422
- const { result } = renderHook(
1423
- () => useClientQueries(schema).user.useFindMany(undefined, { optimisticUpdate: true }),
1424
- {
1425
- wrapper,
1426
- },
1427
- );
1428
- await waitFor(() => {
1429
- expect(result.current.data).toHaveLength(1);
1430
- });
1431
-
1432
- nock(makeUrl('User', 'delete'))
1433
- .delete(/.*/)
1434
- .reply(200, () => ({ data }));
1435
-
1436
- const { result: mutationResult } = renderHook(
1437
- () =>
1438
- useClientQueries(schema).user.useDelete({
1439
- optimisticUpdate: true,
1440
- invalidateQueries: false,
1441
- }),
1442
- {
1443
- wrapper,
1444
- },
1445
- );
1446
-
1447
- act(() => mutationResult.current.mutate({ where: { id: '1' } }));
1448
-
1449
- await waitFor(() => {
1450
- const cacheData = queryClient.getQueryData(
1451
- getQueryKey('User', 'findMany', undefined, { infinite: false, optimisticUpdate: true }),
1452
- );
1453
- expect(cacheData).toHaveLength(0);
1454
- });
1455
- });
1456
-
1457
- it('works with optimistic delete nested query', async () => {
1458
- const { queryClient, wrapper } = createWrapper();
1459
-
1460
- const data: any = { id: '1', name: 'foo', posts: [{ id: 'p1', title: 'post1' }] };
1461
-
1462
- nock(makeUrl('User', 'findFirst'))
1463
- .get(/.*/)
1464
- .reply(200, () => ({ data }))
1465
- .persist();
1466
-
1467
- const { result } = renderHook(
1468
- () =>
1469
- useClientQueries(schema).user.useFindFirst(
1470
- {
1471
- include: { posts: true },
1472
- },
1473
- { optimisticUpdate: true },
1474
- ),
1475
- {
1476
- wrapper,
1477
- },
1478
- );
1479
- await waitFor(() => {
1480
- expect(result.current.data).toMatchObject({ id: '1' });
1481
- });
1482
-
1483
- nock(makeUrl('Post', 'delete'))
1484
- .delete(/.*/)
1485
- .reply(200, () => ({ data }));
1486
-
1487
- const { result: mutationResult } = renderHook(
1488
- () =>
1489
- useClientQueries(schema).post.useDelete({
1490
- optimisticUpdate: true,
1491
- invalidateQueries: false,
1492
- }),
1493
- {
1494
- wrapper,
1495
- },
1496
- );
1497
-
1498
- act(() => mutationResult.current.mutate({ where: { id: 'p1' } }));
1499
-
1500
- await waitFor(() => {
1501
- const cacheData: any = queryClient.getQueryData(
1502
- getQueryKey(
1503
- 'User',
1504
- 'findFirst',
1505
- { include: { posts: true } },
1506
- { infinite: false, optimisticUpdate: true },
1507
- ),
1508
- );
1509
- expect(cacheData.posts).toHaveLength(0);
1510
- });
1511
- });
1512
-
1513
- it('works with optimistic nested delete update query', async () => {
1514
- const { queryClient, wrapper } = createWrapper();
1515
-
1516
- const data: any = [
1517
- { id: 'p1', title: 'post1' },
1518
- { id: 'p2', title: 'post2' },
1519
- ];
1520
-
1521
- nock(makeUrl('Post', 'findMany'))
1522
- .get(/.*/)
1523
- .reply(200, () => ({ data }))
1524
- .persist();
1525
-
1526
- const { result } = renderHook(
1527
- () => useClientQueries(schema).post.useFindMany(undefined, { optimisticUpdate: true }),
1528
- {
1529
- wrapper,
1530
- },
1531
- );
1532
- await waitFor(() => {
1533
- expect(result.current.data).toHaveLength(2);
1534
- });
1535
-
1536
- nock(makeUrl('User', 'update'))
1537
- .put(/.*/)
1538
- .reply(200, () => ({ data }));
1539
-
1540
- const { result: mutationResult } = renderHook(
1541
- () =>
1542
- useClientQueries(schema).user.useUpdate({
1543
- optimisticUpdate: true,
1544
- invalidateQueries: false,
1545
- }),
1546
- {
1547
- wrapper,
1548
- },
1549
- );
1550
-
1551
- act(() => mutationResult.current.mutate({ where: { id: '1' }, data: { posts: { delete: { id: 'p1' } } } }));
1552
-
1553
- await waitFor(() => {
1554
- const cacheData: any = queryClient.getQueryData(
1555
- getQueryKey('Post', 'findMany', undefined, { infinite: false, optimisticUpdate: true }),
1556
- );
1557
- expect(cacheData).toHaveLength(1);
1558
- });
1559
- });
1560
-
1561
- it('top-level mutation and nested-read invalidation', async () => {
1562
- const { queryClient, wrapper } = createWrapper();
1563
-
1564
- const queryArgs = { where: { id: '1' }, include: { posts: true } };
1565
- const data = { posts: [{ id: '1', title: 'post1' }] };
1566
-
1567
- nock(makeUrl('User', 'findUnique', queryArgs))
1568
- .get(/.*/)
1569
- .reply(200, () => ({ data }))
1570
- .persist();
1571
-
1572
- const { result } = renderHook(() => useClientQueries(schema).user.useFindUnique(queryArgs), {
1573
- wrapper,
1574
- });
1575
- await waitFor(() => {
1576
- expect(result.current.data).toMatchObject(data);
1577
- });
1578
-
1579
- nock(makeUrl('Post', 'update'))
1580
- .put(/.*/)
1581
- .reply(200, () => {
1582
- data.posts[0]!.title = 'post2';
1583
- return data;
1584
- });
1585
-
1586
- const { result: mutationResult } = renderHook(() => useClientQueries(schema).post.useUpdate(), {
1587
- wrapper,
1588
- });
1589
-
1590
- act(() => mutationResult.current.mutate({ where: { id: '1' }, data: { title: 'post2' } }));
1591
-
1592
- await waitFor(() => {
1593
- const cacheData: any = queryClient.getQueryData(getQueryKey('User', 'findUnique', queryArgs));
1594
- expect(cacheData.posts[0].title).toBe('post2');
1595
- });
1596
- });
1597
-
1598
- it('nested mutation and top-level-read invalidation', async () => {
1599
- const { queryClient, wrapper } = createWrapper();
1600
-
1601
- const data = [{ id: '1', title: 'post1', ownerId: '1' }];
1602
-
1603
- nock(makeUrl('Post', 'findMany'))
1604
- .get(/.*/)
1605
- .reply(200, () => ({
1606
- data,
1607
- }))
1608
- .persist();
1609
-
1610
- const { result } = renderHook(() => useClientQueries(schema).post.useFindMany(), {
1611
- wrapper,
1612
- });
1613
- await waitFor(() => {
1614
- expect(result.current.data).toMatchObject(data);
1615
- });
1616
-
1617
- nock(makeUrl('User', 'update'))
1618
- .put(/.*/)
1619
- .reply(200, () => {
1620
- data.push({ id: '2', title: 'post2', ownerId: '1' });
1621
- return data;
1622
- });
1623
-
1624
- const { result: mutationResult } = renderHook(() => useClientQueries(schema).user.useUpdate(), {
1625
- wrapper,
1626
- });
1627
-
1628
- act(() =>
1629
- mutationResult.current.mutate({ where: { id: '1' }, data: { posts: { create: { title: 'post2' } } } }),
1630
- );
1631
-
1632
- await waitFor(() => {
1633
- const cacheData: any = queryClient.getQueryData(getQueryKey('Post', 'findMany', undefined));
1634
- expect(cacheData).toHaveLength(2);
1635
- });
1636
- });
1637
-
1638
- it('optimistic create with custom provider', async () => {
1639
- const { queryClient, wrapper } = createWrapper();
1640
-
1641
- const data: any[] = [];
1642
-
1643
- nock(makeUrl('User', 'findMany'))
1644
- .get(/.*/)
1645
- .reply(200, () => ({ data }))
1646
- .persist();
1647
-
1648
- const { result } = renderHook(
1649
- () => useClientQueries(schema).user.useFindMany(undefined, { optimisticUpdate: true }),
1650
- {
1651
- wrapper,
1652
- },
1653
- );
1654
- await waitFor(() => {
1655
- expect(result.current.data).toHaveLength(0);
1656
- });
1657
-
1658
- nock(makeUrl('User', 'create'))
1659
- .post(/.*/)
1660
- .reply(200, () => ({ data: null }))
1661
- .persist();
1662
-
1663
- const { result: mutationResult1 } = renderHook(
1664
- () =>
1665
- useClientQueries(schema).user.useCreate({
1666
- optimisticUpdate: true,
1667
- invalidateQueries: false,
1668
- optimisticDataProvider: ({ queryModel, queryOperation }) => {
1669
- if (queryModel === 'User' && queryOperation === 'findMany') {
1670
- return { kind: 'Skip' };
1671
- } else {
1672
- return { kind: 'ProceedDefault' };
1673
- }
1674
- },
1675
- }),
1676
- {
1677
- wrapper,
1678
- },
1679
- );
1680
-
1681
- act(() => mutationResult1.current.mutate({ data: { email: 'foo' } }));
1682
-
1683
- // cache should not update
1684
- await waitFor(() => {
1685
- const cacheData: any = queryClient.getQueryData(
1686
- getQueryKey('User', 'findMany', undefined, { infinite: false, optimisticUpdate: true }),
1687
- );
1688
- expect(cacheData).toHaveLength(0);
1689
- });
1690
-
1691
- const { result: mutationResult2 } = renderHook(
1692
- () =>
1693
- useClientQueries(schema).user.useCreate({
1694
- optimisticUpdate: true,
1695
- invalidateQueries: false,
1696
- optimisticDataProvider: ({ queryModel, queryOperation, currentData, mutationArgs }) => {
1697
- if (queryModel === 'User' && queryOperation === 'findMany') {
1698
- return {
1699
- kind: 'Update',
1700
- data: [
1701
- ...currentData,
1702
- { id: 100, email: mutationArgs.data.email + 'hooray', $optimistic: true },
1703
- ],
1704
- };
1705
- } else {
1706
- return { kind: 'ProceedDefault' };
1707
- }
1708
- },
1709
- }),
1710
- {
1711
- wrapper,
1712
- },
1713
- );
1714
-
1715
- act(() => mutationResult2.current.mutate({ data: { email: 'foo' } }));
1716
-
1717
- // cache should update
1718
- await waitFor(() => {
1719
- const cacheData: any = queryClient.getQueryData(
1720
- getQueryKey('User', 'findMany', undefined, { infinite: false, optimisticUpdate: true }),
1721
- );
1722
- expect(cacheData).toHaveLength(1);
1723
- expect(cacheData[0].$optimistic).toBe(true);
1724
- expect(cacheData[0].id).toBeTruthy();
1725
- expect(cacheData[0].email).toBe('foohooray');
1726
- });
1727
- });
1728
-
1729
- it('optimistic update mixed with non-zenstack queries', async () => {
1730
- const { queryClient, wrapper } = createWrapper();
1731
-
1732
- // non-zenstack query
1733
- const { result: myQueryResult } = renderHook(
1734
- () => useQuery({ queryKey: ['myQuery'], queryFn: () => ({ data: 'myData' }) }),
1735
- {
1736
- wrapper,
1737
- },
1738
- );
1739
- await waitFor(() => {
1740
- expect(myQueryResult.current.data).toEqual({ data: 'myData' });
1741
- });
1742
-
1743
- const data: any[] = [];
1744
-
1745
- nock(makeUrl('User', 'findMany'))
1746
- .get(/.*/)
1747
- .reply(200, () => ({ data }))
1748
- .persist();
1749
-
1750
- const { result } = renderHook(
1751
- () => useClientQueries(schema).user.useFindMany(undefined, { optimisticUpdate: true }),
1752
- {
1753
- wrapper,
1754
- },
1755
- );
1756
- await waitFor(() => {
1757
- expect(result.current.data).toHaveLength(0);
1758
- });
1759
-
1760
- nock(makeUrl('User', 'create'))
1761
- .post(/.*/)
1762
- .reply(200, () => ({ data: null }));
1763
-
1764
- const { result: mutationResult } = renderHook(
1765
- () =>
1766
- useClientQueries(schema).user.useCreate({
1767
- optimisticUpdate: true,
1768
- invalidateQueries: false,
1769
- }),
1770
- {
1771
- wrapper,
1772
- },
1773
- );
1774
-
1775
- act(() => mutationResult.current.mutate({ data: { email: 'foo' } }));
1776
-
1777
- await waitFor(() => {
1778
- const cacheData: any = queryClient.getQueryData(
1779
- getQueryKey('User', 'findMany', undefined, { infinite: false, optimisticUpdate: true }),
1780
- );
1781
- expect(cacheData).toHaveLength(1);
1782
- expect(cacheData[0].$optimistic).toBe(true);
1783
- expect(cacheData[0].id).toBeTruthy();
1784
- expect(cacheData[0].email).toBe('foo');
1785
- });
1786
- });
1787
- });