@@ -156,6 +156,65 @@ async function complete(document: DocumentNode, rootValue: unknown = { hero }) {
156
156
return result ;
157
157
}
158
158
159
+ function getCountingHero ( ) {
160
+ let stopped = false ;
161
+ let count = 0 ;
162
+ const counts = new Map < string , number > ( ) ;
163
+ function increment ( ) {
164
+ if ( stopped ) {
165
+ return ;
166
+ }
167
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
168
+ Promise . resolve ( ) . then ( ( ) => {
169
+ count ++ ;
170
+ increment ( ) ;
171
+ } ) ;
172
+ }
173
+ increment ( ) ;
174
+ const countingHero = {
175
+ stop : ( ) => {
176
+ stopped = true ;
177
+ } ,
178
+ counts,
179
+ hero : ( ) => {
180
+ counts . set ( 'hero' , count ) ;
181
+ return {
182
+ id : ( ) => {
183
+ counts . set ( 'id' , count ) ;
184
+ return hero . id ;
185
+ } ,
186
+ name : ( ) => {
187
+ counts . set ( 'name' , count ) ;
188
+ return hero . name ;
189
+ } ,
190
+ lastName : ( ) => {
191
+ counts . set ( 'lastName' , count ) ;
192
+ return hero . lastName ;
193
+ } ,
194
+ nestedObject : ( ) => {
195
+ counts . set ( 'nestedObject' , count ) ;
196
+ return {
197
+ deeperObject : ( ) => {
198
+ counts . set ( 'deeperObject' , count ) ;
199
+ return {
200
+ foo : ( ) => {
201
+ counts . set ( 'foo' , count ) ;
202
+ return 'foo' ;
203
+ } ,
204
+ bar : ( ) => {
205
+ counts . set ( 'bar' , count ) ;
206
+ return 'bar' ;
207
+ } ,
208
+ } ;
209
+ } ,
210
+ } ;
211
+ } ,
212
+ } ;
213
+ } ,
214
+ } ;
215
+ return countingHero ;
216
+ }
217
+
159
218
describe ( 'Execute: defer directive' , ( ) => {
160
219
it ( 'Can defer fragments containing scalar types' , async ( ) => {
161
220
const document = parse ( `
@@ -169,7 +228,8 @@ describe('Execute: defer directive', () => {
169
228
name
170
229
}
171
230
` ) ;
172
- const result = await complete ( document ) ;
231
+ const countingHero = getCountingHero ( ) ;
232
+ const result = await complete ( document , { hero : countingHero . hero } ) ;
173
233
174
234
expectJSON ( result ) . toDeepEqual ( [
175
235
{
@@ -194,6 +254,11 @@ describe('Execute: defer directive', () => {
194
254
hasNext : false ,
195
255
} ,
196
256
] ) ;
257
+
258
+ countingHero . stop ( ) ;
259
+ expect ( countingHero . counts . get ( 'hero' ) ) . to . equal ( 0 ) ;
260
+ expect ( countingHero . counts . get ( 'id' ) ) . to . equal ( 0 ) ;
261
+ expect ( countingHero . counts . get ( 'name' ) ) . to . equal ( 1 ) ;
197
262
} ) ;
198
263
it ( 'Can disable defer using if argument' , async ( ) => {
199
264
const document = parse ( `
@@ -487,7 +552,8 @@ describe('Execute: defer directive', () => {
487
552
}
488
553
}
489
554
` ) ;
490
- const result = await complete ( document ) ;
555
+ const countingHero = getCountingHero ( ) ;
556
+ const result = await complete ( document , { hero : countingHero . hero } ) ;
491
557
expectJSON ( result ) . toDeepEqual ( [
492
558
{
493
559
data : {
@@ -518,6 +584,11 @@ describe('Execute: defer directive', () => {
518
584
hasNext : false ,
519
585
} ,
520
586
] ) ;
587
+
588
+ countingHero . stop ( ) ;
589
+ expect ( countingHero . counts . get ( 'hero' ) ) . to . equal ( 0 ) ;
590
+ expect ( countingHero . counts . get ( 'id' ) ) . to . equal ( 1 ) ;
591
+ expect ( countingHero . counts . get ( 'name' ) ) . to . equal ( 1 ) ;
521
592
} ) ;
522
593
523
594
it ( 'Separately emits defer fragments with different labels with varying subfields' , async ( ) => {
@@ -535,7 +606,8 @@ describe('Execute: defer directive', () => {
535
606
}
536
607
}
537
608
` ) ;
538
- const result = await complete ( document ) ;
609
+ const countingHero = getCountingHero ( ) ;
610
+ const result = await complete ( document , { hero : countingHero . hero } ) ;
539
611
expectJSON ( result ) . toDeepEqual ( [
540
612
{
541
613
data : { } ,
@@ -566,6 +638,11 @@ describe('Execute: defer directive', () => {
566
638
hasNext : false ,
567
639
} ,
568
640
] ) ;
641
+
642
+ countingHero . stop ( ) ;
643
+ expect ( countingHero . counts . get ( 'hero' ) ) . to . equal ( 1 ) ;
644
+ expect ( countingHero . counts . get ( 'id' ) ) . to . equal ( 1 ) ;
645
+ expect ( countingHero . counts . get ( 'name' ) ) . to . equal ( 1 ) ;
569
646
} ) ;
570
647
571
648
it ( 'Separately emits defer fragments with different labels with varying subfields with superimposed masked defer' , async ( ) => {
@@ -587,7 +664,8 @@ describe('Execute: defer directive', () => {
587
664
}
588
665
}
589
666
` ) ;
590
- const result = await complete ( document ) ;
667
+ const countingHero = getCountingHero ( ) ;
668
+ const result = await complete ( document , { hero : countingHero . hero } ) ;
591
669
expectJSON ( result ) . toDeepEqual ( [
592
670
{
593
671
data : { } ,
@@ -618,6 +696,12 @@ describe('Execute: defer directive', () => {
618
696
hasNext : false ,
619
697
} ,
620
698
] ) ;
699
+
700
+ countingHero . stop ( ) ;
701
+ expect ( countingHero . counts . get ( 'hero' ) ) . to . equal ( 1 ) ;
702
+ expect ( countingHero . counts . get ( 'id' ) ) . to . equal ( 1 ) ;
703
+ expect ( countingHero . counts . get ( 'name' ) ) . to . equal ( 1 ) ;
704
+ expect ( countingHero . counts . get ( 'lastName' ) ) . to . equal ( 1 ) ;
621
705
} ) ;
622
706
623
707
it ( 'Separately emits defer fragments with different labels with varying subfields that return promises' , async ( ) => {
@@ -688,7 +772,8 @@ describe('Execute: defer directive', () => {
688
772
}
689
773
}
690
774
` ) ;
691
- const result = await complete ( document ) ;
775
+ const countingHero = getCountingHero ( ) ;
776
+ const result = await complete ( document , { hero : countingHero . hero } ) ;
692
777
expectJSON ( result ) . toDeepEqual ( [
693
778
{
694
779
data : {
@@ -720,6 +805,11 @@ describe('Execute: defer directive', () => {
720
805
hasNext : false ,
721
806
} ,
722
807
] ) ;
808
+
809
+ countingHero . stop ( ) ;
810
+ expect ( countingHero . counts . get ( 'hero' ) ) . to . equal ( 0 ) ;
811
+ expect ( countingHero . counts . get ( 'id' ) ) . to . equal ( 1 ) ;
812
+ expect ( countingHero . counts . get ( 'name' ) ) . to . equal ( 1 ) ;
723
813
} ) ;
724
814
725
815
it ( 'Separately emits nested defer fragments with varying subfields of same priorities but different level of defers' , async ( ) => {
@@ -735,7 +825,8 @@ describe('Execute: defer directive', () => {
735
825
}
736
826
}
737
827
` ) ;
738
- const result = await complete ( document ) ;
828
+ const countingHero = getCountingHero ( ) ;
829
+ const result = await complete ( document , { hero : countingHero . hero } ) ;
739
830
expectJSON ( result ) . toDeepEqual ( [
740
831
{
741
832
data : { } ,
@@ -770,6 +861,11 @@ describe('Execute: defer directive', () => {
770
861
hasNext : false ,
771
862
} ,
772
863
] ) ;
864
+
865
+ countingHero . stop ( ) ;
866
+ expect ( countingHero . counts . get ( 'hero' ) ) . to . equal ( 1 ) ;
867
+ expect ( countingHero . counts . get ( 'name' ) ) . to . equal ( 1 ) ;
868
+ expect ( countingHero . counts . get ( 'id' ) ) . to . equal ( 2 ) ;
773
869
} ) ;
774
870
775
871
it ( 'Can deduplicate multiple defers on the same object' , async ( ) => {
@@ -908,9 +1004,8 @@ describe('Execute: defer directive', () => {
908
1004
}
909
1005
}
910
1006
` ) ;
911
- const result = await complete ( document , {
912
- hero : { nestedObject : { deeperObject : { foo : 'foo' , bar : 'bar' } } } ,
913
- } ) ;
1007
+ const countingHero = getCountingHero ( ) ;
1008
+ const result = await complete ( document , { hero : countingHero . hero } ) ;
914
1009
expectJSON ( result ) . toDeepEqual ( [
915
1010
{
916
1011
data : {
@@ -947,6 +1042,81 @@ describe('Execute: defer directive', () => {
947
1042
hasNext : false ,
948
1043
} ,
949
1044
] ) ;
1045
+
1046
+ countingHero . stop ( ) ;
1047
+ expect ( countingHero . counts . get ( 'hero' ) ) . to . equal ( 0 ) ;
1048
+ expect ( countingHero . counts . get ( 'nestedObject' ) ) . to . equal ( 1 ) ;
1049
+ expect ( countingHero . counts . get ( 'deeperObject' ) ) . to . equal ( 1 ) ;
1050
+ expect ( countingHero . counts . get ( 'foo' ) ) . to . equal ( 1 ) ;
1051
+ expect ( countingHero . counts . get ( 'bar' ) ) . to . equal ( 2 ) ;
1052
+ } ) ;
1053
+
1054
+ it ( 'Deduplicates subfields present in a parent defer payload' , async ( ) => {
1055
+ const document = parse ( `
1056
+ query {
1057
+ hero {
1058
+ ... @defer {
1059
+ nestedObject {
1060
+ deeperObject {
1061
+ foo
1062
+ }
1063
+ ... @defer {
1064
+ deeperObject {
1065
+ foo
1066
+ bar
1067
+ }
1068
+ }
1069
+ }
1070
+ }
1071
+ }
1072
+ }
1073
+ ` ) ;
1074
+ const countingHero = getCountingHero ( ) ;
1075
+ const result = await complete ( document , { hero : countingHero . hero } ) ;
1076
+ expectJSON ( result ) . toDeepEqual ( [
1077
+ {
1078
+ data : {
1079
+ hero : { } ,
1080
+ } ,
1081
+ pending : [ { id : '0' , path : [ 'hero' ] } ] ,
1082
+ hasNext : true ,
1083
+ } ,
1084
+ {
1085
+ pending : [ { id : '1' , path : [ 'hero' , 'nestedObject' ] } ] ,
1086
+ incremental : [
1087
+ {
1088
+ data : {
1089
+ nestedObject : {
1090
+ deeperObject : { foo : 'foo' } ,
1091
+ } ,
1092
+ } ,
1093
+ id : '0' ,
1094
+ } ,
1095
+ ] ,
1096
+ completed : [ { id : '0' } ] ,
1097
+ hasNext : true ,
1098
+ } ,
1099
+ {
1100
+ incremental : [
1101
+ {
1102
+ data : {
1103
+ bar : 'bar' ,
1104
+ } ,
1105
+ id : '1' ,
1106
+ subPath : [ 'deeperObject' ] ,
1107
+ } ,
1108
+ ] ,
1109
+ completed : [ { id : '1' } ] ,
1110
+ hasNext : false ,
1111
+ } ,
1112
+ ] ) ;
1113
+
1114
+ countingHero . stop ( ) ;
1115
+ expect ( countingHero . counts . get ( 'hero' ) ) . to . equal ( 0 ) ;
1116
+ expect ( countingHero . counts . get ( 'nestedObject' ) ) . to . equal ( 1 ) ;
1117
+ expect ( countingHero . counts . get ( 'deeperObject' ) ) . to . equal ( 1 ) ;
1118
+ expect ( countingHero . counts . get ( 'foo' ) ) . to . equal ( 1 ) ;
1119
+ expect ( countingHero . counts . get ( 'bar' ) ) . to . equal ( 2 ) ;
950
1120
} ) ;
951
1121
952
1122
it ( 'Deduplicates fields with deferred fragments at multiple levels' , async ( ) => {
0 commit comments