Skip to content

Commit 4841432

Browse files
@OneOf handles non-null inputs
1 parent 42870f3 commit 4841432

File tree

2 files changed

+56
-5
lines changed

2 files changed

+56
-5
lines changed

src/main/java/graphql/execution/ValuesResolver.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import graphql.schema.GraphQLScalarType;
2828
import graphql.schema.GraphQLSchema;
2929
import graphql.schema.GraphQLType;
30+
import graphql.schema.GraphQLTypeUtil;
3031
import graphql.schema.InputValueWithState;
3132
import graphql.schema.visibility.GraphqlFieldVisibility;
3233
import org.jetbrains.annotations.NotNull;
@@ -376,8 +377,9 @@ private static Map<String, Object> getArgumentValuesImpl(
376377
coercedValues.put(argumentName, value);
377378
}
378379
// @oneOf input must be checked now that all variables and literals have been converted
379-
if (argumentType instanceof GraphQLInputObjectType) {
380-
GraphQLInputObjectType inputObjectType = (GraphQLInputObjectType) argumentType;
380+
GraphQLType unwrappedType = GraphQLTypeUtil.unwrapNonNull(argumentType);
381+
if (unwrappedType instanceof GraphQLInputObjectType) {
382+
GraphQLInputObjectType inputObjectType = (GraphQLInputObjectType) unwrappedType;
381383
if (inputObjectType.isOneOf() && ! ValuesResolverConversion.isNullValue(value)) {
382384
validateOneOfInputTypes(inputObjectType, argumentValue, argumentName, value, locale);
383385
}

src/test/groovy/graphql/execution/ValuesResolverTest.groovy

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import graphql.language.Value
2323
import graphql.language.VariableDefinition
2424
import graphql.language.VariableReference
2525
import graphql.schema.CoercingParseValueException
26+
import graphql.schema.GraphQLNonNull
2627
import spock.lang.Specification
2728
import spock.lang.Unroll
2829

@@ -360,16 +361,26 @@ class ValuesResolverTest extends Specification {
360361
.type(GraphQLInt)
361362
.build())
362363
.build()
363-
def fieldArgument = newArgument().name("arg").type(inputObjectType).build()
364364

365-
when:
366365
def argument = new Argument("arg", inputValue)
366+
367+
when:
368+
def fieldArgument = newArgument().name("arg").type(inputObjectType).build()
367369
ValuesResolver.getArgumentValues([fieldArgument], [argument], variables, graphQLContext, locale)
368370

369371
then:
370372
def e = thrown(OneOfTooManyKeysException)
371373
e.message == "Exactly one key must be specified for OneOf type 'oneOfInputObject'."
372374

375+
when: "input type is wrapped in non-null"
376+
def nonNullInputObjectType = GraphQLNonNull.nonNull(inputObjectType)
377+
def fieldArgumentNonNull = newArgument().name("arg").type(nonNullInputObjectType).build()
378+
ValuesResolver.getArgumentValues([fieldArgumentNonNull], [argument], variables, graphQLContext, locale)
379+
380+
then:
381+
def eNonNull = thrown(OneOfTooManyKeysException)
382+
eNonNull.message == "Exactly one key must be specified for OneOf type 'oneOfInputObject'."
383+
373384
where:
374385
// from https://github.com/graphql/graphql-spec/pull/825/files#diff-30a69c5a5eded8e1aea52e53dad1181e6ec8f549ca2c50570b035153e2de1c43R1692
375386
testCase | inputValue | variables
@@ -502,6 +513,44 @@ class ValuesResolverTest extends Specification {
502513

503514
}
504515

516+
def "getArgumentValues: invalid oneOf input no values where passed - #testCase"() {
517+
given: "schema defining input object"
518+
def inputObjectType = newInputObject()
519+
.name("oneOfInputObject")
520+
.withAppliedDirective(Directives.OneOfDirective.toAppliedDirective())
521+
.field(newInputObjectField()
522+
.name("a")
523+
.type(GraphQLString)
524+
.build())
525+
.field(newInputObjectField()
526+
.name("b")
527+
.type(GraphQLInt)
528+
.build())
529+
.build()
530+
def fieldArgument = newArgument().name("arg").type(inputObjectType).build()
531+
532+
when:
533+
def argument = new Argument("arg", inputValue)
534+
ValuesResolver.getArgumentValues([fieldArgument], [argument], variables, graphQLContext, locale)
535+
536+
then:
537+
def e = thrown(OneOfNullValueException)
538+
e.message == "OneOf type field 'oneOfInputObject.a' must be non-null."
539+
540+
where:
541+
// from https://github.com/graphql/graphql-spec/pull/825/files#diff-30a69c5a5eded8e1aea52e53dad1181e6ec8f549ca2c50570b035153e2de1c43R1692
542+
testCase | inputValue | variables
543+
544+
'`{ a: null }` {}' | buildObjectLiteral([
545+
a: NullValue.of()
546+
]) | CoercedVariables.emptyVariables()
547+
548+
'`{ a: $var }` { var : null}' | buildObjectLiteral([
549+
a: VariableReference.of("var")
550+
]) | CoercedVariables.of(["var": null])
551+
552+
}
553+
505554
def "getVariableValues: enum as variable input"() {
506555
given:
507556
def enumDef = newEnum()
@@ -839,4 +888,4 @@ class ValuesResolverTest extends Specification {
839888
executionResult.errors[0].message == "Variable 'input' has an invalid value: Expected a value that can be converted to type 'Float' but it was a 'String'"
840889
executionResult.errors[0].locations == [new SourceLocation(2, 35)]
841890
}
842-
}
891+
}

0 commit comments

Comments
 (0)