@openapi-qraft/react 1.0.0-beta.4 → 1.0.0-beta.6
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/CHANGELOG.md +14 -0
- package/README.md +35 -0
- package/dist/ServiceOperation.d.ts +58 -9
- package/dist/ServiceOperation.d.ts.map +1 -1
- package/dist/callbacks/getMutationKey.d.ts +2 -2
- package/dist/callbacks/getMutationKey.d.ts.map +1 -1
- package/dist/callbacks/getMutationKey.js +2 -19
- package/dist/callbacks/getMutationKey.js.map +1 -1
- package/dist/callbacks/useInfiniteQuery.d.ts +0 -6
- package/dist/callbacks/useInfiniteQuery.d.ts.map +1 -1
- package/dist/callbacks/useInfiniteQuery.js +1 -27
- package/dist/callbacks/useInfiniteQuery.js.map +1 -1
- package/dist/callbacks/useMutation.d.ts.map +1 -1
- package/dist/callbacks/useMutation.js +4 -16
- package/dist/callbacks/useMutation.js.map +1 -1
- package/dist/callbacks/useMutationState.d.ts +7 -0
- package/dist/callbacks/useMutationState.d.ts.map +1 -0
- package/dist/callbacks/useMutationState.js +30 -0
- package/dist/callbacks/useMutationState.js.map +1 -0
- package/dist/callbacks/useSuspenseInfiniteQuery.d.ts +9 -0
- package/dist/callbacks/useSuspenseInfiniteQuery.d.ts.map +1 -0
- package/dist/callbacks/useSuspenseInfiniteQuery.js +25 -0
- package/dist/callbacks/useSuspenseInfiniteQuery.js.map +1 -0
- package/dist/callbacks/useSuspenseQuery.d.ts +9 -0
- package/dist/callbacks/useSuspenseQuery.d.ts.map +1 -0
- package/dist/callbacks/useSuspenseQuery.js +28 -0
- package/dist/callbacks/useSuspenseQuery.js.map +1 -0
- package/dist/lib/composeMutationKey.d.ts +10 -0
- package/dist/lib/composeMutationKey.d.ts.map +1 -0
- package/dist/lib/composeMutationKey.js +21 -0
- package/dist/lib/composeMutationKey.js.map +1 -0
- package/dist/lib/shelfMerge.d.ts +7 -0
- package/dist/lib/shelfMerge.d.ts.map +1 -0
- package/dist/lib/shelfMerge.js +28 -0
- package/dist/lib/shelfMerge.js.map +1 -0
- package/package.json +2 -2
- package/src/ServiceOperation.ts +156 -8
- package/src/callbacks/getMutationKey.ts +6 -34
- package/src/callbacks/useInfiniteQuery.ts +1 -36
- package/src/callbacks/useMutation.ts +7 -19
- package/src/callbacks/useMutationState.ts +73 -0
- package/src/callbacks/useSuspenseInfiniteQuery.ts +60 -0
- package/src/callbacks/useSuspenseQuery.ts +64 -0
- package/src/lib/composeMutationKey.test.ts +43 -0
- package/src/lib/composeMutationKey.ts +50 -0
- package/src/{callbacks → lib}/shelfMerge.test.ts +1 -1
- package/src/lib/shelfMerge.ts +35 -0
- package/src/qraftAPIClient.test.tsx +358 -2
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merges objects with provided depth
|
|
3
|
+
* @param depth
|
|
4
|
+
* @param args
|
|
5
|
+
*/
|
|
6
|
+
export function shelfMerge<T>(depth = 2, ...args: T[]): T {
|
|
7
|
+
return args.reduce((acc, arg) => {
|
|
8
|
+
if (!arg || typeof arg !== 'object') return acc;
|
|
9
|
+
|
|
10
|
+
Object.entries(arg).forEach(([key, value]) => {
|
|
11
|
+
if (typeof value !== 'object') {
|
|
12
|
+
acc[key as never] = value as never;
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (Array.isArray(value)) {
|
|
17
|
+
acc[key as never] = value as never;
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (depth > 1) {
|
|
22
|
+
acc[key as never] = shelfMerge(
|
|
23
|
+
depth - 1,
|
|
24
|
+
acc[key as never],
|
|
25
|
+
value
|
|
26
|
+
) as never;
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
acc[key as never] = value as never;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return acc;
|
|
34
|
+
}, {} as T);
|
|
35
|
+
}
|
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
import { act, renderHook, waitFor } from '@testing-library/react';
|
|
10
10
|
|
|
11
11
|
import { createAPIClient } from './fixtures/api/index.js';
|
|
12
|
-
import { bodySerializer,
|
|
13
|
-
import {
|
|
12
|
+
import { bodySerializer, request, urlSerializer } from './lib/request.js';
|
|
13
|
+
import { QraftContextValue } from './QraftContext.js';
|
|
14
14
|
import type { RequestClient } from './RequestClient.js';
|
|
15
15
|
|
|
16
16
|
const qraft = createAPIClient();
|
|
@@ -130,6 +130,58 @@ describe('Qraft uses Queries', () => {
|
|
|
130
130
|
});
|
|
131
131
|
});
|
|
132
132
|
|
|
133
|
+
describe('Qraft uses Suspense Queries', () => {
|
|
134
|
+
it('supports useSuspenseQuery', async () => {
|
|
135
|
+
const hook = () => {
|
|
136
|
+
try {
|
|
137
|
+
return qraft.approvalPolicies.getApprovalPoliciesId.useSuspenseQuery({
|
|
138
|
+
header: {
|
|
139
|
+
'x-monite-version': '1.0.0',
|
|
140
|
+
},
|
|
141
|
+
path: {
|
|
142
|
+
approval_policy_id: '1',
|
|
143
|
+
},
|
|
144
|
+
query: {
|
|
145
|
+
items_order: ['asc', 'desc'],
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
} catch (error) {
|
|
149
|
+
return error as Promise<unknown>;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const queryClient = new QueryClient();
|
|
154
|
+
|
|
155
|
+
const { result: resultWithErrorPromise } = renderHook(hook, {
|
|
156
|
+
wrapper: (props) => <Providers {...props} queryClient={queryClient} />,
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
expect(resultWithErrorPromise.current).toBeInstanceOf(Promise); // Suspense throws a promise
|
|
160
|
+
|
|
161
|
+
await resultWithErrorPromise.current;
|
|
162
|
+
|
|
163
|
+
const { result: resultWithData } = renderHook(hook, {
|
|
164
|
+
wrapper: (props) => <Providers {...props} queryClient={queryClient} />,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
if (resultWithData.current instanceof Promise) {
|
|
168
|
+
throw new Error('Promise should be resolved');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
expect(resultWithData.current.data).toEqual({
|
|
172
|
+
header: {
|
|
173
|
+
'x-monite-version': '1.0.0',
|
|
174
|
+
},
|
|
175
|
+
path: {
|
|
176
|
+
approval_policy_id: '1',
|
|
177
|
+
},
|
|
178
|
+
query: {
|
|
179
|
+
items_order: ['asc', 'desc'],
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
133
185
|
describe('Qraft uses Infinite Queries', () => {
|
|
134
186
|
it('supports useInfiniteQuery', async () => {
|
|
135
187
|
const { result } = renderHook(
|
|
@@ -292,6 +344,86 @@ describe('Qraft uses Infinite Queries', () => {
|
|
|
292
344
|
});
|
|
293
345
|
});
|
|
294
346
|
|
|
347
|
+
describe('Qraft uses Suspense Infinite Queries', () => {
|
|
348
|
+
it('supports useSuspenseInfiniteQuery', async () => {
|
|
349
|
+
const hook = () => {
|
|
350
|
+
try {
|
|
351
|
+
return qraft.files.getFiles.useSuspenseInfiniteQuery(
|
|
352
|
+
{
|
|
353
|
+
header: {
|
|
354
|
+
'x-monite-version': '1.0.0',
|
|
355
|
+
},
|
|
356
|
+
query: {
|
|
357
|
+
id__in: ['1', '2'],
|
|
358
|
+
},
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
getNextPageParam: (lastPage, allPages, params) => {
|
|
362
|
+
return {
|
|
363
|
+
query: {
|
|
364
|
+
page: params.query?.page
|
|
365
|
+
? String(Number(params.query.page) + 1)
|
|
366
|
+
: undefined,
|
|
367
|
+
},
|
|
368
|
+
};
|
|
369
|
+
},
|
|
370
|
+
initialPageParam: {
|
|
371
|
+
query: {
|
|
372
|
+
page: '1',
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
}
|
|
376
|
+
);
|
|
377
|
+
} catch (error) {
|
|
378
|
+
return error as Promise<unknown>;
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
const queryClient = new QueryClient();
|
|
383
|
+
|
|
384
|
+
const { result } = renderHook(hook, {
|
|
385
|
+
wrapper: (props) => <Providers {...props} queryClient={queryClient} />,
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
const { result: resultWithErrorPromise } = renderHook(hook, {
|
|
389
|
+
wrapper: (props) => <Providers {...props} queryClient={queryClient} />,
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
expect(resultWithErrorPromise.current).toBeInstanceOf(Promise); // Suspense throws a promise
|
|
393
|
+
|
|
394
|
+
await resultWithErrorPromise.current;
|
|
395
|
+
|
|
396
|
+
const { result: resultWithData } = renderHook(hook, {
|
|
397
|
+
wrapper: (props) => <Providers {...props} queryClient={queryClient} />,
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
if (resultWithData.current instanceof Promise) {
|
|
401
|
+
throw new Error('Promise should be resolved');
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
expect(resultWithData.current.data).toEqual({
|
|
405
|
+
pageParams: [
|
|
406
|
+
{
|
|
407
|
+
query: {
|
|
408
|
+
page: '1',
|
|
409
|
+
},
|
|
410
|
+
},
|
|
411
|
+
],
|
|
412
|
+
pages: [
|
|
413
|
+
{
|
|
414
|
+
header: {
|
|
415
|
+
'x-monite-version': '1.0.0',
|
|
416
|
+
},
|
|
417
|
+
query: {
|
|
418
|
+
id__in: ['1', '2'],
|
|
419
|
+
page: '1',
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
],
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
|
|
295
427
|
describe('Qraft uses Mutations', () => {
|
|
296
428
|
it('supports useMutation without predefined parameters', async () => {
|
|
297
429
|
const { result } = renderHook(
|
|
@@ -408,6 +540,230 @@ describe('Qraft uses Mutations', () => {
|
|
|
408
540
|
});
|
|
409
541
|
});
|
|
410
542
|
|
|
543
|
+
describe('Qraft uses Mutation State', () => {
|
|
544
|
+
const parameters = {
|
|
545
|
+
header: {
|
|
546
|
+
'x-monite-version': '1.0.0',
|
|
547
|
+
},
|
|
548
|
+
path: {
|
|
549
|
+
entity_id: '1',
|
|
550
|
+
},
|
|
551
|
+
query: {
|
|
552
|
+
referer: 'https://example.com',
|
|
553
|
+
},
|
|
554
|
+
} as const;
|
|
555
|
+
|
|
556
|
+
it('supports useMutationState with filter', async () => {
|
|
557
|
+
const queryClient = new QueryClient();
|
|
558
|
+
|
|
559
|
+
const { result: mutationResult } = renderHook(
|
|
560
|
+
() => qraft.entities.postEntitiesIdDocuments.useMutation(parameters),
|
|
561
|
+
{
|
|
562
|
+
wrapper: (props) => <Providers {...props} queryClient={queryClient} />,
|
|
563
|
+
}
|
|
564
|
+
);
|
|
565
|
+
|
|
566
|
+
act(() => {
|
|
567
|
+
mutationResult.current.mutate({
|
|
568
|
+
verification_document_back: 'back',
|
|
569
|
+
verification_document_front: 'front',
|
|
570
|
+
});
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
await waitFor(() => {
|
|
574
|
+
expect(mutationResult.current.data).toBeDefined();
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
const { result: mutationStateResult } = renderHook(
|
|
578
|
+
() =>
|
|
579
|
+
qraft.entities.postEntitiesIdDocuments.useMutationState({
|
|
580
|
+
filters: {
|
|
581
|
+
parameters,
|
|
582
|
+
},
|
|
583
|
+
}),
|
|
584
|
+
{
|
|
585
|
+
wrapper: (props) => <Providers {...props} queryClient={queryClient} />,
|
|
586
|
+
}
|
|
587
|
+
);
|
|
588
|
+
|
|
589
|
+
expect(mutationStateResult.current.at(0)?.data).toEqual({
|
|
590
|
+
body: {
|
|
591
|
+
verification_document_back: 'back',
|
|
592
|
+
verification_document_front: 'front',
|
|
593
|
+
},
|
|
594
|
+
...parameters,
|
|
595
|
+
});
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
it('supports useMutationState with filter and select', async () => {
|
|
599
|
+
const queryClient = new QueryClient();
|
|
600
|
+
|
|
601
|
+
const { result: mutationResult } = renderHook(
|
|
602
|
+
() => qraft.entities.postEntitiesIdDocuments.useMutation(parameters),
|
|
603
|
+
{
|
|
604
|
+
wrapper: (props) => <Providers {...props} queryClient={queryClient} />,
|
|
605
|
+
}
|
|
606
|
+
);
|
|
607
|
+
|
|
608
|
+
act(() => {
|
|
609
|
+
mutationResult.current.mutate({
|
|
610
|
+
verification_document_back: 'back',
|
|
611
|
+
verification_document_front: 'front',
|
|
612
|
+
});
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
await waitFor(() => {
|
|
616
|
+
expect(mutationResult.current.data).toBeDefined();
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
const { result: mutationStateResult } = renderHook(
|
|
620
|
+
() =>
|
|
621
|
+
qraft.entities.postEntitiesIdDocuments.useMutationState({
|
|
622
|
+
filters: {
|
|
623
|
+
parameters,
|
|
624
|
+
},
|
|
625
|
+
select(mutation) {
|
|
626
|
+
return (
|
|
627
|
+
mutation.state.data?.header?.['x-monite-version'] ===
|
|
628
|
+
parameters.header['x-monite-version']
|
|
629
|
+
);
|
|
630
|
+
},
|
|
631
|
+
}),
|
|
632
|
+
{
|
|
633
|
+
wrapper: (props) => <Providers {...props} queryClient={queryClient} />,
|
|
634
|
+
}
|
|
635
|
+
);
|
|
636
|
+
|
|
637
|
+
expect(mutationStateResult.current.at(0)).toEqual(true);
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
it('supports useMutationState with without filter', async () => {
|
|
641
|
+
const queryClient = new QueryClient();
|
|
642
|
+
|
|
643
|
+
const { result: mutationResult } = renderHook(
|
|
644
|
+
() => qraft.entities.postEntitiesIdDocuments.useMutation(parameters),
|
|
645
|
+
{
|
|
646
|
+
wrapper: (props) => <Providers {...props} queryClient={queryClient} />,
|
|
647
|
+
}
|
|
648
|
+
);
|
|
649
|
+
|
|
650
|
+
act(() => {
|
|
651
|
+
mutationResult.current.mutate({
|
|
652
|
+
verification_document_back: 'back',
|
|
653
|
+
verification_document_front: 'front',
|
|
654
|
+
});
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
await waitFor(() => {
|
|
658
|
+
expect(mutationResult.current.data).toBeDefined();
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
const { result: mutationStateResult } = renderHook(
|
|
662
|
+
() => qraft.entities.postEntitiesIdDocuments.useMutationState(),
|
|
663
|
+
{
|
|
664
|
+
wrapper: (props) => <Providers {...props} queryClient={queryClient} />,
|
|
665
|
+
}
|
|
666
|
+
);
|
|
667
|
+
|
|
668
|
+
expect(mutationStateResult.current.at(0)?.data).toEqual({
|
|
669
|
+
body: {
|
|
670
|
+
verification_document_back: 'back',
|
|
671
|
+
verification_document_front: 'front',
|
|
672
|
+
},
|
|
673
|
+
...parameters,
|
|
674
|
+
});
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
it('supports useMutationState with mutationKey and select', async () => {
|
|
678
|
+
const queryClient = new QueryClient();
|
|
679
|
+
|
|
680
|
+
const { result: mutationHookResultToMatch } = renderHook(
|
|
681
|
+
() => qraft.entities.postEntitiesIdDocuments.useMutation(parameters),
|
|
682
|
+
{
|
|
683
|
+
wrapper: (props) => <Providers {...props} queryClient={queryClient} />,
|
|
684
|
+
}
|
|
685
|
+
);
|
|
686
|
+
|
|
687
|
+
act(() => {
|
|
688
|
+
mutationHookResultToMatch.current.mutate({
|
|
689
|
+
verification_document_back: 'back',
|
|
690
|
+
verification_document_front: 'front',
|
|
691
|
+
});
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
await waitFor(() => {
|
|
695
|
+
expect(mutationHookResultToMatch.current.data).toBeDefined();
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
const { result: mutationStateHookResult } = renderHook(
|
|
699
|
+
() =>
|
|
700
|
+
qraft.entities.postEntitiesIdDocuments.useMutationState({
|
|
701
|
+
filters: {
|
|
702
|
+
mutationKey:
|
|
703
|
+
qraft.entities.postEntitiesIdDocuments.getMutationKey(parameters),
|
|
704
|
+
},
|
|
705
|
+
select(mutation) {
|
|
706
|
+
return (
|
|
707
|
+
mutation.state.data?.header?.['x-monite-version'] ===
|
|
708
|
+
parameters.header['x-monite-version']
|
|
709
|
+
);
|
|
710
|
+
},
|
|
711
|
+
}),
|
|
712
|
+
{
|
|
713
|
+
wrapper: (props) => <Providers {...props} queryClient={queryClient} />,
|
|
714
|
+
}
|
|
715
|
+
);
|
|
716
|
+
|
|
717
|
+
expect(mutationStateHookResult.current.length).toEqual(1);
|
|
718
|
+
expect(mutationStateHookResult.current.at(0)).toEqual(true);
|
|
719
|
+
});
|
|
720
|
+
|
|
721
|
+
it('supports useMutationState with not partial parameters', async () => {
|
|
722
|
+
const queryClient = new QueryClient();
|
|
723
|
+
|
|
724
|
+
const { result: mutationHookResultToMatch } = renderHook(
|
|
725
|
+
() => qraft.entities.postEntitiesIdDocuments.useMutation(parameters),
|
|
726
|
+
{
|
|
727
|
+
wrapper: (props) => <Providers {...props} queryClient={queryClient} />,
|
|
728
|
+
}
|
|
729
|
+
);
|
|
730
|
+
|
|
731
|
+
act(() => {
|
|
732
|
+
mutationHookResultToMatch.current.mutate({
|
|
733
|
+
verification_document_back: 'back',
|
|
734
|
+
verification_document_front: 'front',
|
|
735
|
+
});
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
await waitFor(() => {
|
|
739
|
+
expect(mutationHookResultToMatch.current.data).toBeDefined();
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
const { result: mutationStateResult } = renderHook(
|
|
743
|
+
() =>
|
|
744
|
+
qraft.entities.postEntitiesIdDocuments.useMutationState({
|
|
745
|
+
filters: {
|
|
746
|
+
parameters: {
|
|
747
|
+
header: parameters.header,
|
|
748
|
+
},
|
|
749
|
+
},
|
|
750
|
+
select(mutation) {
|
|
751
|
+
return (
|
|
752
|
+
mutation.state.data?.header?.['x-monite-version'] ===
|
|
753
|
+
parameters.header['x-monite-version']
|
|
754
|
+
);
|
|
755
|
+
},
|
|
756
|
+
}),
|
|
757
|
+
{
|
|
758
|
+
wrapper: (props) => <Providers {...props} queryClient={queryClient} />,
|
|
759
|
+
}
|
|
760
|
+
);
|
|
761
|
+
|
|
762
|
+
expect(mutationStateResult.current.length).toEqual(1);
|
|
763
|
+
expect(mutationStateResult.current.at(0)).toEqual(true);
|
|
764
|
+
});
|
|
765
|
+
});
|
|
766
|
+
|
|
411
767
|
describe('Qraft uses Query Function', () => {
|
|
412
768
|
it('uses queryFn', async () => {
|
|
413
769
|
const result = await qraft.approvalPolicies.getApprovalPoliciesId.queryFn(
|