@apollo/gateway 2.4.5 → 2.4.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.
Files changed (64) hide show
  1. package/dist/__generated__/graphqlTypes.d.ts +19 -1
  2. package/dist/__generated__/graphqlTypes.d.ts.map +1 -1
  3. package/dist/__generated__/graphqlTypes.js +1 -0
  4. package/dist/__generated__/graphqlTypes.js.map +1 -1
  5. package/package.json +4 -4
  6. package/src/__generated__/graphqlTypes.ts +33 -2
  7. package/src/__mocks__/tsconfig.json +0 -7
  8. package/src/__tests__/.gitkeep +0 -0
  9. package/src/__tests__/CucumberREADME.md +0 -96
  10. package/src/__tests__/build-query-plan.feature +0 -1471
  11. package/src/__tests__/buildQueryPlan.test.ts +0 -1225
  12. package/src/__tests__/executeQueryPlan.conditions.test.ts +0 -1488
  13. package/src/__tests__/executeQueryPlan.introspection.test.ts +0 -140
  14. package/src/__tests__/executeQueryPlan.test.ts +0 -6140
  15. package/src/__tests__/execution-utils.ts +0 -124
  16. package/src/__tests__/gateway/__snapshots__/opentelemetry.test.ts.snap +0 -195
  17. package/src/__tests__/gateway/buildService.test.ts +0 -249
  18. package/src/__tests__/gateway/endToEnd.test.ts +0 -486
  19. package/src/__tests__/gateway/executor.test.ts +0 -96
  20. package/src/__tests__/gateway/extensions.test.ts +0 -37
  21. package/src/__tests__/gateway/lifecycle-hooks.test.ts +0 -239
  22. package/src/__tests__/gateway/opentelemetry.test.ts +0 -123
  23. package/src/__tests__/gateway/queryPlanCache.test.ts +0 -231
  24. package/src/__tests__/gateway/queryPlannerConfig.test.ts +0 -101
  25. package/src/__tests__/gateway/reporting.test.ts +0 -616
  26. package/src/__tests__/gateway/supergraphSdl.test.ts +0 -396
  27. package/src/__tests__/gateway/testUtils.ts +0 -89
  28. package/src/__tests__/integration/abstract-types.test.ts +0 -1861
  29. package/src/__tests__/integration/aliases.test.ts +0 -180
  30. package/src/__tests__/integration/boolean.test.ts +0 -279
  31. package/src/__tests__/integration/complex-key.test.ts +0 -197
  32. package/src/__tests__/integration/configuration.test.ts +0 -404
  33. package/src/__tests__/integration/custom-directives.test.ts +0 -174
  34. package/src/__tests__/integration/execution-style.test.ts +0 -35
  35. package/src/__tests__/integration/fragments.test.ts +0 -237
  36. package/src/__tests__/integration/list-key.test.ts +0 -128
  37. package/src/__tests__/integration/logger.test.ts +0 -122
  38. package/src/__tests__/integration/managed.test.ts +0 -319
  39. package/src/__tests__/integration/merge-arrays.test.ts +0 -34
  40. package/src/__tests__/integration/multiple-key.test.ts +0 -327
  41. package/src/__tests__/integration/mutations.test.ts +0 -287
  42. package/src/__tests__/integration/networkRequests.test.ts +0 -542
  43. package/src/__tests__/integration/nockMocks.ts +0 -157
  44. package/src/__tests__/integration/provides.test.ts +0 -77
  45. package/src/__tests__/integration/requires.test.ts +0 -359
  46. package/src/__tests__/integration/scope.test.ts +0 -557
  47. package/src/__tests__/integration/single-service.test.ts +0 -119
  48. package/src/__tests__/integration/unions.test.ts +0 -79
  49. package/src/__tests__/integration/value-types.test.ts +0 -382
  50. package/src/__tests__/integration/variables.test.ts +0 -120
  51. package/src/__tests__/nockAssertions.ts +0 -20
  52. package/src/__tests__/queryPlanCucumber.test.ts +0 -55
  53. package/src/__tests__/resultShaping.test.ts +0 -605
  54. package/src/__tests__/testSetup.ts +0 -1
  55. package/src/__tests__/tsconfig.json +0 -8
  56. package/src/core/__tests__/core.test.ts +0 -412
  57. package/src/datasources/__tests__/LocalGraphQLDataSource.test.ts +0 -51
  58. package/src/datasources/__tests__/RemoteGraphQLDataSource.test.ts +0 -574
  59. package/src/schema-helper/__tests__/addExtensions.test.ts +0 -70
  60. package/src/supergraphManagers/IntrospectAndCompose/__tests__/IntrospectAndCompose.test.ts +0 -364
  61. package/src/supergraphManagers/IntrospectAndCompose/__tests__/loadServicesFromRemoteEndpoint.test.ts +0 -40
  62. package/src/supergraphManagers/UplinkSupergraphManager/__tests__/UplinkSupergraphManager.test.ts +0 -65
  63. package/src/supergraphManagers/UplinkSupergraphManager/__tests__/loadSupergraphSdlFromStorage.test.ts +0 -511
  64. package/src/utilities/__tests__/deepMerge.test.ts +0 -77
