From be08d15c77df5f92c8d2903bdbc7e75e299a119e Mon Sep 17 00:00:00 2001 From: Steve Hollaar Date: Thu, 19 Apr 2018 12:06:22 -0700 Subject: [PATCH] RequiredFields rule supports inline fragments --- src/rules.js | 18 +++++++++++++++--- test/makeRule.js | 12 +++++++++++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/rules.js b/src/rules.js index 88a65fe4..683b267f 100644 --- a/src/rules.js +++ b/src/rules.js @@ -12,6 +12,20 @@ export function OperationsMustHaveNames(context) { }; } +function getFieldWasRequestedOnNode(node, field, recursing = false) { + return node.selectionSet.selections.some(n => { + // If it's an inline fragment, we need to look deeper + if (n.kind === 'InlineFragment' && !recursing) { + return getFieldWasRequestedOnNode(n, field, true); + } + if (n.kind === 'FragmentSpread') { + // We don't know if the field was requested in this case, so default to not erroring. + return true; + } + return n.name.value === field; + }); +} + export function RequiredFields(context, options) { return { Field(node) { @@ -32,9 +46,7 @@ export function RequiredFields(context, options) { fieldAvaliableOnOfType = recursivelyCheckOnType(def.type.ofType, field); } if (fieldAvaliableOnType || fieldAvaliableOnOfType) { - const fieldWasRequested = !!node.selectionSet.selections.find( - n => (n.name.value === field || n.kind === 'FragmentSpread') - ); + const fieldWasRequested = getFieldWasRequestedOnNode(node, field); if (!fieldWasRequested) { context.reportError( new GraphQLError(`'${field}' field required on '${node.name.value}'`, [node]) diff --git a/test/makeRule.js b/test/makeRule.js index 94a431c5..c860c680 100644 --- a/test/makeRule.js +++ b/test/makeRule.js @@ -856,7 +856,8 @@ const requiredFieldsTestCases = { pass: [ 'const x = gql`query { allFilms { films { title } } }`', 'const x = gql`query { stories { id comments { text } } }`', - 'const x = gql`query { greetings { id, hello, foo } }`' + 'const x = gql`query { greetings { id, hello, foo } }`', + 'const x = gql`query { greetings { hello ... on Greetings { id } } }`', ], fail: [ { @@ -873,6 +874,15 @@ const requiredFieldsTestCases = { type: 'TaggedTemplateExpression', }], }, + { + code: 'const x = gql`query { greetings { hello ... on Greetings { foo } } }`', + errors: [ + { + message: `'id' field required on 'greetings'`, + type: 'TaggedTemplateExpression', + }, + ], + }, ], };