Skip to content

Commit 130f79c

Browse files
committed
add checks for actual deferral
1 parent 0b7590f commit 130f79c

File tree

1 file changed

+167
-8
lines changed

1 file changed

+167
-8
lines changed

src/execution/__tests__/defer-test.ts

Lines changed: 167 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,61 @@ async function complete(document: DocumentNode, rootValue: unknown = { hero }) {
154154
return result;
155155
}
156156

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+
157212
describe('Execute: defer directive', () => {
158213
it('Can defer fragments containing scalar types', async () => {
159214
const document = parse(`
@@ -167,7 +222,8 @@ describe('Execute: defer directive', () => {
167222
name
168223
}
169224
`);
170-
const result = await complete(document);
225+
const countingHero = getCountingHero();
226+
const result = await complete(document, { hero: countingHero.hero });
171227

172228
expectJSON(result).toDeepEqual([
173229
{
@@ -192,6 +248,11 @@ describe('Execute: defer directive', () => {
192248
hasNext: false,
193249
},
194250
]);
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);
195256
});
196257
it('Can disable defer using if argument', async () => {
197258
const document = parse(`
@@ -485,7 +546,8 @@ describe('Execute: defer directive', () => {
485546
}
486547
}
487548
`);
488-
const result = await complete(document);
549+
const countingHero = getCountingHero();
550+
const result = await complete(document, { hero: countingHero.hero });
489551
expectJSON(result).toDeepEqual([
490552
{
491553
data: {
@@ -516,6 +578,11 @@ describe('Execute: defer directive', () => {
516578
hasNext: false,
517579
},
518580
]);
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);
519586
});
520587

521588
it('Separately emits defer fragments with different labels with varying subfields', async () => {
@@ -533,7 +600,8 @@ describe('Execute: defer directive', () => {
533600
}
534601
}
535602
`);
536-
const result = await complete(document);
603+
const countingHero = getCountingHero();
604+
const result = await complete(document, { hero: countingHero.hero });
537605
expectJSON(result).toDeepEqual([
538606
{
539607
data: {},
@@ -564,6 +632,11 @@ describe('Execute: defer directive', () => {
564632
hasNext: false,
565633
},
566634
]);
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);
567640
});
568641

569642
it('Separately emits defer fragments with different labels with varying subfields that return promises', async () => {
@@ -634,7 +707,8 @@ describe('Execute: defer directive', () => {
634707
}
635708
}
636709
`);
637-
const result = await complete(document);
710+
const countingHero = getCountingHero();
711+
const result = await complete(document, { hero: countingHero.hero });
638712
expectJSON(result).toDeepEqual([
639713
{
640714
data: {
@@ -666,6 +740,11 @@ describe('Execute: defer directive', () => {
666740
hasNext: false,
667741
},
668742
]);
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);
669748
});
670749

671750
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', () => {
681760
}
682761
}
683762
`);
684-
const result = await complete(document);
763+
const countingHero = getCountingHero();
764+
const result = await complete(document, { hero: countingHero.hero });
685765
expectJSON(result).toDeepEqual([
686766
{
687767
data: {},
@@ -716,6 +796,11 @@ describe('Execute: defer directive', () => {
716796
hasNext: false,
717797
},
718798
]);
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);
719804
});
720805

721806
it('Can deduplicate multiple defers on the same object', async () => {
@@ -854,9 +939,8 @@ describe('Execute: defer directive', () => {
854939
}
855940
}
856941
`);
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 });
860944
expectJSON(result).toDeepEqual([
861945
{
862946
data: {
@@ -893,6 +977,81 @@ describe('Execute: defer directive', () => {
893977
hasNext: false,
894978
},
895979
]);
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);
8961055
});
8971056

8981057
it('Deduplicates fields with deferred fragments at multiple levels', async () => {

0 commit comments

Comments
 (0)