From 22d44ec5ece0e3bbb958320a0b698a7f99d7b366 Mon Sep 17 00:00:00 2001 From: Rob Richard Date: Wed, 12 Apr 2023 17:06:38 -0400 Subject: [PATCH] simplify schema in defer tests --- src/execution/__tests__/defer-test.ts | 160 +++++++++++++++----------- 1 file changed, 92 insertions(+), 68 deletions(-) diff --git a/src/execution/__tests__/defer-test.ts b/src/execution/__tests__/defer-test.ts index 5cad95bbc3..2840eda58f 100644 --- a/src/execution/__tests__/defer-test.ts +++ b/src/execution/__tests__/defer-test.ts @@ -26,10 +26,7 @@ const friendType = new GraphQLObjectType({ fields: { id: { type: GraphQLID }, name: { type: GraphQLString }, - promiseNonNullErrorField: { - type: new GraphQLNonNull(GraphQLString), - resolve: () => Promise.resolve(null), - }, + nonNullName: { type: new GraphQLNonNull(GraphQLString) }, }, name: 'Friend', }); @@ -40,52 +37,24 @@ const friends = [ { name: 'C-3PO', id: 4 }, ]; +const hero = { name: 'Luke', id: 1, friends }; + const heroType = new GraphQLObjectType({ fields: { id: { type: GraphQLID }, name: { type: GraphQLString }, - slowField: { - type: GraphQLString, - resolve: async () => { - await resolveOnNextTick(); - return 'slow'; - }, - }, - errorField: { - type: GraphQLString, - resolve: () => { - throw new Error('bad'); - }, - }, - nonNullErrorField: { - type: new GraphQLNonNull(GraphQLString), - resolve: () => null, - }, - promiseNonNullErrorField: { - type: new GraphQLNonNull(GraphQLString), - resolve: () => Promise.resolve(null), - }, + nonNullName: { type: new GraphQLNonNull(GraphQLString) }, friends: { type: new GraphQLList(friendType), - resolve: () => friends, - }, - asyncFriends: { - type: new GraphQLList(friendType), - async *resolve() { - yield await Promise.resolve(friends[0]); - }, }, }, name: 'Hero', }); -const hero = { name: 'Luke', id: 1 }; - const query = new GraphQLObjectType({ fields: { hero: { type: heroType, - resolve: () => hero, }, }, name: 'Query', @@ -93,11 +62,11 @@ const query = new GraphQLObjectType({ const schema = new GraphQLSchema({ query }); -async function complete(document: DocumentNode) { +async function complete(document: DocumentNode, rootValue: unknown = { hero }) { const result = await experimentalExecuteIncrementally({ schema, document, - rootValue: {}, + rootValue, }); if ('initialResult' in result) { @@ -244,11 +213,18 @@ describe('Execute: defer directive', () => { } fragment QueryFragment on Query { hero { - errorField + name } } `); - const result = await complete(document); + const result = await complete(document, { + hero: { + ...hero, + name: () => { + throw new Error('bad'); + }, + }, + }); expectJSON(result).toDeepEqual([ { @@ -260,14 +236,14 @@ describe('Execute: defer directive', () => { { data: { hero: { - errorField: null, + name: null, }, }, errors: [ { message: 'bad', locations: [{ line: 7, column: 11 }], - path: ['hero', 'errorField'], + path: ['hero', 'name'], }, ], path: [], @@ -440,10 +416,17 @@ describe('Execute: defer directive', () => { } } fragment NameFragment on Hero { - errorField + name } `); - const result = await complete(document); + const result = await complete(document, { + hero: { + ...hero, + name: () => { + throw new Error('bad'); + }, + }, + }); expectJSON(result).toDeepEqual([ { data: { hero: { id: '1' } }, @@ -452,13 +435,13 @@ describe('Execute: defer directive', () => { { incremental: [ { - data: { errorField: null }, + data: { name: null }, path: ['hero'], errors: [ { message: 'bad', locations: [{ line: 9, column: 9 }], - path: ['hero', 'errorField'], + path: ['hero', 'name'], }, ], }, @@ -476,10 +459,15 @@ describe('Execute: defer directive', () => { } } fragment NameFragment on Hero { - nonNullErrorField + nonNullName } `); - const result = await complete(document); + const result = await complete(document, { + hero: { + ...hero, + nonNullName: () => null, + }, + }); expectJSON(result).toDeepEqual([ { data: { hero: { id: '1' } }, @@ -493,9 +481,9 @@ describe('Execute: defer directive', () => { errors: [ { message: - 'Cannot return null for non-nullable field Hero.nonNullErrorField.', + 'Cannot return null for non-nullable field Hero.nonNullName.', locations: [{ line: 9, column: 9 }], - path: ['hero', 'nonNullErrorField'], + path: ['hero', 'nonNullName'], }, ], }, @@ -508,7 +496,7 @@ describe('Execute: defer directive', () => { const document = parse(` query HeroNameQuery { hero { - nonNullErrorField + nonNullName ...NameFragment @defer } } @@ -516,19 +504,24 @@ describe('Execute: defer directive', () => { id } `); - const result = await complete(document); + const result = await complete(document, { + hero: { + ...hero, + nonNullName: () => null, + }, + }); expectJSON(result).toDeepEqual({ errors: [ { message: - 'Cannot return null for non-nullable field Hero.nonNullErrorField.', + 'Cannot return null for non-nullable field Hero.nonNullName.', locations: [ { line: 4, column: 11, }, ], - path: ['hero', 'nonNullErrorField'], + path: ['hero', 'nonNullName'], }, ], data: { @@ -545,10 +538,15 @@ describe('Execute: defer directive', () => { } } fragment NameFragment on Hero { - promiseNonNullErrorField + nonNullName } `); - const result = await complete(document); + const result = await complete(document, { + hero: { + ...hero, + nonNullName: () => Promise.resolve(null), + }, + }); expectJSON(result).toDeepEqual([ { data: { hero: { id: '1' } }, @@ -562,9 +560,9 @@ describe('Execute: defer directive', () => { errors: [ { message: - 'Cannot return null for non-nullable field Hero.promiseNonNullErrorField.', + 'Cannot return null for non-nullable field Hero.nonNullName.', locations: [{ line: 9, column: 9 }], - path: ['hero', 'promiseNonNullErrorField'], + path: ['hero', 'nonNullName'], }, ], }, @@ -582,7 +580,7 @@ describe('Execute: defer directive', () => { } } fragment NameFragment on Hero { - slowField + name friends { ...NestedFragment @defer } @@ -591,7 +589,15 @@ describe('Execute: defer directive', () => { name } `); - const result = await complete(document); + const result = await complete(document, { + hero: { + ...hero, + name: async () => { + await resolveOnNextTick(); + return 'slow'; + }, + }, + }); expectJSON(result).toDeepEqual([ { data: { @@ -602,7 +608,7 @@ describe('Execute: defer directive', () => { { incremental: [ { - data: { slowField: 'slow', friends: [{}, {}, {}] }, + data: { name: 'slow', friends: [{}, {}, {}] }, path: ['hero'], }, ], @@ -671,8 +677,8 @@ describe('Execute: defer directive', () => { const document = parse(` query { hero { - asyncFriends { - promiseNonNullErrorField + friends { + nonNullName ...NameFragment @defer } } @@ -681,19 +687,29 @@ describe('Execute: defer directive', () => { name } `); - const result = await complete(document); + const result = await complete(document, { + hero: { + ...hero, + async *friends() { + yield await Promise.resolve({ + ...friends[0], + nonNullName: () => Promise.resolve(null), + }); + }, + }, + }); expectJSON(result).toDeepEqual({ data: { hero: { - asyncFriends: [null], + friends: [null], }, }, errors: [ { message: - 'Cannot return null for non-nullable field Friend.promiseNonNullErrorField.', + 'Cannot return null for non-nullable field Friend.nonNullName.', locations: [{ line: 5, column: 11 }], - path: ['hero', 'asyncFriends', 0, 'promiseNonNullErrorField'], + path: ['hero', 'friends', 0, 'nonNullName'], }, ], }); @@ -719,7 +735,7 @@ describe('Execute: defer directive', () => { it('original execute function resolves to error if anything is deferred and something else is async', async () => { const doc = ` query Deferred { - hero { slowField } + hero { name } ... @defer { hero { id } } } `; @@ -727,7 +743,15 @@ describe('Execute: defer directive', () => { execute({ schema, document: parse(doc), - rootValue: {}, + rootValue: { + hero: { + ...hero, + name: async () => { + await resolveOnNextTick(); + return 'slow'; + }, + }, + }, }), ).toRejectWith( 'Executing this GraphQL operation would unexpectedly produce multiple payloads (due to @defer or @stream directive)',