Skip to content

Commit

Permalink
add checks for actual deferral
Browse files Browse the repository at this point in the history
  • Loading branch information
yaacovCR committed Nov 23, 2023
1 parent 1d038d6 commit c69d2cd
Showing 1 changed file with 179 additions and 9 deletions.
188 changes: 179 additions & 9 deletions src/execution/__tests__/defer-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,65 @@ async function complete(document: DocumentNode, rootValue: unknown = { hero }) {
return result;
}

function getCountingHero() {
let stopped = false;
let count = 0;
const counts = new Map<string, number>();
function increment() {
if (stopped) {
return;
}
// eslint-disable-next-line @typescript-eslint/no-floating-promises
Promise.resolve().then(() => {
count++;
increment();
});
}
increment();
const countingHero = {
stop: () => {
stopped = true;
},
counts,
hero: () => {
counts.set('hero', count);
return {
id: () => {
counts.set('id', count);
return hero.id;
},
name: () => {
counts.set('name', count);
return hero.name;
},
lastName: () => {
counts.set('lastName', count);
return hero.lastName;
},
nestedObject: () => {
counts.set('nestedObject', count);
return {
deeperObject: () => {
counts.set('deeperObject', count);
return {
foo: () => {
counts.set('foo', count);
return 'foo';
},
bar: () => {
counts.set('bar', count);
return 'bar';
},
};
},
};
},
};
},
};
return countingHero;
}

