Skip to content

Commit 4203dda

Browse files
committed
add checks for actual deferral
1 parent af18110 commit 4203dda

File tree

1 file changed

+179
-9
lines changed

1 file changed

+179
-9
lines changed

src/execution/__tests__/defer-test.ts

Lines changed: 179 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
159218
describe('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

Comments
 (0)