@@ -1,1225 +0,0 @@
1
- import {
2
- astSerializer,
3
- queryPlanSerializer,
4
- } from 'apollo-federation-integration-testsuite';
5
- import { getFederatedTestingSchema } from './execution-utils';
6
- import { QueryPlan, QueryPlanner } from '@apollo/query-planner';
7
- import { Schema, parseOperation } from '@apollo/federation-internals';
8
-
9
- expect.addSnapshotSerializer(astSerializer);
10
- expect.addSnapshotSerializer(queryPlanSerializer);
11
-
12
- describe('buildQueryPlan', () => {
13
- let schema: Schema;
14
- let queryPlanner: QueryPlanner;
15
-
16
- const buildPlan = (operation: string): QueryPlan => {
17
- return queryPlanner.buildQueryPlan(parseOperation(schema, operation));
18
- };
19
-
20
- beforeEach(() => {
21
- expect(
22
- () => ({ schema, queryPlanner } = getFederatedTestingSchema()),
23
- ).not.toThrow();
24
- });
25
-
26
- it(`should not confuse union types with overlapping field names`, () => {
27
- const operationString = `#graphql
28
- query {
29
- body {
30
- ... on Image {
31
- attributes {
32
- url
33
- }
34
- }
35
- ... on Text {
36
- attributes {
37
- bold
38
- text
39
- }
40
- }
41
- }
42
- }
43
- `;
44
- const queryPlan = buildPlan(operationString);
45
-
46
- expect(queryPlan).toMatchInlineSnapshot(`
47
- QueryPlan {
48
- Fetch(service: "documents") {
49
- {
50
- body {
51
- __typename
52
- ... on Image {
53
- attributes {
54
- url
55
- }
56
- }
57
- ... on Text {
58
- attributes {
59
- bold
60
- text
61
- }
62
- }
63
- }
64
- }
65
- },
66
- }
67
- `);
68
- });
69
-
70
- it(`should use a single fetch when requesting a root field from one service`, () => {
71
- const operationString = `#graphql
72
- query {
73
- me {
74
- name {
75
- first
76
- }
77
- }
78
- }
79
- `;
80
-
81
- const queryPlan = buildPlan(operationString);
82
- expect(queryPlan).toMatchInlineSnapshot(`
83
- QueryPlan {
84
- Fetch(service: "accounts") {
85
- {
86
- me {
87
- name {
88
- first
89
- }
90
- }
91
- }
92
- },
93
- }
94
- `);
95
- });
96
-
97
- it(`should use two independent fetches when requesting root fields from two services`, () => {
98
- const operationString = `#graphql
99
- query {
100
- me {
101
- name {
102
- first
103
- }
104
- }
105
- topProducts {
106
- name
107
- }
108
- }
109
- `;
110
-
111
- const queryPlan = buildPlan(operationString);
112
-
113
- expect(queryPlan).toMatchInlineSnapshot(`
114
- QueryPlan {
115
- Parallel {
116
- Fetch(service: "accounts") {
117
- {
118
- me {
119
- name {
120
- first
121
- }
122
- }
123
- }
124
- },
125
- Sequence {
126
- Fetch(service: "product") {
127
- {
128
- topProducts {
129
- __typename
130
- ... on Book {
131
- __typename
132
- isbn
133
- }
134
- ... on Furniture {
135
- name
136
- }
137
- }
138
- }
139
- },
140
- Flatten(path: "topProducts.@") {
141
- Fetch(service: "books") {
142
- {
143
- ... on Book {
144
- __typename
145
- isbn
146
- }
147
- } =>
148
- {
149
- ... on Book {
150
- title
151
- year
152
- }
153
- }
154
- },
155
- },
156
- Flatten(path: "topProducts.@") {
157
- Fetch(service: "product") {
158
- {
159
- ... on Book {
160
- __typename
161
- title
162
- year
163
- isbn
164
- }
165
- } =>
166
- {
167
- ... on Book {
168
- name
169
- }
170
- }
171
- },
172
- },
173
- },
174
- },
175
- }
176
- `);
177
- });
178
-
179
- it(`should use a single fetch when requesting multiple root fields from the same service`, () => {
180
- const operationString = `#graphql
181
- query {
182
- topProducts {
183
- name
184
- }
185
- product(upc: "1") {
186
- name
187
- }
188
- }
189
- `;
190
-
191
- const queryPlan = buildPlan(operationString);
192
-
193
- expect(queryPlan).toMatchInlineSnapshot(`
194
- QueryPlan {
195
- Sequence {
196
- Fetch(service: "product") {
197
- {
198
- topProducts {
199
- __typename
200
- ... on Book {
201
- __typename
202
- isbn
203
- }
204
- ... on Furniture {
205
- name
206
- }
207
- }
208
- product(upc: "1") {
209
- __typename
210
- ... on Book {
211
- __typename
212
- isbn
213
- }
214
- ... on Furniture {
215
- name
216
- }
217
- }
218
- }
219
- },
220
- Parallel {
221
- Sequence {
222
- Flatten(path: "topProducts.@") {
223
- Fetch(service: "books") {
224
- {
225
- ... on Book {
226
- __typename
227
- isbn
228
- }
229
- } =>
230
- {
231
- ... on Book {
232
- title
233
- year
234
- }
235
- }
236
- },
237
- },
238
- Flatten(path: "topProducts.@") {
239
- Fetch(service: "product") {
240
- {
241
- ... on Book {
242
- __typename
243
- title
244
- year
245
- isbn
246
- }
247
- } =>
248
- {
249
- ... on Book {
250
- name
251
- }
252
- }
253
- },
254
- },
255
- },
256
- Sequence {
257
- Flatten(path: "product") {
258
- Fetch(service: "books") {
259
- {
260
- ... on Book {
261
- __typename
262
- isbn
263
- }
264
- } =>
265
- {
266
- ... on Book {
267
- title
268
- year
269
- }
270
- }
271
- },
272
- },
273
- Flatten(path: "product") {
274
- Fetch(service: "product") {
275
- {
276
- ... on Book {
277
- __typename
278
- title
279
- year
280
- isbn
281
- }
282
- } =>
283
- {
284
- ... on Book {
285
- name
286
- }
287
- }
288
- },
289
- },
290
- },
291
- },
292
- },
293
- }
294
- `);
295
- });
296
-
297
- it(`should use a single fetch when requesting relationship subfields from the same service`, () => {
298
- const operationString = `#graphql
299
- query {
300
- topReviews {
301
- body
302
- author {
303
- reviews {
304
- body
305
- }
306
- }
307
- }
308
- }
309
- `;
310
-
311
- const queryPlan = buildPlan(operationString);
312
-
313
- expect(queryPlan).toMatchInlineSnapshot(`
314
- QueryPlan {
315
- Fetch(service: "reviews") {
316
- {
317
- topReviews {
318
- body
319
- author {
320
- reviews {
321
- body
322
- }
323
- }
324
- }
325
- }
326
- },
327
- }
328
- `);
329
- });
330
-
331
- it(`should use a single fetch when requesting relationship subfields and provided keys from the same service`, () => {
332
- const operationString = `#graphql
333
- query {
334
- topReviews {
335
- body
336
- author {
337
- id
338
- reviews {
339
- body
340
- }
341
- }
342
- }
343
- }
344
- `;
345
-
346
- const queryPlan = buildPlan(operationString);
347
-
348
- expect(queryPlan).toMatchInlineSnapshot(`
349
- QueryPlan {
350
- Fetch(service: "reviews") {
351
- {
352
- topReviews {
353
- body
354
- author {
355
- id
356
- reviews {
357
- body
358
- }
359
- }
360
- }
361
- }
362
- },
363
- }
364
- `);
365
- });
366
-
367
- describe(`when requesting an extension field from another service`, () => {
368
- it(`should add the field's representation requirements to the parent selection set and use a dependent fetch`, () => {
369
- const operationString = `#graphql
370
- query {
371
- me {
372
- name {
373
- first
374
- }
375
- reviews {
376
- body
377
- }
378
- }
379
- }
380
- `;
381
-
382
- const queryPlan = buildPlan(operationString);
383
-
384
- expect(queryPlan).toMatchInlineSnapshot(`
385
- QueryPlan {
386
- Sequence {
387
- Fetch(service: "accounts") {
388
- {
389
- me {
390
- __typename
391
- id
392
- name {
393
- first
394
- }
395
- }
396
- }
397
- },
398
- Flatten(path: "me") {
399
- Fetch(service: "reviews") {
400
- {
401
- ... on User {
402
- __typename
403
- id
404
- }
405
- } =>
406
- {
407
- ... on User {
408
- reviews {
409
- body
410
- }
411
- }
412
- }
413
- },
414
- },
415
- },
416
- }
417
- `);
418
- });
419
-
420
- describe(`when the parent selection set is empty`, () => {
421
- it(`should add the field's requirements to the parent selection set and use a dependent fetch`, () => {
422
- const operationString = `#graphql
423
- query {
424
- me {
425
- reviews {
426
- body
427
- }
428
- }
429
- }
430
- `;
431
-
432
- const queryPlan = buildPlan(operationString);
433
-
434
- expect(queryPlan).toMatchInlineSnapshot(`
435
- QueryPlan {
436
- Sequence {
437
- Fetch(service: "accounts") {
438
- {
439
- me {
440
- __typename
441
- id
442
- }
443
- }
444
- },
445
- Flatten(path: "me") {
446
- Fetch(service: "reviews") {
447
- {
448
- ... on User {
449
- __typename
450
- id
451
- }
452
- } =>
453
- {
454
- ... on User {
455
- reviews {
456
- body
457
- }
458
- }
459
- }
460
- },
461
- },
462
- },
463
- }
464
- `);
465
- });
466
- });
467
-
468
- it(`should only add requirements once`, () => {
469
- const operationString = `#graphql
470
- query {
471
- me {
472
- reviews {
473
- body
474
- }
475
- numberOfReviews
476
- }
477
- }
478
- `;
479
-
480
- const queryPlan = buildPlan(operationString);
481
-
482
- expect(queryPlan).toMatchInlineSnapshot(`
483
- QueryPlan {
484
- Sequence {
485
- Fetch(service: "accounts") {
486
- {
487
- me {
488
- __typename
489
- id
490
- }
491
- }
492
- },
493
- Flatten(path: "me") {
494
- Fetch(service: "reviews") {
495
- {
496
- ... on User {
497
- __typename
498
- id
499
- }
500
- } =>
501
- {
502
- ... on User {
503
- reviews {
504
- body
505
- }
506
- numberOfReviews
507
- }
508
- }
509
- },
510
- },
511
- },
512
- }
513
- `);
514
- });
515
- });
516
-
517
- describe(`when requesting a composite field with subfields from another service`, () => {
518
- it(`should add key fields to the parent selection set and use a dependent fetch`, () => {
519
- const operationString = `#graphql
520
- query {
521
- topReviews {
522
- body
523
- author {
524
- name {
525
- first
526
- }
527
- }
528
- }
529
- }
530
- `;
531
-
532
- const queryPlan = buildPlan(operationString);
533
-
534
- expect(queryPlan).toMatchInlineSnapshot(`
535
- QueryPlan {
536
- Sequence {
537
- Fetch(service: "reviews") {
538
- {
539
- topReviews {
540
- body
541
- author {
542
- __typename
543
- id
544
- }
545
- }
546
- }
547
- },
548
- Flatten(path: "topReviews.@.author") {
549
- Fetch(service: "accounts") {
550
- {
551
- ... on User {
552
- __typename
553
- id
554
- }
555
- } =>
556
- {
557
- ... on User {
558
- name {
559
- first
560
- }
561
- }
562
- }
563
- },
564
- },
565
- },
566
- }
567
- `);
568
- });
569
-
570
- describe(`when requesting a field defined in another service which requires a field in the base service`, () => {
571
- it(`should add the field provided by base service in first Fetch`, () => {
572
- const operationString = `#graphql
573
- query {
574
- topCars {
575
- retailPrice
576
- }
577
- }
578
- `;
579
-
580
- const queryPlan = buildPlan(operationString);
581
-
582
- expect(queryPlan).toMatchInlineSnapshot(`
583
- QueryPlan {
584
- Sequence {
585
- Fetch(service: "product") {
586
- {
587
- topCars {
588
- __typename
589
- id
590
- price
591
- }
592
- }
593
- },
594
- Flatten(path: "topCars.@") {
595
- Fetch(service: "reviews") {
596
- {
597
- ... on Car {
598
- __typename
599
- id
600
- price
601
- }
602
- } =>
603
- {
604
- ... on Car {
605
- retailPrice
606
- }
607
- }
608
- },
609
- },
610
- },
611
- }
612
- `);
613
- });
614
- });
615
-
616
- describe(`when the parent selection set is empty`, () => {
617
- it(`should add key fields to the parent selection set and use a dependent fetch`, () => {
618
- const operationString = `#graphql
619
- query {
620
- topReviews {
621
- author {
622
- name {
623
- first
624
- }
625
- }
626
- }
627
- }
628
- `;
629
-
630
- const queryPlan = buildPlan(operationString);
631
-
632
- expect(queryPlan).toMatchInlineSnapshot(`
633
- QueryPlan {
634
- Sequence {
635
- Fetch(service: "reviews") {
636
- {
637
- topReviews {
638
- author {
639
- __typename
640
- id
641
- }
642
- }
643
- }
644
- },
645
- Flatten(path: "topReviews.@.author") {
646
- Fetch(service: "accounts") {
647
- {
648
- ... on User {
649
- __typename
650
- id
651
- }
652
- } =>
653
- {
654
- ... on User {
655
- name {
656
- first
657
- }
658
- }
659
- }
660
- },
661
- },
662
- },
663
- }
664
- `);
665
- });
666
- });
667
- });
668
- describe(`when requesting a relationship field with extension subfields from a different service`, () => {
669
- it(`should first fetch the object using a key from the base service and then pass through the requirements`, () => {
670
- const operationString = `#graphql
671
- query {
672
- topReviews {
673
- author {
674
- birthDate
675
- }
676
- }
677
- }
678
- `;
679
-
680
- const queryPlan = buildPlan(operationString);
681
-
682
- expect(queryPlan).toMatchInlineSnapshot(`
683
- QueryPlan {
684
- Sequence {
685
- Fetch(service: "reviews") {
686
- {
687
- topReviews {
688
- author {
689
- __typename
690
- id
691
- }
692
- }
693
- }
694
- },
695
- Flatten(path: "topReviews.@.author") {
696
- Fetch(service: "accounts") {
697
- {
698
- ... on User {
699
- __typename
700
- id
701
- }
702
- } =>
703
- {
704
- ... on User {
705
- birthDate
706
- }
707
- }
708
- },
709
- },
710
- },
711
- }
712
- `);
713
- });
714
- });
715
-
716
- describe(`for abstract types`, () => {
717
- // GraphQLError: Cannot query field "isbn" on type "Book"
718
- // Probably an issue with extending / interfaces in composition. None of the fields from the base Book type
719
- // are showing up in the resulting schema.
720
- it(`should add __typename when fetching objects of an interface type from a service`, () => {
721
- const operationString = `#graphql
722
- query {
723
- topProducts {
724
- price
725
- }
726
- }
727
- `;
728
-
729
- const queryPlan = buildPlan(operationString);
730
-
731
- expect(queryPlan).toMatchInlineSnapshot(`
732
- QueryPlan {
733
- Fetch(service: "product") {
734
- {
735
- topProducts {
736
- __typename
737
- price
738
- }
739
- }
740
- },
741
- }
742
- `);
743
- });
744
-
745
- it(`should not get confused by a fragment spread multiple times`, () => {
746
- const operationString = `#graphql
747
- fragment Price on Product {
748
- price
749
- }
750
-
751
- query {
752
- topProducts {
753
- __typename
754
- ... on Book {
755
- ...Price
756
- }
757
- ... on Furniture {
758
- ...Price
759
- }
760
- }
761
- }
762
- `;
763
-
764
- const queryPlan = buildPlan(operationString);
765
-
766
- expect(queryPlan).toMatchInlineSnapshot(`
767
- QueryPlan {
768
- Fetch(service: "product") {
769
- {
770
- topProducts {
771
- __typename
772
- ... on Book {
773
- ...Price
774
- }
775
- ... on Furniture {
776
- ...Price
777
- }
778
- }
779
- }
780
-
781
- fragment Price on Product {
782
- price
783
- }
784
- },
785
- }
786
- `);
787
- });
788
-
789
- it(`should not get confused by an inline fragment multiple times`, () => {
790
- const operationString = `#graphql
791
- query {
792
- topProducts {
793
- __typename
794
- ... on Book {
795
- ...on Product {
796
- price
797
- }
798
- }
799
- ... on Furniture {
800
- ... on Product {
801
- price
802
- }
803
- }
804
- }
805
- }
806
- `;
807
-
808
- const queryPlan = buildPlan(operationString);
809
-
810
- expect(queryPlan).toMatchInlineSnapshot(`
811
- QueryPlan {
812
- Fetch(service: "product") {
813
- {
814
- topProducts {
815
- __typename
816
- ... on Book {
817
- price
818
- }
819
- ... on Furniture {
820
- price
821
- }
822
- }
823
- }
824
- },
825
- }
826
- `);
827
- });
828
-
829
- it(`eliminate unecessary type conditions`, () => {
830
- const operationString = `#graphql
831
- query {
832
- body {
833
- ... on Image {
834
- ... on NamedObject {
835
- name
836
- }
837
- }
838
- }
839
- }
840
- `;
841
-
842
- const queryPlan = buildPlan(operationString);
843
-
844
- expect(queryPlan).toMatchInlineSnapshot(`
845
- QueryPlan {
846
- Fetch(service: "documents") {
847
- {
848
- body {
849
- __typename
850
- ... on Image {
851
- name
852
- }
853
- }
854
- }
855
- },
856
- }
857
- `);
858
- });
859
-
860
- it(`should preserve directives on inline fragments even if the fragment is otherwise useless`, () => {
861
- const operationString = `#graphql
862
- query myQuery($b: Boolean!) {
863
- body {
864
- ... on Image {
865
- ... on NamedObject @include(if: $b) {
866
- name
867
- }
868
- }
869
- }
870
- }
871
- `;
872
-
873
- const queryPlan = buildPlan(operationString);
874
-
875
- expect(queryPlan).toMatchInlineSnapshot(`
876
- QueryPlan {
877
- Fetch(service: "documents") {
878
- {
879
- body {
880
- __typename
881
- ... on Image {
882
- ... on NamedObject @include(if: $b) {
883
- __typename
884
- name
885
- }
886
- }
887
- }
888
- }
889
- },
890
- }
891
- `);
892
- });
893
- });
894
-
895
- // GraphQLError: Cannot query field "isbn" on type "Book"
896
- // Probably an issue with extending / interfaces in composition. None of the fields from the base Book type
897
- // are showing up in the resulting schema.
898
- it(`should break up when traversing an extension field on an interface type from a service`, () => {
899
- const operationString = `#graphql
900
- query {
901
- topProducts {
902
- price
903
- reviews {
904
- body
905
- }
906
- }
907
- }
908
- `;
909
-
910
- const queryPlan = buildPlan(operationString);
911
-
912
- expect(queryPlan).toMatchInlineSnapshot(`
913
- QueryPlan {
914
- Sequence {
915
- Fetch(service: "product") {
916
- {
917
- topProducts {
918
- __typename
919
- price
920
- ... on Book {
921
- __typename
922
- isbn
923
- }
924
- ... on Furniture {
925
- __typename
926
- upc
927
- }
928
- }
929
- }
930
- },
931
- Flatten(path: "topProducts.@") {
932
- Fetch(service: "reviews") {
933
- {
934
- ... on Book {
935
- __typename
936
- isbn
937
- }
938
- ... on Furniture {
939
- __typename
940
- upc
941
- }
942
- } =>
943
- {
944
- ... on Book {
945
- reviews {
946
- body
947
- }
948
- }
949
- ... on Furniture {
950
- reviews {
951
- body
952
- }
953
- }
954
- }
955
- },
956
- },
957
- },
958
- }
959
- `);
960
- });
961
-
962
- it(`interface fragments should expand into possible types only`, () => {
963
- const operationString = `#graphql
964
- query {
965
- books {
966
- ... on Product {
967
- name
968
- ... on Furniture {
969
- upc
970
- }
971
- }
972
- }
973
- }
974
- `;
975
-
976
- const queryPlan = buildPlan(operationString);
977
-
978
- expect(queryPlan).toMatchInlineSnapshot(`
979
- QueryPlan {
980
- Sequence {
981
- Fetch(service: "books") {
982
- {
983
- books {
984
- __typename
985
- isbn
986
- title
987
- year
988
- }
989
- }
990
- },
991
- Flatten(path: "books.@") {
992
- Fetch(service: "product") {
993
- {
994
- ... on Book {
995
- __typename
996
- isbn
997
- title
998
- year
999
- }
1000
- } =>
1001
- {
1002
- ... on Book {
1003
- name
1004
- }
1005
- }
1006
- },
1007
- },
1008
- },
1009
- }
1010
- `);
1011
- });
1012
-
1013
- it(`interface inside interface should not type explode if possible`, () => {
1014
- const operationString = `#graphql
1015
- query {
1016
- product(upc: "") {
1017
- details {
1018
- country
1019
- }
1020
- }
1021
- }
1022
- `;
1023
-
1024
- const queryPlan = buildPlan(operationString);
1025
-
1026
- expect(queryPlan).toMatchInlineSnapshot(`
1027
- QueryPlan {
1028
- Fetch(service: "product") {
1029
- {
1030
- product(upc: "") {
1031
- __typename
1032
- details {
1033
- __typename
1034
- country
1035
- }
1036
- }
1037
- }
1038
- },
1039
- }
1040
- `);
1041
- });
1042
-
1043
- it(`should properly expand nested unions with inline fragments`, () => {
1044
- const operationString = `#graphql
1045
- query {
1046
- body {
1047
- ... on Image {
1048
- ... on Body {
1049
- ... on Image {
1050
- attributes {
1051
- url
1052
- }
1053
- }
1054
- ... on Text {
1055
- attributes {
1056
- bold
1057
- text
1058
- }
1059
- }
1060
- }
1061
- }
1062
- ... on Text {
1063
- attributes {
1064
- bold
1065
- }
1066
- }
1067
- }
1068
- }
1069
- `;
1070
-
1071
- const queryPlan = buildPlan(operationString);
1072
-
1073
- expect(queryPlan).toMatchInlineSnapshot(`
1074
- QueryPlan {
1075
- Fetch(service: "documents") {
1076
- {
1077
- body {
1078
- __typename
1079
- ... on Image {
1080
- attributes {
1081
- url
1082
- }
1083
- }
1084
- ... on Text {
1085
- attributes {
1086
- bold
1087
- }
1088
- }
1089
- }
1090
- }
1091
- },
1092
- }
1093
- `);
1094
- });
1095
-
1096
- describe('deduplicates fields / selections regardless of adjacency and type condition nesting', () => {
1097
- it('for inline fragments', () => {
1098
- const operationString = `#graphql
1099
- query {
1100
- body {
1101
- ... on Body {
1102
- ... on Text {
1103
- attributes {
1104
- bold
1105
- text
1106
- }
1107
- }
1108
- }
1109
- ... on Text {
1110
- attributes {
1111
- bold
1112
- text
1113
- }
1114
- }
1115
- }
1116
- }
1117
- `;
1118
-
1119
- const queryPlan = buildPlan(operationString);
1120
-
1121
- expect(queryPlan).toMatchInlineSnapshot(`
1122
- QueryPlan {
1123
- Fetch(service: "documents") {
1124
- {
1125
- body {
1126
- __typename
1127
- ... on Text {
1128
- attributes {
1129
- bold
1130
- text
1131
- }
1132
- }
1133
- }
1134
- }
1135
- },
1136
- }
1137
- `);
1138
- });
1139
-
1140
- it('for named fragment spreads', () => {
1141
- const operationString = `#graphql
1142
- fragment TextFragment on Text {
1143
- attributes {
1144
- bold
1145
- text
1146
- }
1147
- }
1148
-
1149
- query {
1150
- body {
1151
- ... on Body {
1152
- ...TextFragment
1153
- }
1154
- ...TextFragment
1155
- }
1156
- }
1157
- `;
1158
-
1159
- const queryPlan = buildPlan(operationString);
1160
-
1161
- expect(queryPlan).toMatchInlineSnapshot(`
1162
- QueryPlan {
1163
- Fetch(service: "documents") {
1164
- {
1165
- body {
1166
- __typename
1167
- ... on Text {
1168
- attributes {
1169
- bold
1170
- text
1171
- }
1172
- }
1173
- }
1174
- }
1175
- },
1176
- }
1177
- `);
1178
- });
1179
- });
1180
-
1181
- describe('overridden fields and type', () => {
1182
- it(`query plan of overridden field`, () => {
1183
- const operationString = `#graphql
1184
- query {
1185
- library (id: "3") {
1186
- name
1187
- description
1188
- }
1189
- }
1190
- `;
1191
-
1192
- const queryPlan = buildPlan(operationString);
1193
- expect(queryPlan).toMatchInlineSnapshot(`
1194
- QueryPlan {
1195
- Sequence {
1196
- Fetch(service: "books") {
1197
- {
1198
- library(id: 3) {
1199
- __typename
1200
- id
1201
- name
1202
- }
1203
- }
1204
- },
1205
- Flatten(path: "library") {
1206
- Fetch(service: "accounts") {
1207
- {
1208
- ... on Library {
1209
- __typename
1210
- id
1211
- }
1212
- } =>
1213
- {
1214
- ... on Library {
1215
- description
1216
- }
1217
- }
1218
- },
1219
- },
1220
- },
1221
- }
1222
- `);
1223
- });
1224
- });
1225
- });