describe('Execute: defer directive', () => {
it('Can defer fragments containing scalar types', async () => {
const document = parse(`
Expand All @@ -169,7 +228,8 @@ describe('Execute: defer directive', () => {
name
}
`);
const result = await complete(document);
const countingHero = getCountingHero();
const result = await complete(document, { hero: countingHero.hero });

expectJSON(result).toDeepEqual([
{
Expand All @@ -194,6 +254,11 @@ describe('Execute: defer directive', () => {
hasNext: false,
},
]);

countingHero.stop();
expect(countingHero.counts.get('hero')).to.equal(0);
expect(countingHero.counts.get('id')).to.equal(0);
expect(countingHero.counts.get('name')).to.equal(1);
});
it('Can disable defer using if argument', async () => {
const document = parse(`
Expand Down Expand Up @@ -487,7 +552,8 @@ describe('Execute: defer directive', () => {
}
}
`);
const result = await complete(document);
const countingHero = getCountingHero();
const result = await complete(document, { hero: countingHero.hero });
expectJSON(result).toDeepEqual([
{
data: {
Expand Down Expand Up @@ -518,6 +584,11 @@ describe('Execute: defer directive', () => {
hasNext: false,
},
]);

countingHero.stop();
expect(countingHero.counts.get('hero')).to.equal(0);
expect(countingHero.counts.get('id')).to.equal(1);
expect(countingHero.counts.get('name')).to.equal(1);
});

it('Separately emits defer fragments with different labels with varying subfields', async () => {
Expand All @@ -535,7 +606,8 @@ describe('Execute: defer directive', () => {
}
}
`);
const result = await complete(document);
const countingHero = getCountingHero();
const result = await complete(document, { hero: countingHero.hero });
expectJSON(result).toDeepEqual([
{
data: {},
Expand Down Expand Up @@ -566,6 +638,11 @@ describe('Execute: defer directive', () => {
hasNext: false,
},
]);

countingHero.stop();
expect(countingHero.counts.get('hero')).to.equal(1);
expect(countingHero.counts.get('id')).to.equal(1);
expect(countingHero.counts.get('name')).to.equal(1);
});

it('Separately emits defer fragments with different labels with varying subfields with superimposed masked defer', async () => {
Expand All @@ -587,7 +664,8 @@ describe('Execute: defer directive', () => {
}
}
`);
const result = await complete(document);
const countingHero = getCountingHero();
const result = await complete(document, { hero: countingHero.hero });
expectJSON(result).toDeepEqual([
{
data: {},
Expand Down Expand Up @@ -618,6 +696,12 @@ describe('Execute: defer directive', () => {
hasNext: false,
},
]);

countingHero.stop();
expect(countingHero.counts.get('hero')).to.equal(1);
expect(countingHero.counts.get('id')).to.equal(1);
expect(countingHero.counts.get('name')).to.equal(1);
expect(countingHero.counts.get('lastName')).to.equal(1);
});

it('Separately emits defer fragments with different labels with varying subfields that return promises', async () => {
Expand Down Expand Up @@ -688,7 +772,8 @@ describe('Execute: defer directive', () => {
}
}
`);
const result = await complete(document);
const countingHero = getCountingHero();
const result = await complete(document, { hero: countingHero.hero });
expectJSON(result).toDeepEqual([
{
data: {
Expand Down Expand Up @@ -720,6 +805,11 @@ describe('Execute: defer directive', () => {
hasNext: false,
},
]);

countingHero.stop();
expect(countingHero.counts.get('hero')).to.equal(0);
expect(countingHero.counts.get('id')).to.equal(1);
expect(countingHero.counts.get('name')).to.equal(1);
});

it('Separately emits nested defer fragments with varying subfields of same priorities but different level of defers', async () => {
Expand All @@ -735,7 +825,8 @@ describe('Execute: defer directive', () => {
}
}
`);
const result = await complete(document);
const countingHero = getCountingHero();
const result = await complete(document, { hero: countingHero.hero });
expectJSON(result).toDeepEqual([
{
data: {},
Expand Down Expand Up @@ -770,6 +861,11 @@ describe('Execute: defer directive', () => {
hasNext: false,
},
]);

countingHero.stop();
expect(countingHero.counts.get('hero')).to.equal(1);
expect(countingHero.counts.get('name')).to.equal(1);
expect(countingHero.counts.get('id')).to.equal(2);
});

it('Can deduplicate multiple defers on the same object', async () => {
Expand Down Expand Up @@ -908,9 +1004,8 @@ describe('Execute: defer directive', () => {
}
}
`);
const result = await complete(document, {
hero: { nestedObject: { deeperObject: { foo: 'foo', bar: 'bar' } } },
});
const countingHero = getCountingHero();
const result = await complete(document, { hero: countingHero.hero });
expectJSON(result).toDeepEqual([
{
data: {
Expand Down Expand Up @@ -947,6 +1042,81 @@ describe('Execute: defer directive', () => {
hasNext: false,
},
]);

countingHero.stop();
expect(countingHero.counts.get('hero')).to.equal(0);
expect(countingHero.counts.get('nestedObject')).to.equal(1);
expect(countingHero.counts.get('deeperObject')).to.equal(1);
expect(countingHero.counts.get('foo')).to.equal(1);
expect(countingHero.counts.get('bar')).to.equal(2);
});

it('Deduplicates subfields present in a parent defer payload', async () => {
const document = parse(`
query {
hero {
... @defer {
nestedObject {
deeperObject {
foo
}
... @defer {
deeperObject {
foo
bar
}
}
}
}
}
}
`);
const countingHero = getCountingHero();
const result = await complete(document, { hero: countingHero.hero });
expectJSON(result).toDeepEqual([
{
data: {
hero: {},
},
pending: [{ id: '0', path: ['hero'] }],
hasNext: true,
},
{
pending: [{ id: '1', path: ['hero', 'nestedObject'] }],
incremental: [
{
data: {
nestedObject: {
deeperObject: { foo: 'foo' },
},
},
id: '0',
},
],
completed: [{ id: '0' }],
hasNext: true,
},
{
incremental: [
{
data: {
bar: 'bar',
},
id: '1',
subPath: ['deeperObject'],
},
],
completed: [{ id: '1' }],
hasNext: false,
},
]);

countingHero.stop();
expect(countingHero.counts.get('hero')).to.equal(0);
expect(countingHero.counts.get('nestedObject')).to.equal(1);
expect(countingHero.counts.get('deeperObject')).to.equal(1);
expect(countingHero.counts.get('foo')).to.equal(1);
expect(countingHero.counts.get('bar')).to.equal(2);
});

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

0 comments on commit c69d2cd

Please sign in to comment.