From a0b561dbd346b91fe9c083394c57d8f1faa22079 Mon Sep 17 00:00:00 2001 From: tinnou Date: Thu, 7 Mar 2019 18:10:37 -0800 Subject: [PATCH 1/2] Fix #1440 ClassCastException when using a fragment with wrong input type condition and overlapping fields are being merged. --- .../rules/OverlappingFieldsCanBeMerged.java | 4 +- src/test/groovy/graphql/Issue1440.groovy | 90 +++++++++++++++++++ 2 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 src/test/groovy/graphql/Issue1440.groovy diff --git a/src/main/java/graphql/validation/rules/OverlappingFieldsCanBeMerged.java b/src/main/java/graphql/validation/rules/OverlappingFieldsCanBeMerged.java index 8a5d81ea1e..ec3adf4a1c 100644 --- a/src/main/java/graphql/validation/rules/OverlappingFieldsCanBeMerged.java +++ b/src/main/java/graphql/validation/rules/OverlappingFieldsCanBeMerged.java @@ -305,14 +305,14 @@ private void collectFieldsForFragmentSpread(Map> fiel return; } visitedFragmentSpreads.add(fragment.getName()); - GraphQLOutputType graphQLType = (GraphQLOutputType) TypeFromAST.getTypeFromAST(getValidationContext().getSchema(), + GraphQLType graphQLType = TypeFromAST.getTypeFromAST(getValidationContext().getSchema(), fragment.getTypeCondition()); collectFields(fieldMap, fragment.getSelectionSet(), graphQLType, visitedFragmentSpreads); } private void collectFieldsForInlineFragment(Map> fieldMap, Set visitedFragmentSpreads, GraphQLType parentType, InlineFragment inlineFragment) { GraphQLType graphQLType = inlineFragment.getTypeCondition() != null - ? (GraphQLOutputType) TypeFromAST.getTypeFromAST(getValidationContext().getSchema(), inlineFragment.getTypeCondition()) + ? TypeFromAST.getTypeFromAST(getValidationContext().getSchema(), inlineFragment.getTypeCondition()) : parentType; collectFields(fieldMap, inlineFragment.getSelectionSet(), graphQLType, visitedFragmentSpreads); } diff --git a/src/test/groovy/graphql/Issue1440.groovy b/src/test/groovy/graphql/Issue1440.groovy new file mode 100644 index 0000000000..2abd464b59 --- /dev/null +++ b/src/test/groovy/graphql/Issue1440.groovy @@ -0,0 +1,90 @@ +package graphql + +import graphql.validation.ValidationError +import graphql.validation.ValidationErrorType +import spock.lang.Specification + +class Issue1440 extends Specification { + + def schema = TestUtil.schema(""" + type Query { + nothing: String + } + + type Mutation { + updateUDI(input: UDIInput!): UDIOutput + } + + type UDIOutput { + device: String + version: String + } + + input UDIInput { + device: String + version: String + } + """) + + def graphQL = GraphQL.newGraphQL(schema).build() + + + def "#1440 when fragment type condition is input type it should return validation error - not classCastException"() { + when: + def executionInput = ExecutionInput.newExecutionInput() + .query(''' + mutation UpdateUDI($input: UDIInput!) { + updateUDI(input: $input) { + ...fragOnInputType + __typename + } + } + + # fragment should only target composite types + fragment fragOnInputType on UDIInput { + device + version + __typename + } + + ''') + .variables([input: [device: 'device', version: 'version'] ]) + .build() + + def executionResult = graphQL.execute(executionInput) + + then: + + executionResult.data == null + executionResult.errors.size() == 1 + (executionResult.errors[0] as ValidationError).validationErrorType == ValidationErrorType.InlineFragmentTypeConditionInvalid + } + + def "#1440 when inline fragment type condition is input type it should return validation error - not classCastException"() { + when: + def executionInput = ExecutionInput.newExecutionInput() + .query(''' + mutation UpdateUDI($input: UDIInput!) { + updateUDI(input: $input) { + # fragment should only target composite types + ... on UDIInput { + device + version + __typename + } + __typename + } + } + ''') + .variables([input: [device: 'device', version: 'version'] ]) + .build() + + def executionResult = graphQL.execute(executionInput) + + then: + + executionResult.data == null + executionResult.errors.size() == 1 + (executionResult.errors[0] as ValidationError).validationErrorType == ValidationErrorType.InlineFragmentTypeConditionInvalid + } +} From 78d7b159b5e1048278e569bae54e1db19316ad24 Mon Sep 17 00:00:00 2001 From: tinnou Date: Mon, 11 Mar 2019 10:58:50 -0700 Subject: [PATCH 2/2] Fix Enum value for FragmentsOnCompositeType --- .../java/graphql/validation/rules/FragmentsOnCompositeType.java | 2 +- src/test/groovy/graphql/Issue1440.groovy | 2 +- .../validation/rules/FragmentsOnCompositeTypeTest.groovy | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/graphql/validation/rules/FragmentsOnCompositeType.java b/src/main/java/graphql/validation/rules/FragmentsOnCompositeType.java index 2114c5c669..d7087321ac 100644 --- a/src/main/java/graphql/validation/rules/FragmentsOnCompositeType.java +++ b/src/main/java/graphql/validation/rules/FragmentsOnCompositeType.java @@ -36,7 +36,7 @@ public void checkFragmentDefinition(FragmentDefinition fragmentDefinition) { if (type == null) return; if (!(type instanceof GraphQLCompositeType)) { String message = "Fragment type condition is invalid, must be on Object/Interface/Union"; - addError(ValidationErrorType.InlineFragmentTypeConditionInvalid, fragmentDefinition.getSourceLocation(), message); + addError(ValidationErrorType.FragmentTypeConditionInvalid, fragmentDefinition.getSourceLocation(), message); } } } diff --git a/src/test/groovy/graphql/Issue1440.groovy b/src/test/groovy/graphql/Issue1440.groovy index 2abd464b59..f1b9fef5bf 100644 --- a/src/test/groovy/graphql/Issue1440.groovy +++ b/src/test/groovy/graphql/Issue1440.groovy @@ -57,7 +57,7 @@ class Issue1440 extends Specification { executionResult.data == null executionResult.errors.size() == 1 - (executionResult.errors[0] as ValidationError).validationErrorType == ValidationErrorType.InlineFragmentTypeConditionInvalid + (executionResult.errors[0] as ValidationError).validationErrorType == ValidationErrorType.FragmentTypeConditionInvalid } def "#1440 when inline fragment type condition is input type it should return validation error - not classCastException"() { diff --git a/src/test/groovy/graphql/validation/rules/FragmentsOnCompositeTypeTest.groovy b/src/test/groovy/graphql/validation/rules/FragmentsOnCompositeTypeTest.groovy index 381d61b22d..cc9deef310 100644 --- a/src/test/groovy/graphql/validation/rules/FragmentsOnCompositeTypeTest.groovy +++ b/src/test/groovy/graphql/validation/rules/FragmentsOnCompositeTypeTest.groovy @@ -68,7 +68,7 @@ class FragmentsOnCompositeTypeTest extends Specification { fragmentsOnCompositeType.checkFragmentDefinition(fragmentDefinition) then: - errorCollector.containsValidationError(ValidationErrorType.InlineFragmentTypeConditionInvalid) + errorCollector.containsValidationError(ValidationErrorType.FragmentTypeConditionInvalid) }