Skip to content

Commit ff491fe

Browse files
authored
Merge pull request #3315 from graphql-java/21.x-backport-of-3286-null-fix
21.x Cherry pick pull request #3286
2 parents 36f8633 + e11e254 commit ff491fe

File tree

3 files changed

+79
-33
lines changed

3 files changed

+79
-33
lines changed

src/main/java/graphql/execution/ValuesResolverConversion.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,17 @@ static Object valueToLiteralImpl(GraphqlFieldVisibility fieldVisibility,
6969
if (valueMode == NORMALIZED) {
7070
return assertShouldNeverHappen("can't infer normalized structure");
7171
}
72-
return ValuesResolverLegacy.valueToLiteralLegacy(
72+
Value<?> value = ValuesResolverLegacy.valueToLiteralLegacy(
7373
inputValueWithState.getValue(),
7474
type,
7575
graphqlContext,
7676
locale);
77+
//
78+
// the valueToLiteralLegacy() nominally cant know if null means never set or is set to a null value
79+
// but this code can know - its is SET to a value so, it MUST be a Null Literal
80+
// this method would assert at the end of it if inputValueWithState.isNotSet() were true
81+
//
82+
return value == null ? NullValue.of() : value;
7783
}
7884
if (inputValueWithState.isLiteral()) {
7985
return inputValueWithState.getValue();

src/test/groovy/graphql/introspection/IntrospectionTest.groovy

Lines changed: 54 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package graphql.introspection
22

3+
34
import graphql.TestUtil
45
import graphql.schema.DataFetcher
56
import graphql.schema.FieldCoordinates
@@ -438,7 +439,7 @@ class IntrospectionTest extends Specification {
438439

439440
def "test AST printed introspection query is equivalent to original string"() {
440441
when:
441-
def oldIntrospectionQuery = "\n" +
442+
def oldIntrospectionQuery = "\n" +
442443
" query IntrospectionQuery {\n" +
443444
" __schema {\n" +
444445
" queryType { name }\n" +
@@ -540,12 +541,11 @@ class IntrospectionTest extends Specification {
540541
" }\n" +
541542
"\n"
542543

543-
def newIntrospectionQuery = IntrospectionQuery.INTROSPECTION_QUERY;
544+
def newIntrospectionQuery = IntrospectionQuery.INTROSPECTION_QUERY
544545

545546
then:
546-
oldIntrospectionQuery.replaceAll("\\s+","").equals(
547-
newIntrospectionQuery.replaceAll("\\s+","")
548-
)
547+
oldIntrospectionQuery.replaceAll("\\s+", "") ==
548+
newIntrospectionQuery.replaceAll("\\s+", "")
549549
}
550550

551551
def "test parameterized introspection queries"() {
@@ -582,44 +582,66 @@ class IntrospectionTest extends Specification {
582582

583583
def parseExecutionResult = {
584584
[
585-
it.data["__schema"]["types"].find{it["name"] == "Query"}["fields"].find{it["name"] == "notDeprecated"}["description"] != null, // descriptions is true
586-
it.data["__schema"]["types"].find{it["name"] == "UUID"}["specifiedByURL"] != null, // specifiedByUrl is true
587-
it.data["__schema"]["directives"].find{it["name"] == "repeatableDirective"}["isRepeatable"] != null, // directiveIsRepeatable is true
588-
it.data["__schema"]["description"] != null, // schemaDescription is true
589-
it.data["__schema"]["types"].find { it['name'] == 'InputType' }["inputFields"].find({ it["name"] == "inputField" }) != null // inputValueDeprecation is true
585+
it.data["__schema"]["types"].find { it["name"] == "Query" }["fields"].find { it["name"] == "notDeprecated" }["description"] != null, // descriptions is true
586+
it.data["__schema"]["types"].find { it["name"] == "UUID" }["specifiedByURL"] != null, // specifiedByUrl is true
587+
it.data["__schema"]["directives"].find { it["name"] == "repeatableDirective" }["isRepeatable"] != null, // directiveIsRepeatable is true
588+
it.data["__schema"]["description"] != null, // schemaDescription is true
589+
it.data["__schema"]["types"].find { it['name'] == 'InputType' }["inputFields"].find({ it["name"] == "inputField" }) != null // inputValueDeprecation is true
590590
]
591591
}
592592

593593
when:
594-
def allFalseExecutionResult = graphQL.execute(
594+
def allFalseExecutionResult = graphQL.execute(
595595
IntrospectionQueryBuilder.build(
596-
IntrospectionQueryBuilder.Options.defaultOptions()
597-
.descriptions(false)
598-
.specifiedByUrl(false)
599-
.directiveIsRepeatable(false)
600-
.schemaDescription(false)
601-
.inputValueDeprecation(false)
602-
.typeRefFragmentDepth(5)
596+
IntrospectionQueryBuilder.Options.defaultOptions()
597+
.descriptions(false)
598+
.specifiedByUrl(false)
599+
.directiveIsRepeatable(false)
600+
.schemaDescription(false)
601+
.inputValueDeprecation(false)
602+
.typeRefFragmentDepth(5)
603603
)
604-
)
604+
)
605605
then:
606-
!parseExecutionResult(allFalseExecutionResult).any()
607-
allFalseExecutionResult.data["__schema"]["types"].find{it["name"] == "Query"}["fields"].find{it["name"] == "tenDimensionalList"}["type"]["ofType"]["ofType"]["ofType"]["ofType"]["ofType"]["ofType"] == null // typeRefFragmentDepth is 5
606+
!parseExecutionResult(allFalseExecutionResult).any()
607+
allFalseExecutionResult.data["__schema"]["types"].find { it["name"] == "Query" }["fields"].find { it["name"] == "tenDimensionalList" }["type"]["ofType"]["ofType"]["ofType"]["ofType"]["ofType"]["ofType"] == null // typeRefFragmentDepth is 5
608608

609609
when:
610-
def allTrueExecutionResult = graphQL.execute(
610+
def allTrueExecutionResult = graphQL.execute(
611611
IntrospectionQueryBuilder.build(
612-
IntrospectionQueryBuilder.Options.defaultOptions()
613-
.descriptions(true)
614-
.specifiedByUrl(true)
615-
.directiveIsRepeatable(true)
616-
.schemaDescription(true)
617-
.inputValueDeprecation(true)
618-
.typeRefFragmentDepth(7)
612+
IntrospectionQueryBuilder.Options.defaultOptions()
613+
.descriptions(true)
614+
.specifiedByUrl(true)
615+
.directiveIsRepeatable(true)
616+
.schemaDescription(true)
617+
.inputValueDeprecation(true)
618+
.typeRefFragmentDepth(7)
619619
)
620-
)
620+
)
621+
then:
622+
parseExecutionResult(allTrueExecutionResult).every()
623+
allTrueExecutionResult.data["__schema"]["types"].find { it["name"] == "Query" }["fields"].find { it["name"] == "tenDimensionalList" }["type"]["ofType"]["ofType"]["ofType"]["ofType"]["ofType"]["ofType"]["ofType"]["ofType"] == null // typeRefFragmentDepth is 7
624+
}
625+
626+
def "issue 3285 - deprecated defaultValue on programmatic args prints AST literal as expected"() {
627+
def queryObjType = newObject().name("Query")
628+
.field(newFieldDefinition().name("f").type(GraphQLString)
629+
.argument(newArgument().name("arg").type(GraphQLString).defaultValue(null)))
630+
.build()
631+
def schema = newSchema().query(queryObjType).build()
632+
def graphQL = newGraphQL(schema).build()
633+
634+
635+
when:
636+
def executionResult = graphQL.execute(IntrospectionQuery.INTROSPECTION_QUERY)
621637
then:
622-
parseExecutionResult(allTrueExecutionResult).every()
623-
allTrueExecutionResult.data["__schema"]["types"].find{it["name"] == "Query"}["fields"].find{it["name"] == "tenDimensionalList"}["type"]["ofType"]["ofType"]["ofType"]["ofType"]["ofType"]["ofType"]["ofType"]["ofType"] == null // typeRefFragmentDepth is 7
638+
executionResult.errors.isEmpty()
639+
640+
def types = executionResult.data['__schema']['types'] as List
641+
def queryType = types.find { it['name'] == 'Query' }
642+
def fField = (queryType['fields'] as List)[0]
643+
def arg = (fField['args'] as List)[0]
644+
arg['name'] == "arg"
645+
arg['defaultValue'] == "null" // printed AST
624646
}
625647
}

src/test/groovy/graphql/schema/idl/SchemaPrinterTest.groovy

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2247,6 +2247,24 @@ type Query {
22472247
type TestObjectB {
22482248
field: String
22492249
}
2250+
'''
2251+
}
2252+
2253+
def "issue 3285 - deprecated defaultValue on programmatic args prints as expected"() {
2254+
def queryObjType = newObject().name("Query")
2255+
.field(newFieldDefinition().name("f").type(GraphQLString)
2256+
.argument(newArgument().name("arg").type(GraphQLString).defaultValue(null)))
2257+
.build()
2258+
def schema = GraphQLSchema.newSchema().query(queryObjType).build()
2259+
2260+
2261+
when:
2262+
def options = defaultOptions().includeDirectiveDefinitions(false)
2263+
def sdl = new SchemaPrinter(options).print(schema)
2264+
then:
2265+
sdl == '''type Query {
2266+
f(arg: String = null): String
2267+
}
22502268
'''
22512269
}
22522270
}

0 commit comments

Comments
 (0)