@@ -154,6 +154,61 @@ async function complete(document: DocumentNode, rootValue: unknown = { hero }) {
154
154
return result ;
155
155
}
156
156
157
+ function getCountingHero ( ) {
158
+ let stopped = false ;
159
+ let count = 0 ;
160
+ const counts = new Map < string , number > ( ) ;
161
+ function increment ( ) {
162
+ if ( stopped ) {
163
+ return ;
164
+ }
165
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
166
+ Promise . resolve ( ) . then ( ( ) => {
167
+ count ++ ;
168
+ increment ( ) ;
169
+ } ) ;
170
+ }
171
+ increment ( ) ;
172
+ const countingHero = {
173
+ stop : ( ) => {
174
+ stopped = true ;
175
+ } ,
176
+ counts,
177
+ hero : ( ) => {
178
+ counts . set ( 'hero' , count ) ;
179
+ return {
180
+ id : ( ) => {
181
+ counts . set ( 'id' , count ) ;
182
+ return hero . id ;
183
+ } ,
184
+ name : ( ) => {
185
+ counts . set ( 'name' , count ) ;
186
+ return hero . name ;
187
+ } ,
188
+ nestedObject : ( ) => {
189
+ counts . set ( 'nestedObject' , count ) ;
190
+ return {
191
+ deeperObject : ( ) => {
192
+ counts . set ( 'deeperObject' , count ) ;
193
+ return {
194
+ foo : ( ) => {
195
+ counts . set ( 'foo' , count ) ;
196
+ return 'foo' ;
197
+ } ,
198
+ bar : ( ) => {
199
+ counts . set ( 'bar' , count ) ;
200
+ return 'bar' ;
201
+ } ,
202
+ } ;
203
+ } ,
204
+ } ;
205
+ } ,
206
+ } ;
207
+ } ,
208
+ } ;
209
+ return countingHero ;
210
+ }
211
+
157
212
describe ( 'Execute: defer directive' , ( ) => {
158
213
it ( 'Can defer fragments containing scalar types' , async ( ) => {
159
214
const document = parse ( `
@@ -167,7 +222,8 @@ describe('Execute: defer directive', () => {
167
222
name
168
223
}
169
224
` ) ;
170
- const result = await complete ( document ) ;
225
+ const countingHero = getCountingHero ( ) ;
226
+ const result = await complete ( document , { hero : countingHero . hero } ) ;
171
227
172
228
expectJSON ( result ) . toDeepEqual ( [
173
229
{
@@ -192,6 +248,11 @@ describe('Execute: defer directive', () => {
192
248
hasNext : false ,
193
249
} ,
194
250
] ) ;
251
+
252
+ countingHero . stop ( ) ;
253
+ expect ( countingHero . counts . get ( 'hero' ) ) . to . equal ( 0 ) ;
254
+ expect ( countingHero . counts . get ( 'id' ) ) . to . equal ( 0 ) ;
255
+ expect ( countingHero . counts . get ( 'name' ) ) . to . equal ( 1 ) ;
195
256
} ) ;
196
257
it ( 'Can disable defer using if argument' , async ( ) => {
197
258
const document = parse ( `
@@ -485,7 +546,8 @@ describe('Execute: defer directive', () => {
485
546
}
486
547
}
487
548
` ) ;
488
- const result = await complete ( document ) ;
549
+ const countingHero = getCountingHero ( ) ;
550
+ const result = await complete ( document , { hero : countingHero . hero } ) ;
489
551
expectJSON ( result ) . toDeepEqual ( [
490
552
{
491
553
data : {
@@ -516,6 +578,11 @@ describe('Execute: defer directive', () => {
516
578
hasNext : false ,
517
579
} ,
518
580
] ) ;
581
+
582
+ countingHero . stop ( ) ;
583
+ expect ( countingHero . counts . get ( 'hero' ) ) . to . equal ( 0 ) ;
584
+ expect ( countingHero . counts . get ( 'id' ) ) . to . equal ( 1 ) ;
585
+ expect ( countingHero . counts . get ( 'name' ) ) . to . equal ( 1 ) ;
519
586
} ) ;
520
587
521
588
it ( 'Separately emits defer fragments with different labels with varying subfields' , async ( ) => {
@@ -533,7 +600,8 @@ describe('Execute: defer directive', () => {
533
600
}
534
601
}
535
602
` ) ;
536
- const result = await complete ( document ) ;
603
+ const countingHero = getCountingHero ( ) ;
604
+ const result = await complete ( document , { hero : countingHero . hero } ) ;
537
605
expectJSON ( result ) . toDeepEqual ( [
538
606
{
539
607
data : { } ,
@@ -564,6 +632,11 @@ describe('Execute: defer directive', () => {
564
632
hasNext : false ,
565
633
} ,
566
634
] ) ;
635
+
636
+ countingHero . stop ( ) ;
637
+ expect ( countingHero . counts . get ( 'hero' ) ) . to . equal ( 1 ) ;
638
+ expect ( countingHero . counts . get ( 'id' ) ) . to . equal ( 1 ) ;
639
+ expect ( countingHero . counts . get ( 'name' ) ) . to . equal ( 1 ) ;
567
640
} ) ;
568
641
569
642
it ( 'Separately emits defer fragments with different labels with varying subfields that return promises' , async ( ) => {
@@ -634,7 +707,8 @@ describe('Execute: defer directive', () => {
634
707
}
635
708
}
636
709
` ) ;
637
- const result = await complete ( document ) ;
710
+ const countingHero = getCountingHero ( ) ;
711
+ const result = await complete ( document , { hero : countingHero . hero } ) ;
638
712
expectJSON ( result ) . toDeepEqual ( [
639
713
{
640
714
data : {
@@ -666,6 +740,11 @@ describe('Execute: defer directive', () => {
666
740
hasNext : false ,
667
741
} ,
668
742
] ) ;
743
+
744
+ countingHero . stop ( ) ;
745
+ expect ( countingHero . counts . get ( 'hero' ) ) . to . equal ( 0 ) ;
746
+ expect ( countingHero . counts . get ( 'id' ) ) . to . equal ( 1 ) ;
747
+ expect ( countingHero . counts . get ( 'name' ) ) . to . equal ( 1 ) ;
669
748
} ) ;
670
749
671
750
it ( 'Separately emits nested defer fragments with varying subfields of same priorities but different level of defers' , async ( ) => {
@@ -681,7 +760,8 @@ describe('Execute: defer directive', () => {
681
760
}
682
761
}
683
762
` ) ;
684
- const result = await complete ( document ) ;
763
+ const countingHero = getCountingHero ( ) ;
764
+ const result = await complete ( document , { hero : countingHero . hero } ) ;
685
765
expectJSON ( result ) . toDeepEqual ( [
686
766
{
687
767
data : { } ,
@@ -716,6 +796,11 @@ describe('Execute: defer directive', () => {
716
796
hasNext : false ,
717
797
} ,
718
798
] ) ;
799
+
800
+ countingHero . stop ( ) ;
801
+ expect ( countingHero . counts . get ( 'hero' ) ) . to . equal ( 1 ) ;
802
+ expect ( countingHero . counts . get ( 'name' ) ) . to . equal ( 1 ) ;
803
+ expect ( countingHero . counts . get ( 'id' ) ) . to . equal ( 2 ) ;
719
804
} ) ;
720
805
721
806
it ( 'Can deduplicate multiple defers on the same object' , async ( ) => {
@@ -854,9 +939,8 @@ describe('Execute: defer directive', () => {
854
939
}
855
940
}
856
941
` ) ;
857
- const result = await complete ( document , {
858
- hero : { nestedObject : { deeperObject : { foo : 'foo' , bar : 'bar' } } } ,
859
- } ) ;
942
+ const countingHero = getCountingHero ( ) ;
943
+ const result = await complete ( document , { hero : countingHero . hero } ) ;
860
944
expectJSON ( result ) . toDeepEqual ( [
861
945
{
862
946
data : {
@@ -893,6 +977,81 @@ describe('Execute: defer directive', () => {
893
977
hasNext : false ,
894
978
} ,
895
979
] ) ;
980
+
981
+ countingHero . stop ( ) ;
982
+ expect ( countingHero . counts . get ( 'hero' ) ) . to . equal ( 0 ) ;
983
+ expect ( countingHero . counts . get ( 'nestedObject' ) ) . to . equal ( 1 ) ;
984
+ expect ( countingHero . counts . get ( 'deeperObject' ) ) . to . equal ( 1 ) ;
985
+ expect ( countingHero . counts . get ( 'foo' ) ) . to . equal ( 1 ) ;
986
+ expect ( countingHero . counts . get ( 'bar' ) ) . to . equal ( 2 ) ;
987
+ } ) ;
988
+
989
+ it ( 'Deduplicates subfields present in a parent defer payload' , async ( ) => {
990
+ const document = parse ( `
991
+ query {
992
+ hero {
993
+ ... @defer {
994
+ nestedObject {
995
+ deeperObject {
996
+ foo
997
+ }
998
+ ... @defer {
999
+ deeperObject {
1000
+ foo
1001
+ bar
1002
+ }
1003
+ }
1004
+ }
1005
+ }
1006
+ }
1007
+ }
1008
+ ` ) ;
1009
+ const countingHero = getCountingHero ( ) ;
1010
+ const result = await complete ( document , { hero : countingHero . hero } ) ;
1011
+ expectJSON ( result ) . toDeepEqual ( [
1012
+ {
1013
+ data : {
1014
+ hero : { } ,
1015
+ } ,
1016
+ pending : [ { id : '0' , path : [ 'hero' ] } ] ,
1017
+ hasNext : true ,
1018
+ } ,
1019
+ {
1020
+ pending : [ { id : '1' , path : [ 'hero' , 'nestedObject' ] } ] ,
1021
+ incremental : [
1022
+ {
1023
+ data : {
1024
+ nestedObject : {
1025
+ deeperObject : { foo : 'foo' } ,
1026
+ } ,
1027
+ } ,
1028
+ id : '0' ,
1029
+ } ,
1030
+ ] ,
1031
+ completed : [ { id : '0' } ] ,
1032
+ hasNext : true ,
1033
+ } ,
1034
+ {
1035
+ incremental : [
1036
+ {
1037
+ data : {
1038
+ bar : 'bar' ,
1039
+ } ,
1040
+ id : '1' ,
1041
+ subPath : [ 'deeperObject' ] ,
1042
+ } ,
1043
+ ] ,
1044
+ completed : [ { id : '1' } ] ,
1045
+ hasNext : false ,
1046
+ } ,
1047
+ ] ) ;
1048
+
1049
+ countingHero . stop ( ) ;
1050
+ expect ( countingHero . counts . get ( 'hero' ) ) . to . equal ( 0 ) ;
1051
+ expect ( countingHero . counts . get ( 'nestedObject' ) ) . to . equal ( 1 ) ;
1052
+ expect ( countingHero . counts . get ( 'deeperObject' ) ) . to . equal ( 1 ) ;
1053
+ expect ( countingHero . counts . get ( 'foo' ) ) . to . equal ( 1 ) ;
1054
+ expect ( countingHero . counts . get ( 'bar' ) ) . to . equal ( 2 ) ;
896
1055
} ) ;
897
1056
898
1057
it ( 'Deduplicates fields with deferred fragments at multiple levels' , async ( ) => {
0 commit comments