graphql 1.9.9 → 1.9.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/graphql/analysis/ast/query_depth.rb +12 -1
- data/lib/graphql/language/nodes.rb +11 -8
- data/lib/graphql/query.rb +4 -4
- data/lib/graphql/schema.rb +1 -1
- data/lib/graphql/schema/member/has_fields.rb +2 -2
- data/lib/graphql/schema/validation.rb +0 -4
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +14 -2
- data/spec/graphql/analysis/ast/max_query_depth_spec.rb +14 -15
- data/spec/graphql/analysis/max_query_complexity_spec.rb +16 -8
- data/spec/graphql/analysis/max_query_depth_spec.rb +12 -3
- data/spec/graphql/query_spec.rb +13 -10
- data/spec/graphql/schema/argument_spec.rb +42 -8
- data/spec/graphql/schema/object_spec.rb +19 -0
- data/spec/graphql/schema/printer_spec.rb +14 -0
- data/spec/graphql/schema/validation_spec.rb +4 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 239691cd4bf2f9f93314691a4ae3206438e2c51d544b3ef03f6928f62d5930a2
|
4
|
+
data.tar.gz: bb8c26e8da805c1020692ac979a5717a521aa14a353e17c0eaddb30ce1ebc092
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32e52e6bc896c1b2f62bdefd4ce905ecbead2c81b52e2dac53700fd6a5956ccc594d4ff8eff5c314f496e44b16ab91ad7a3c1ed3c4e784bee489433b19853faa
|
7
|
+
data.tar.gz: 386a90ecd152c2b450d5c2045814241a6660180aef8edca92eea062cdc2285aa2545045390fa53bd92f0a5423ae2622aa18f7815e73fef5d902649f77e44b80b
|
@@ -3,13 +3,24 @@ module GraphQL
|
|
3
3
|
module Analysis
|
4
4
|
# A query reducer for measuring the depth of a given query.
|
5
5
|
#
|
6
|
+
# See https://graphql-ruby.org/queries/ast_analysis.html for more examples.
|
7
|
+
#
|
6
8
|
# @example Logging the depth of a query
|
7
9
|
# class LogQueryDepth < GraphQL::Analysis::QueryDepth
|
8
|
-
# def
|
10
|
+
# def result
|
9
11
|
# log("GraphQL query depth: #{@max_depth}")
|
10
12
|
# end
|
11
13
|
# end
|
12
14
|
#
|
15
|
+
# # In your Schema file:
|
16
|
+
#
|
17
|
+
# class MySchema < GraphQL::Schema
|
18
|
+
# use GraphQL::Analysis::AST
|
19
|
+
# query_analyzer LogQueryDepth
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # When you run the query, the depth will get logged:
|
23
|
+
#
|
13
24
|
# Schema.execute(query_str)
|
14
25
|
# # GraphQL query depth: 8
|
15
26
|
#
|
@@ -61,6 +61,7 @@ module GraphQL
|
|
61
61
|
def initialize_copy(other)
|
62
62
|
@children = nil
|
63
63
|
@scalars = nil
|
64
|
+
@query_string = nil
|
64
65
|
end
|
65
66
|
|
66
67
|
# @return [Symbol] the method to call on {Language::Visitor} for this node
|
@@ -84,14 +85,7 @@ module GraphQL
|
|
84
85
|
# @param new_options [Hash]
|
85
86
|
# @return [AbstractNode] a shallow copy of `self`
|
86
87
|
def merge(new_options)
|
87
|
-
|
88
|
-
new_options.each do |key, value|
|
89
|
-
copied_self.instance_variable_set(:"@#{key}", value)
|
90
|
-
if copied_self.instance_variable_defined?(:@query_string)
|
91
|
-
copied_self.instance_variable_set(:@query_string, nil)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
copied_self
|
88
|
+
dup.merge!(new_options)
|
95
89
|
end
|
96
90
|
|
97
91
|
# Copy `self`, but modify the copy so that `previous_child` is replaced by `new_child`
|
@@ -129,6 +123,15 @@ module GraphQL
|
|
129
123
|
copy_of_self
|
130
124
|
end
|
131
125
|
|
126
|
+
protected
|
127
|
+
|
128
|
+
def merge!(new_options)
|
129
|
+
new_options.each do |key, value|
|
130
|
+
instance_variable_set(:"@#{key}", value)
|
131
|
+
end
|
132
|
+
self
|
133
|
+
end
|
134
|
+
|
132
135
|
class << self
|
133
136
|
# Add a default `#visit_method` and `#children_method_name` using the class name
|
134
137
|
def inherited(child_class)
|
data/lib/graphql/query.rb
CHANGED
@@ -78,7 +78,7 @@ module GraphQL
|
|
78
78
|
# @param max_complexity [Numeric] the maximum field complexity for this query (falls back to schema-level value)
|
79
79
|
# @param except [<#call(schema_member, context)>] If provided, objects will be hidden from the schema when `.call(schema_member, context)` returns truthy
|
80
80
|
# @param only [<#call(schema_member, context)>] If provided, objects will be hidden from the schema when `.call(schema_member, context)` returns false
|
81
|
-
def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth:
|
81
|
+
def initialize(schema, query_string = nil, query: nil, document: nil, context: nil, variables: nil, validate: true, subscription_topic: nil, operation_name: nil, root_value: nil, max_depth: schema.max_depth, max_complexity: schema.max_complexity, except: nil, only: nil)
|
82
82
|
# Even if `variables: nil` is passed, use an empty hash for simpler logic
|
83
83
|
variables ||= {}
|
84
84
|
@schema = schema
|
@@ -127,8 +127,8 @@ module GraphQL
|
|
127
127
|
@operation_name = operation_name
|
128
128
|
@prepared_ast = false
|
129
129
|
@validation_pipeline = nil
|
130
|
-
@max_depth = max_depth
|
131
|
-
@max_complexity = max_complexity
|
130
|
+
@max_depth = max_depth
|
131
|
+
@max_complexity = max_complexity
|
132
132
|
|
133
133
|
@result_values = nil
|
134
134
|
@executed = false
|
@@ -368,7 +368,7 @@ module GraphQL
|
|
368
368
|
parse_error: parse_error,
|
369
369
|
operation_name_error: operation_name_error,
|
370
370
|
max_depth: @max_depth,
|
371
|
-
max_complexity: @max_complexity
|
371
|
+
max_complexity: @max_complexity
|
372
372
|
)
|
373
373
|
end
|
374
374
|
|
data/lib/graphql/schema.rb
CHANGED
@@ -705,7 +705,7 @@ module GraphQL
|
|
705
705
|
# Eventually, the methods will be moved into this class, removing the need for the singleton.
|
706
706
|
def_delegators :graphql_definition,
|
707
707
|
# Schema structure
|
708
|
-
:as_json, :to_json, :to_document, :to_definition,
|
708
|
+
:as_json, :to_json, :to_document, :to_definition, :ast_node,
|
709
709
|
# Execution
|
710
710
|
:execute, :multiplex,
|
711
711
|
:static_validator, :introspection_system,
|
@@ -53,8 +53,8 @@ module GraphQL
|
|
53
53
|
# @param field_defn [GraphQL::Schema::Field]
|
54
54
|
# @return [void]
|
55
55
|
def add_field(field_defn)
|
56
|
-
if CONFLICT_FIELD_NAMES.include?(field_defn.resolver_method
|
57
|
-
warn "#{self.graphql_name}'s `field :#{field_defn.
|
56
|
+
if CONFLICT_FIELD_NAMES.include?(field_defn.original_name) && field_defn.original_name == field_defn.resolver_method
|
57
|
+
warn "#{self.graphql_name}'s `field :#{field_defn.original_name}` conflicts with a built-in method, use `resolver_method:` to pick a different resolver method for this field (for example, `resolver_method: :resolve_#{field_defn.original_name}` and `def resolve_#{field_defn.original_name}`)"
|
58
58
|
end
|
59
59
|
own_fields[field_defn.name] = field_defn
|
60
60
|
nil
|
@@ -104,10 +104,6 @@ module GraphQL
|
|
104
104
|
ARGUMENTS_ARE_VALID = Rules.assert_named_items_are_valid("argument", ->(type) { type.arguments.values })
|
105
105
|
|
106
106
|
DEFAULT_VALUE_IS_VALID_FOR_TYPE = ->(type) {
|
107
|
-
if !type.default_value.nil? && type.type.is_a?(NonNullType)
|
108
|
-
return %Q(Variable #{type.name} of type "#{type.type}" is required and will not use the default value. Perhaps you meant to use type "#{type.type.of_type}".)
|
109
|
-
end
|
110
|
-
|
111
107
|
if !type.default_value.nil?
|
112
108
|
coerced_value = begin
|
113
109
|
type.type.coerce_isolated_result(type.default_value)
|
@@ -18,7 +18,7 @@ module GraphQL
|
|
18
18
|
def assert_required_args(ast_node, defn)
|
19
19
|
present_argument_names = ast_node.arguments.map(&:name)
|
20
20
|
required_argument_names = context.warden.arguments(defn)
|
21
|
-
.select { |a| a.type.kind.non_null? }
|
21
|
+
.select { |a| a.type.kind.non_null? && !a.default_value? }
|
22
22
|
.map(&:name)
|
23
23
|
|
24
24
|
missing_names = required_argument_names - present_argument_names
|
data/lib/graphql/version.rb
CHANGED
@@ -45,7 +45,7 @@ describe GraphQL::Analysis::AST::MaxQueryComplexity do
|
|
45
45
|
|
46
46
|
describe "when max_complexity is decreased at query-level" do
|
47
47
|
before do
|
48
|
-
schema.max_complexity
|
48
|
+
schema.max_complexity(100)
|
49
49
|
end
|
50
50
|
|
51
51
|
let(:max_complexity) { 7 }
|
@@ -58,7 +58,7 @@ describe GraphQL::Analysis::AST::MaxQueryComplexity do
|
|
58
58
|
|
59
59
|
describe "when max_complexity is increased at query-level" do
|
60
60
|
before do
|
61
|
-
schema.max_complexity
|
61
|
+
schema.max_complexity(1)
|
62
62
|
end
|
63
63
|
|
64
64
|
let(:max_complexity) { 10 }
|
@@ -68,6 +68,18 @@ describe GraphQL::Analysis::AST::MaxQueryComplexity do
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
+
describe "when max_complexity is nil at query-level" do
|
72
|
+
let(:max_complexity) { nil }
|
73
|
+
|
74
|
+
before do
|
75
|
+
schema.max_complexity(1)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "is applied" do
|
79
|
+
assert_nil result
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
71
83
|
describe "across a multiplex" do
|
72
84
|
before do
|
73
85
|
schema.analysis_engine = GraphQL::Analysis::AST
|
@@ -20,29 +20,27 @@ describe GraphQL::Analysis::AST::MaxQueryDepth do
|
|
20
20
|
}
|
21
21
|
}
|
22
22
|
"}
|
23
|
-
let(:
|
24
|
-
let(:query) {
|
25
|
-
GraphQL::Query.new(
|
26
|
-
schema.graphql_definition,
|
27
|
-
query_string,
|
28
|
-
variables: {},
|
29
|
-
max_depth: max_depth
|
30
|
-
)
|
31
|
-
}
|
23
|
+
let(:query) { GraphQL::Query.new(schema, query_string) }
|
32
24
|
let(:result) {
|
33
25
|
GraphQL::Analysis::AST.analyze_query(query, [GraphQL::Analysis::AST::MaxQueryDepth]).first
|
34
26
|
}
|
35
27
|
|
36
28
|
describe "when the query is deeper than max depth" do
|
37
|
-
let(:max_depth) { 5 }
|
38
|
-
|
39
29
|
it "adds an error message for a too-deep query" do
|
40
30
|
assert_equal "Query has depth of 7, which exceeds max depth of 5", result.message
|
41
31
|
end
|
42
32
|
end
|
43
33
|
|
44
34
|
describe "when the query specifies a different max_depth" do
|
45
|
-
let(:
|
35
|
+
let(:query) { GraphQL::Query.new(schema, query_string, max_depth: 100) }
|
36
|
+
|
37
|
+
it "obeys that max_depth" do
|
38
|
+
assert_nil result
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "when the query disables max_depth" do
|
43
|
+
let(:query) { GraphQL::Query.new(schema, query_string, max_depth: nil) }
|
46
44
|
|
47
45
|
it "obeys that max_depth" do
|
48
46
|
assert_nil result
|
@@ -51,7 +49,7 @@ describe GraphQL::Analysis::AST::MaxQueryDepth do
|
|
51
49
|
|
52
50
|
describe "When the query is not deeper than max_depth" do
|
53
51
|
before do
|
54
|
-
schema.max_depth
|
52
|
+
schema.max_depth(100)
|
55
53
|
end
|
56
54
|
|
57
55
|
it "doesn't add an error" do
|
@@ -61,7 +59,8 @@ describe GraphQL::Analysis::AST::MaxQueryDepth do
|
|
61
59
|
|
62
60
|
describe "when the max depth isn't set" do
|
63
61
|
before do
|
64
|
-
|
62
|
+
# Yuck - Can't override GraphQL::Schema.max_depth to return nil if it has already been set
|
63
|
+
schema.define_singleton_method(:max_depth) { |*| nil }
|
65
64
|
end
|
66
65
|
|
67
66
|
it "doesn't add an error message" do
|
@@ -71,7 +70,7 @@ describe GraphQL::Analysis::AST::MaxQueryDepth do
|
|
71
70
|
|
72
71
|
describe "when a fragment exceeds max depth" do
|
73
72
|
before do
|
74
|
-
schema.max_depth
|
73
|
+
schema.max_depth(4)
|
75
74
|
end
|
76
75
|
|
77
76
|
let(:query_string) { "
|
@@ -16,7 +16,7 @@ describe GraphQL::Analysis::MaxQueryComplexity do
|
|
16
16
|
|
17
17
|
describe "when a query goes over max complexity" do
|
18
18
|
before do
|
19
|
-
schema.max_complexity
|
19
|
+
schema.max_complexity(9)
|
20
20
|
end
|
21
21
|
|
22
22
|
it "returns an error" do
|
@@ -25,9 +25,6 @@ describe GraphQL::Analysis::MaxQueryComplexity do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
describe "when there is no max complexity" do
|
28
|
-
before do
|
29
|
-
schema.max_complexity = nil
|
30
|
-
end
|
31
28
|
it "doesn't error" do
|
32
29
|
assert_nil result["errors"]
|
33
30
|
end
|
@@ -35,7 +32,7 @@ describe GraphQL::Analysis::MaxQueryComplexity do
|
|
35
32
|
|
36
33
|
describe "when the query is less than the max complexity" do
|
37
34
|
before do
|
38
|
-
schema.max_complexity
|
35
|
+
schema.max_complexity(99)
|
39
36
|
end
|
40
37
|
it "doesn't error" do
|
41
38
|
assert_nil result["errors"]
|
@@ -44,7 +41,7 @@ describe GraphQL::Analysis::MaxQueryComplexity do
|
|
44
41
|
|
45
42
|
describe "when max_complexity is decreased at query-level" do
|
46
43
|
before do
|
47
|
-
schema.max_complexity
|
44
|
+
schema.max_complexity(100)
|
48
45
|
end
|
49
46
|
let(:result) {schema.execute(query_string, max_complexity: 7) }
|
50
47
|
|
@@ -55,7 +52,7 @@ describe GraphQL::Analysis::MaxQueryComplexity do
|
|
55
52
|
|
56
53
|
describe "when max_complexity is increased at query-level" do
|
57
54
|
before do
|
58
|
-
schema.max_complexity
|
55
|
+
schema.max_complexity(1)
|
59
56
|
end
|
60
57
|
let(:result) {schema.execute(query_string, max_complexity: 10) }
|
61
58
|
|
@@ -64,9 +61,20 @@ describe GraphQL::Analysis::MaxQueryComplexity do
|
|
64
61
|
end
|
65
62
|
end
|
66
63
|
|
64
|
+
describe "when max_complexity is nil query-level" do
|
65
|
+
before do
|
66
|
+
schema.max_complexity(1)
|
67
|
+
end
|
68
|
+
let(:result) {schema.execute(query_string, max_complexity: nil) }
|
69
|
+
|
70
|
+
it "is applied" do
|
71
|
+
assert_nil result["errors"]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
67
75
|
describe "across a multiplex" do
|
68
76
|
before do
|
69
|
-
schema.max_complexity
|
77
|
+
schema.max_complexity(9)
|
70
78
|
end
|
71
79
|
|
72
80
|
let(:queries) { 5.times.map { |n| { query: "{ cheese(id: #{n}) { id } }" } } }
|
@@ -36,9 +36,17 @@ describe GraphQL::Analysis::MaxQueryDepth do
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
describe "when the query specifies a nil max_depth" do
|
40
|
+
let(:result) { schema.execute(query_string, max_depth: nil) }
|
41
|
+
|
42
|
+
it "obeys that max_depth" do
|
43
|
+
assert_nil result["errors"]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
39
47
|
describe "When the query is not deeper than max_depth" do
|
40
48
|
before do
|
41
|
-
schema.max_depth
|
49
|
+
schema.max_depth(100)
|
42
50
|
end
|
43
51
|
|
44
52
|
it "doesn't add an error" do
|
@@ -48,7 +56,8 @@ describe GraphQL::Analysis::MaxQueryDepth do
|
|
48
56
|
|
49
57
|
describe "when the max depth isn't set" do
|
50
58
|
before do
|
51
|
-
|
59
|
+
# Yuck - Can't override GraphQL::Schema.max_depth to return nil if it has already been set
|
60
|
+
schema.define_singleton_method(:max_depth) { |*| nil }
|
52
61
|
end
|
53
62
|
|
54
63
|
it "doesn't add an error message" do
|
@@ -58,7 +67,7 @@ describe GraphQL::Analysis::MaxQueryDepth do
|
|
58
67
|
|
59
68
|
describe "when a fragment exceeds max depth" do
|
60
69
|
before do
|
61
|
-
schema.max_depth
|
70
|
+
schema.max_depth(4)
|
62
71
|
end
|
63
72
|
|
64
73
|
let(:query_string) { "
|
data/spec/graphql/query_spec.rb
CHANGED
@@ -30,7 +30,6 @@ describe GraphQL::Query do
|
|
30
30
|
}
|
31
31
|
|}
|
32
32
|
let(:operation_name) { nil }
|
33
|
-
let(:max_depth) { nil }
|
34
33
|
let(:query_variables) { {"cheeseId" => 2} }
|
35
34
|
let(:schema) { Dummy::Schema }
|
36
35
|
let(:document) { GraphQL.parse(query_string) }
|
@@ -39,8 +38,7 @@ describe GraphQL::Query do
|
|
39
38
|
schema,
|
40
39
|
query_string,
|
41
40
|
variables: query_variables,
|
42
|
-
operation_name: operation_name
|
43
|
-
max_depth: max_depth,
|
41
|
+
operation_name: operation_name
|
44
42
|
)}
|
45
43
|
let(:result) { query.result }
|
46
44
|
|
@@ -71,8 +69,7 @@ describe GraphQL::Query do
|
|
71
69
|
res = GraphQL::Query.new(
|
72
70
|
schema,
|
73
71
|
variables: query_variables,
|
74
|
-
operation_name: operation_name
|
75
|
-
max_depth: max_depth,
|
72
|
+
operation_name: operation_name
|
76
73
|
).result
|
77
74
|
assert_equal 1, res["errors"].length
|
78
75
|
assert_equal "No query string was present", res["errors"][0]["message"]
|
@@ -82,8 +79,7 @@ describe GraphQL::Query do
|
|
82
79
|
query = GraphQL::Query.new(
|
83
80
|
schema,
|
84
81
|
variables: query_variables,
|
85
|
-
operation_name: operation_name
|
86
|
-
max_depth: max_depth,
|
82
|
+
operation_name: operation_name
|
87
83
|
)
|
88
84
|
query.query_string = '{ __type(name: """Cheese""") { name } }'
|
89
85
|
assert_equal "Cheese", query.result["data"] ["__type"]["name"]
|
@@ -174,8 +170,7 @@ describe GraphQL::Query do
|
|
174
170
|
schema,
|
175
171
|
document: document,
|
176
172
|
variables: query_variables,
|
177
|
-
operation_name: operation_name
|
178
|
-
max_depth: max_depth,
|
173
|
+
operation_name: operation_name
|
179
174
|
)}
|
180
175
|
|
181
176
|
it "runs the query using the already parsed document" do
|
@@ -560,7 +555,15 @@ describe GraphQL::Query do
|
|
560
555
|
end
|
561
556
|
|
562
557
|
describe "overriding max_depth" do
|
563
|
-
let(:
|
558
|
+
let(:query) {
|
559
|
+
GraphQL::Query.new(
|
560
|
+
schema,
|
561
|
+
query_string,
|
562
|
+
variables: query_variables,
|
563
|
+
operation_name: operation_name,
|
564
|
+
max_depth: 12
|
565
|
+
)
|
566
|
+
}
|
564
567
|
|
565
568
|
it "overrides the schema's max_depth" do
|
566
569
|
assert result["data"].key?("cheese")
|
@@ -10,7 +10,7 @@ describe GraphQL::Schema::Argument do
|
|
10
10
|
argument :arg_with_block, String, required: false do
|
11
11
|
description "test"
|
12
12
|
end
|
13
|
-
|
13
|
+
argument :required_with_default_arg, Int, required: true, default_value: 1
|
14
14
|
argument :aliased_arg, String, required: false, as: :renamed
|
15
15
|
argument :prepared_arg, Int, required: false, prepare: :multiply
|
16
16
|
argument :prepared_by_proc_arg, Int, required: false, prepare: ->(val, context) { context[:multiply_by] * val }
|
@@ -30,7 +30,11 @@ describe GraphQL::Schema::Argument do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def field(**args)
|
33
|
-
|
33
|
+
# sort the fields so that they match the output of the new interpreter
|
34
|
+
sorted_keys = args.keys.sort
|
35
|
+
sorted_args = {}
|
36
|
+
sorted_keys.each {|k| sorted_args[k] = args[k] }
|
37
|
+
sorted_args.inspect
|
34
38
|
end
|
35
39
|
|
36
40
|
def multiply(val)
|
@@ -48,7 +52,7 @@ describe GraphQL::Schema::Argument do
|
|
48
52
|
|
49
53
|
describe "#keys" do
|
50
54
|
it "is not overwritten by the 'keys' argument" do
|
51
|
-
expected_keys = ["aliasedArg", "arg", "argWithBlock", "explodingPreparedArg", "keys", "preparedArg", "preparedByCallableArg", "preparedByProcArg"]
|
55
|
+
expected_keys = ["aliasedArg", "arg", "argWithBlock", "explodingPreparedArg", "keys", "preparedArg", "preparedByCallableArg", "preparedByProcArg", "requiredWithDefaultArg"]
|
52
56
|
assert_equal expected_keys, SchemaArgumentTest::Query.fields["field"].arguments.keys.sort
|
53
57
|
end
|
54
58
|
end
|
@@ -103,7 +107,7 @@ describe GraphQL::Schema::Argument do
|
|
103
107
|
|
104
108
|
res = SchemaArgumentTest::Schema.execute(query_str)
|
105
109
|
# Make sure it's getting the renamed symbol:
|
106
|
-
assert_equal '{:renamed=>"x"}', res["data"]["field"]
|
110
|
+
assert_equal '{:renamed=>"x", :required_with_default_arg=>1}', res["data"]["field"]
|
107
111
|
end
|
108
112
|
end
|
109
113
|
|
@@ -115,7 +119,7 @@ describe GraphQL::Schema::Argument do
|
|
115
119
|
|
116
120
|
res = SchemaArgumentTest::Schema.execute(query_str, context: {multiply_by: 3})
|
117
121
|
# Make sure it's getting the renamed symbol:
|
118
|
-
assert_equal '{:prepared_arg=>15}', res["data"]["field"]
|
122
|
+
assert_equal '{:prepared_arg=>15, :required_with_default_arg=>1}', res["data"]["field"]
|
119
123
|
end
|
120
124
|
|
121
125
|
it "calls the method on the provided Proc" do
|
@@ -125,7 +129,7 @@ describe GraphQL::Schema::Argument do
|
|
125
129
|
|
126
130
|
res = SchemaArgumentTest::Schema.execute(query_str, context: {multiply_by: 3})
|
127
131
|
# Make sure it's getting the renamed symbol:
|
128
|
-
assert_equal '{:prepared_by_proc_arg=>15}', res["data"]["field"]
|
132
|
+
assert_equal '{:prepared_by_proc_arg=>15, :required_with_default_arg=>1}', res["data"]["field"]
|
129
133
|
end
|
130
134
|
|
131
135
|
it "calls the method on the provided callable object" do
|
@@ -135,7 +139,7 @@ describe GraphQL::Schema::Argument do
|
|
135
139
|
|
136
140
|
res = SchemaArgumentTest::Schema.execute(query_str, context: {multiply_by: 3})
|
137
141
|
# Make sure it's getting the renamed symbol:
|
138
|
-
assert_equal '{:prepared_by_callable_arg=>15}', res["data"]["field"]
|
142
|
+
assert_equal '{:prepared_by_callable_arg=>15, :required_with_default_arg=>1}', res["data"]["field"]
|
139
143
|
end
|
140
144
|
|
141
145
|
it "handles exceptions raised by prepare" do
|
@@ -144,9 +148,39 @@ describe GraphQL::Schema::Argument do
|
|
144
148
|
GRAPHQL
|
145
149
|
|
146
150
|
res = SchemaArgumentTest::Schema.execute(query_str, context: {multiply_by: 3})
|
147
|
-
assert_equal({ 'f1' => '{:arg=>"echo"}', 'f2' => nil }, res['data'])
|
151
|
+
assert_equal({ 'f1' => '{:arg=>"echo", :required_with_default_arg=>1}', 'f2' => nil }, res['data'])
|
148
152
|
assert_equal(res['errors'][0]['message'], 'boom!')
|
149
153
|
assert_equal(res['errors'][0]['path'], ['f2'])
|
150
154
|
end
|
151
155
|
end
|
156
|
+
|
157
|
+
describe "default_value:" do
|
158
|
+
it 'uses default_value: with no input' do
|
159
|
+
query_str = <<-GRAPHQL
|
160
|
+
{ field() }
|
161
|
+
GRAPHQL
|
162
|
+
|
163
|
+
res = SchemaArgumentTest::Schema.execute(query_str)
|
164
|
+
assert_equal '{:required_with_default_arg=>1}', res["data"]["field"]
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'uses provided input value' do
|
168
|
+
query_str = <<-GRAPHQL
|
169
|
+
{ field(requiredWithDefaultArg: 2) }
|
170
|
+
GRAPHQL
|
171
|
+
|
172
|
+
res = SchemaArgumentTest::Schema.execute(query_str)
|
173
|
+
assert_equal '{:required_with_default_arg=>2}', res["data"]["field"]
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'respects non-null type' do
|
177
|
+
query_str = <<-GRAPHQL
|
178
|
+
{ field(requiredWithDefaultArg: null) }
|
179
|
+
GRAPHQL
|
180
|
+
|
181
|
+
res = SchemaArgumentTest::Schema.execute(query_str)
|
182
|
+
assert_equal "Argument 'requiredWithDefaultArg' on Field 'field' has an invalid value. Expected type 'Int!'.", res['errors'][0]['message']
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
152
186
|
end
|
@@ -324,6 +324,16 @@ describe GraphQL::Schema::Object do
|
|
324
324
|
end
|
325
325
|
end
|
326
326
|
|
327
|
+
it "warns when override matches field name" do
|
328
|
+
expected_warning = "X's `field :object` conflicts with a built-in method, use `resolver_method:` to pick a different resolver method for this field (for example, `resolver_method: :resolve_object` and `def resolve_object`)\n"
|
329
|
+
assert_output "", expected_warning do
|
330
|
+
Class.new(GraphQL::Schema::Object) do
|
331
|
+
graphql_name "X"
|
332
|
+
field :object, String, null: true, resolver_method: :object
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
327
337
|
it "doesn't warn with an override" do
|
328
338
|
assert_output "", "" do
|
329
339
|
Class.new(GraphQL::Schema::Object) do
|
@@ -332,5 +342,14 @@ describe GraphQL::Schema::Object do
|
|
332
342
|
end
|
333
343
|
end
|
334
344
|
end
|
345
|
+
|
346
|
+
it "doesn't warn when passing object through using resolver_method" do
|
347
|
+
assert_output "", "" do
|
348
|
+
Class.new(GraphQL::Schema::Object) do
|
349
|
+
graphql_name "X"
|
350
|
+
field :thing, String, null: true, resolver_method: :object
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
335
354
|
end
|
336
355
|
end
|
@@ -866,4 +866,18 @@ SCHEMA
|
|
866
866
|
assert_equal expected.chomp, GraphQL::Schema::Printer.new(schema, context: context, only: only_filter).print_schema
|
867
867
|
end
|
868
868
|
end
|
869
|
+
|
870
|
+
it "prints schemas from class" do
|
871
|
+
class TestPrintSchema < GraphQL::Schema
|
872
|
+
class OddlyNamedQuery < GraphQL::Schema::Object
|
873
|
+
field :int, Int, null: false
|
874
|
+
end
|
875
|
+
|
876
|
+
query(OddlyNamedQuery)
|
877
|
+
end
|
878
|
+
|
879
|
+
|
880
|
+
str = GraphQL::Schema::Printer.print_schema TestPrintSchema
|
881
|
+
assert_equal "schema {\n query: OddlyNamedQuery\n}\n\ntype OddlyNamedQuery {\n int: Int!\n}", str
|
882
|
+
end
|
869
883
|
end
|
@@ -297,9 +297,9 @@ describe GraphQL::Schema::Validation do
|
|
297
297
|
end
|
298
298
|
}
|
299
299
|
|
300
|
-
let(:
|
300
|
+
let(:default_argument_for_non_null_argument) {
|
301
301
|
GraphQL::Argument.define do
|
302
|
-
name "
|
302
|
+
name "ValidDefault"
|
303
303
|
type !GraphQL::INT_TYPE
|
304
304
|
default_value 1
|
305
305
|
end
|
@@ -324,8 +324,8 @@ describe GraphQL::Schema::Validation do
|
|
324
324
|
assert_error_includes untyped_argument, "must be a valid input type (Scalar or InputObject), not Symbol"
|
325
325
|
end
|
326
326
|
|
327
|
-
it "
|
328
|
-
|
327
|
+
it "allows default values for non-null argument" do
|
328
|
+
assert_nil GraphQL::Schema::Validation.validate(default_argument_for_non_null_argument)
|
329
329
|
end
|
330
330
|
|
331
331
|
it "cannot use reserved name" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.9.
|
4
|
+
version: 1.9.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-ips
|