@@ -156,6 +156,65 @@ async function complete(document: DocumentNode, rootValue: unknown = { hero }) {
156156 return result ;
157157}
158158
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+
159218describe ( 'Execute: defer directive' , ( ) => {
160219 it ( 'Can defer fragments containing scalar types' , async ( ) => {
161220 const document = parse ( `
@@ -169,7 +228,8 @@ describe('Execute: defer directive', () => {
169228 name
170229 }
171230 ` ) ;
172- const result = await complete ( document ) ;
231+ const countingHero = getCountingHero ( ) ;
232+ const result = await complete ( document , { hero : countingHero . hero } ) ;
173233
174234 expectJSON ( result ) . toDeepEqual ( [
175235 {
@@ -194,6 +254,11 @@ describe('Execute: defer directive', () => {
194254 hasNext : false ,
195255 } ,
196256 ] ) ;
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 ) ;
197262 } ) ;
198263 it ( 'Can disable defer using if argument' , async ( ) => {
199264 const document = parse ( `
@@ -487,7 +552,8 @@ describe('Execute: defer directive', () => {
487552 }
488553 }
489554 ` ) ;
490- const result = await complete ( document ) ;
555+ const countingHero = getCountingHero ( ) ;
556+ const result = await complete ( document , { hero : countingHero . hero } ) ;
491557 expectJSON ( result ) . toDeepEqual ( [
492558 {
493559 data : {
@@ -518,6 +584,11 @@ describe('Execute: defer directive', () => {
518584 hasNext : false ,
519585 } ,
520586 ] ) ;
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 ) ;
521592 } ) ;
522593
523594 it ( 'Separately emits defer fragments with different labels with varying subfields' , async ( ) => {
@@ -535,7 +606,8 @@ describe('Execute: defer directive', () => {
535606 }
536607 }
537608 ` ) ;
538- const result = await complete ( document ) ;
609+ const countingHero = getCountingHero ( ) ;
610+ const result = await complete ( document , { hero : countingHero . hero } ) ;
539611 expectJSON ( result ) . toDeepEqual ( [
540612 {
541613 data : { } ,
@@ -566,6 +638,11 @@ describe('Execute: defer directive', () => {
566638 hasNext : false ,
567639 } ,
568640 ] ) ;
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 ) ;
569646 } ) ;
570647
571648 it ( 'Separately emits defer fragments with different labels with varying subfields with superimposed masked defer' , async ( ) => {
@@ -587,7 +664,8 @@ describe('Execute: defer directive', () => {
587664 }
588665 }
589666 ` ) ;
590- const result = await complete ( document ) ;
667+ const countingHero = getCountingHero ( ) ;
668+ const result = await complete ( document , { hero : countingHero . hero } ) ;
591669 expectJSON ( result ) . toDeepEqual ( [
592670 {
593671 data : { } ,
@@ -618,6 +696,12 @@ describe('Execute: defer directive', () => {
618696 hasNext : false ,
619697 } ,
620698 ] ) ;
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 ) ;
621705 } ) ;
622706
623707 it ( 'Separately emits defer fragments with different labels with varying subfields that return promises' , async ( ) => {
@@ -688,7 +772,8 @@ describe('Execute: defer directive', () => {
688772 }
689773 }
690774 ` ) ;
691- const result = await complete ( document ) ;
775+ const countingHero = getCountingHero ( ) ;
776+ const result = await complete ( document , { hero : countingHero . hero } ) ;
692777 expectJSON ( result ) . toDeepEqual ( [
693778 {
694779 data : {
@@ -720,6 +805,11 @@ describe('Execute: defer directive', () => {
720805 hasNext : false ,
721806 } ,
722807 ] ) ;
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 ) ;
723813 } ) ;
724814
725815 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', () => {
735825 }
736826 }
737827 ` ) ;
738- const result = await complete ( document ) ;
828+ const countingHero = getCountingHero ( ) ;
829+ const result = await complete ( document , { hero : countingHero . hero } ) ;
739830 expectJSON ( result ) . toDeepEqual ( [
740831 {
741832 data : { } ,
@@ -770,6 +861,11 @@ describe('Execute: defer directive', () => {
770861 hasNext : false ,
771862 } ,
772863 ] ) ;
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 ) ;
773869 } ) ;
774870
775871 it ( 'Can deduplicate multiple defers on the same object' , async ( ) => {
@@ -908,9 +1004,8 @@ describe('Execute: defer directive', () => {
9081004 }
9091005 }
9101006 ` ) ;
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 } ) ;
9141009 expectJSON ( result ) . toDeepEqual ( [
9151010 {
9161011 data : {
@@ -947,6 +1042,81 @@ describe('Execute: defer directive', () => {
9471042 hasNext : false ,
9481043 } ,
9491044 ] ) ;
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 ) ;
9501120 } ) ;
9511121
9521122 it ( 'Deduplicates fields with deferred fragments at multiple levels' , async ( ) => {
0 commit comments