Skip to content

Commit 6a7efe6

Browse files
committed
Add an argument validation step
1 parent 18bee78 commit 6a7efe6

File tree

4 files changed

+68
-1
lines changed

4 files changed

+68
-1
lines changed

lib/graphql/schema.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1725,6 +1725,10 @@ def add_type_and_traverse(t, root:)
17251725
}
17261726

17271727
addition.directives.each { |dir_class| own_directives[dir_class.graphql_name] = dir_class }
1728+
1729+
addition.arguments_with_default_values.each do |arg|
1730+
arg.validate_default_value
1731+
end
17281732
end
17291733

17301734
def lazy_methods

lib/graphql/schema/addition.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
module GraphQL
44
class Schema
55
class Addition
6-
attr_reader :directives, :possible_types, :types, :union_memberships, :references
6+
attr_reader :directives, :possible_types, :types, :union_memberships, :references, :arguments_with_default_values
77

88
def initialize(schema:, own_types:, new_types:)
99
@schema = schema
@@ -13,6 +13,7 @@ def initialize(schema:, own_types:, new_types:)
1313
@types = {}
1414
@union_memberships = {}
1515
@references = Hash.new { |h, k| h[k] = [] }
16+
@arguments_with_default_values = []
1617
add_type_and_traverse(new_types)
1718
end
1819

@@ -164,6 +165,9 @@ def add_type(type, owner:, late_types:, path:)
164165
arg_type = arg.type.unwrap
165166
references_to(arg_type, from: arg)
166167
add_type(arg_type, owner: arg, late_types: late_types, path: path + [name])
168+
if arg.default_value?
169+
@arguments_with_default_values << arg
170+
end
167171
end
168172
else
169173
@types[type.graphql_name] = type
@@ -180,6 +184,9 @@ def add_type(type, owner:, late_types:, path:)
180184
arg_type = arg.type.unwrap
181185
references_to(arg_type, from: arg)
182186
add_type(arg_type, owner: arg, late_types: late_types, path: field_path + [arg_name])
187+
if arg.default_value?
188+
@arguments_with_default_values << arg
189+
end
183190
end
184191
end
185192
end
@@ -189,6 +196,9 @@ def add_type(type, owner:, late_types:, path:)
189196
arg_type = arg.type.unwrap
190197
references_to(arg_type, from: arg)
191198
add_type(arg_type, owner: arg, late_types: late_types, path: path + [arg_name])
199+
if arg.default_value?
200+
@arguments_with_default_values << arg
201+
end
192202
end
193203
end
194204
if type.kind.union?

lib/graphql/schema/argument.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,22 @@ def coerce_into_values(parent_object, values, context, argument_values)
295295
end
296296
end
297297

298+
# @api private
299+
def validate_default_value
300+
coerced_default_value = type.coerce_isolated_result(default_value) unless default_value.nil?
301+
res = type.valid_isolated_input?(coerced_default_value)
302+
if !res
303+
raise InvalidDefaultValueError.new(self)
304+
end
305+
end
306+
307+
class InvalidDefaultValueError < GraphQL::Error
308+
def initialize(argument)
309+
message = "`#{argument.path}` has an invalid default value: `#{argument.default_value.inspect}` isn't accepted by `#{argument.type.to_type_signature}`; update the default value or the argument type."
310+
super(message)
311+
end
312+
end
313+
298314
private
299315

300316
def validate_input_type(input_type)

spec/graphql/schema/argument_spec.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,4 +396,41 @@ class InvalidLazyArgumentObject < GraphQL::Schema::Object
396396
assert_equal expected_message, err.message
397397
end
398398
end
399+
400+
describe "validating default values" do
401+
it "raises when field argument default values are invalid" do
402+
query_type = Class.new(GraphQL::Schema::Object) do
403+
graphql_name "Query"
404+
field :f1, Integer, null: false do
405+
argument :arg1, Integer, default_value: nil, required: true
406+
end
407+
end
408+
409+
err = assert_raises GraphQL::Schema::Argument::InvalidDefaultValueError do
410+
Class.new(GraphQL::Schema) do
411+
query(query_type)
412+
end
413+
end
414+
expected_message = "`Query.f1.arg1` has an invalid default value: `nil` isn't accepted by `Int!`; update the default value or the argument type."
415+
assert_equal expected_message, err.message
416+
end
417+
418+
it "TODO: raises when input argument default values are invalid"
419+
420+
it "TODO: raises when directive argument default values are invalid"
421+
422+
it "raises when parsing a schema from a string" do
423+
schema_str = <<-GRAPHQL
424+
type Query {
425+
f1(arg1: Int! = null): Int!
426+
}
427+
GRAPHQL
428+
429+
err = assert_raises GraphQL::Schema::Argument::InvalidDefaultValueError do
430+
GraphQL::Schema.from_definition(schema_str)
431+
end
432+
expected_message = "`Query.f1.arg1` has an invalid default value: `nil` isn't accepted by `Int!`; update the default value or the argument type."
433+
assert_equal expected_message, err.message
434+
end
435+
end
399436
end

0 commit comments

Comments
 (0)