Skip to content

Commit 3295066

Browse files
#1914 Use default values for fields of input types when default argument value is provided (#2085)
* Use default values for fields of input types when default arguments are provided * #1914 Shortened test name * #1914 Added a test to verify if null value provided in input overrides default * #1914 Added a test with field having null value and refactored a long statement into a method * #1914 Updated test to have a field with default value null Co-authored-by: Priya Aggarwal <paggarwal@atlassian.com>
1 parent 0de364a commit 3295066

3 files changed

Lines changed: 150 additions & 3 deletions

File tree

src/main/java/graphql/schema/idl/SchemaGeneratorHelper.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import graphql.language.NullValue;
2525
import graphql.language.ObjectTypeDefinition;
2626
import graphql.language.ObjectTypeExtensionDefinition;
27+
import graphql.language.ObjectField;
2728
import graphql.language.ObjectValue;
2829
import graphql.language.OperationTypeDefinition;
2930
import graphql.language.ScalarTypeDefinition;
@@ -292,11 +293,24 @@ Object buildArrayValue(GraphQLType requiredType, ArrayValue arrayValue) {
292293

293294
Object buildObjectValue(ObjectValue defaultValue, GraphQLInputObjectType objectType) {
294295
Map<String, Object> map = new LinkedHashMap<>();
295-
defaultValue.getObjectFields().forEach(of -> map.put(of.getName(),
296-
buildValue(of.getValue(), objectType.getField(of.getName()).getType())));
296+
objectType.getFieldDefinitions().forEach(
297+
f -> {
298+
final Value<?> fieldValueFromDefaultObjectValue = getFieldValueFromObjectValue(defaultValue, f.getName());
299+
map.put(f.getName(), fieldValueFromDefaultObjectValue != null ? buildValue(fieldValueFromDefaultObjectValue, f.getType()) : f.getDefaultValue());
300+
}
301+
);
297302
return map;
298303
}
299304

305+
Value<?> getFieldValueFromObjectValue(final ObjectValue objectValue, final String fieldName) {
306+
return objectValue.getObjectFields()
307+
.stream()
308+
.filter(dvf -> dvf.getName().equals(fieldName))
309+
.map(ObjectField::getValue)
310+
.findFirst()
311+
.orElse(null);
312+
}
313+
300314
String buildDescription(Node<?> node, Description description) {
301315
if (description != null) {
302316
return description.getContent();
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package graphql
2+
3+
import graphql.schema.DataFetcher
4+
import spock.lang.Specification
5+
6+
class Issue1914 extends Specification {
7+
8+
def "default values in input objects are respected when variable is not provided"() {
9+
given:
10+
def spec = """type Query {
11+
sayHello(arg: Arg! = {}): String
12+
}
13+
input Arg {
14+
foo: String = "bar"
15+
}
16+
"""
17+
DataFetcher df = { dfe ->
18+
Map arg = dfe.getArgument("arg")
19+
return arg.get("foo")
20+
} as DataFetcher
21+
def graphQL = TestUtil.graphQL(spec, ["Query": ["sayHello": df]]).build()
22+
23+
when:
24+
def result = graphQL.execute('{sayHello}')
25+
26+
then:
27+
result.errors.isEmpty()
28+
result.data == [sayHello: "bar"]
29+
30+
}
31+
32+
def "default values in input objects are overridden when variable is provided"() {
33+
given:
34+
def spec = """type Query {
35+
sayHello(arg: Arg! = {foo: "brewery"}): String
36+
}
37+
input Arg {
38+
foo: String = "bar"
39+
}
40+
"""
41+
DataFetcher df = { dfe ->
42+
Map arg = dfe.getArgument("arg")
43+
return arg.get("foo")
44+
} as DataFetcher
45+
def graphQL = TestUtil.graphQL(spec, ["Query": ["sayHello": df]]).build()
46+
47+
when:
48+
def result = graphQL.execute('{sayHello}')
49+
50+
then:
51+
result.errors.isEmpty()
52+
result.data == [sayHello: "brewery"]
53+
54+
}
55+
56+
def "default values in input objects are overridden when null value is provided in input"() {
57+
given:
58+
def spec = """type Query {
59+
sayHello(arg: Arg! = {foo: null}): String
60+
}
61+
input Arg {
62+
foo: String = "bar"
63+
}
64+
"""
65+
DataFetcher df = { dfe ->
66+
Map arg = dfe.getArgument("arg")
67+
return arg.get("foo")
68+
} as DataFetcher
69+
def graphQL = TestUtil.graphQL(spec, ["Query": ["sayHello": df]]).build()
70+
71+
when:
72+
def result = graphQL.execute('{sayHello}')
73+
74+
then:
75+
result.errors.isEmpty()
76+
result.data == [sayHello: null]
77+
78+
}
79+
80+
def "default values in input objects are overridden when variable is provided and otherwise are respected"() {
81+
given:
82+
def spec = """type Query {
83+
sayHello(arg: Arg! = {field1: "F1ValOverride"}): String
84+
}
85+
input Arg {
86+
field1: String = "F1V"
87+
field2: String = "F2V"
88+
}
89+
"""
90+
DataFetcher df = { dfe ->
91+
Map arg = dfe.getArgument("arg")
92+
return arg.get("field1") + " & " + arg.get("field2")
93+
} as DataFetcher
94+
def graphQL = TestUtil.graphQL(spec, ["Query": ["sayHello": df]]).build()
95+
96+
when:
97+
def result = graphQL.execute('{sayHello}')
98+
99+
then:
100+
result.errors.isEmpty()
101+
result.data == [sayHello: "F1ValOverride & F2V"]
102+
103+
}
104+
105+
def "default values (including null) in input objects are overridden when variable is provided and otherwise are respected"() {
106+
given:
107+
def spec = """type Query {
108+
sayHello(arg: Arg! = {field1: "F1ValOverride", field5: "F5Val"}): String
109+
}
110+
input Arg {
111+
field1: String = "F1V"
112+
field2: String = "F2V"
113+
field3: String = null
114+
field4: String
115+
field5: String
116+
}
117+
"""
118+
DataFetcher df = { dfe ->
119+
Map arg = dfe.getArgument("arg")
120+
return arg.get("field1") + " & " + arg.get("field2") + " & " + arg.get("field3") + " & " + arg.get("field4") + " & " + arg.get("field5")
121+
} as DataFetcher
122+
def graphQL = TestUtil.graphQL(spec, ["Query": ["sayHello": df]]).build()
123+
124+
when:
125+
def result = graphQL.execute('{sayHello}')
126+
127+
then:
128+
result.errors.isEmpty()
129+
result.data == [sayHello: "F1ValOverride & F2V & null & null & F5Val"]
130+
131+
}
132+
}
133+

src/test/groovy/graphql/introspection/IntrospectionResultToSchemaTest.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ input CharacterInput {
590590
}
591591
592592
type Query {
593-
outputField(inputArg: InputType = {age : 666, name : "nameViaArg"}, inputBoolean: Boolean = true, inputInt: Int = 1, inputString: String = "viaArgString"): OutputType
593+
outputField(inputArg: InputType = {age : 666, complex : {boolean : true, int : 666, string : "string"}, name : "nameViaArg", rocks : true}, inputBoolean: Boolean = true, inputInt: Int = 1, inputString: String = "viaArgString"): OutputType
594594
}
595595
596596
input ComplexType {

0 commit comments

Comments
 (0)