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 21, 2023
1 parent 0b7590f commit 130f79c
Showing 1 changed file with 167 additions and 8 deletions.
175 changes: 167 additions & 8 deletions src/execution/__tests__/defer-test.ts
Expand Up @@ -154,6 +154,61 @@ 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;
},
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 @@ -167,7 +222,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 @@ -192,6 +248,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 @@ -485,7 +546,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 @@ -516,6 +578,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 @@ -533,7 +600,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 @@ -564,6 +632,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 that return promises', async () => {
Expand Down Expand Up @@ -634,7 +707,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 @@ -666,6 +740,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 @@ -681,7 +760,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 @@ -716,6 +796,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 @@ -854,9 +939,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 @@ -893,6 +977,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 130f79c

Please sign in to comment.