graphql 0.10.9 → 0.11.0
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.rb +8 -5
- data/lib/graphql/definition_helpers/defined_by_config.rb +2 -1
- data/lib/graphql/field.rb +34 -7
- data/lib/graphql/input_object_type.rb +4 -3
- data/lib/graphql/invalid_null_error.rb +22 -0
- data/lib/graphql/language/nodes.rb +165 -58
- data/lib/graphql/language/transform.rb +5 -6
- data/lib/graphql/non_null_type.rb +0 -4
- data/lib/graphql/query.rb +1 -2
- data/lib/graphql/query/arguments.rb +39 -7
- data/lib/graphql/query/literal_input.rb +1 -1
- data/lib/graphql/query/serial_execution.rb +30 -1
- data/lib/graphql/query/serial_execution/execution_context.rb +30 -0
- data/lib/graphql/query/serial_execution/field_resolution.rb +27 -21
- data/lib/graphql/query/serial_execution/operation_resolution.rb +9 -6
- data/lib/graphql/query/serial_execution/selection_resolution.rb +49 -56
- data/lib/graphql/query/{base_execution → serial_execution}/value_resolution.rb +35 -24
- data/lib/graphql/static_validation/complexity_validator.rb +27 -0
- data/lib/graphql/static_validation/literal_validator.rb +4 -4
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -0
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -1
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
- data/lib/graphql/static_validation/validator.rb +1 -1
- data/lib/graphql/version.rb +1 -1
- data/readme.md +8 -4
- data/spec/graphql/execution_error_spec.rb +7 -1
- data/spec/graphql/field_spec.rb +53 -0
- data/spec/graphql/input_object_type_spec.rb +8 -1
- data/spec/graphql/introspection/schema_type_spec.rb +2 -1
- data/spec/graphql/language/transform_spec.rb +14 -14
- data/spec/graphql/object_type_spec.rb +7 -0
- data/spec/graphql/query/arguments_spec.rb +5 -5
- data/spec/graphql/query/executor_spec.rb +31 -0
- data/spec/graphql/query/serial_execution/execution_context_spec.rb +55 -0
- data/spec/graphql/query/{base_execution → serial_execution}/value_resolution_spec.rb +1 -1
- data/spec/graphql/query/variables_spec.rb +1 -1
- data/spec/graphql/static_validation/complexity_validator.rb +15 -0
- data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +2 -1
- data/spec/graphql/static_validation/validator_spec.rb +1 -1
- data/spec/support/dairy_app.rb +15 -0
- data/spec/support/minimum_input_object.rb +13 -0
- metadata +14 -6
- data/lib/graphql/query/base_execution.rb +0 -32
@@ -132,6 +132,37 @@ describe GraphQL::Query::Executor do
|
|
132
132
|
end
|
133
133
|
end
|
134
134
|
|
135
|
+
describe 'if nil is given for a non-null field' do
|
136
|
+
let(:query_string) {%| query noMilk { cow { name cantBeNullButIs } }|}
|
137
|
+
it 'turns into error message and nulls the entire selection' do
|
138
|
+
expected = {
|
139
|
+
"data" => { "cow" => nil },
|
140
|
+
"errors" => [
|
141
|
+
{
|
142
|
+
"message" => "Cannot return null for non-nullable field cantBeNullButIs"
|
143
|
+
}
|
144
|
+
]
|
145
|
+
}
|
146
|
+
assert_equal(expected, result)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe 'if an execution error is raised for a non-null field' do
|
151
|
+
let(:query_string) {%| query noMilk { cow { name cantBeNullButRaisesExecutionError } }|}
|
152
|
+
it 'uses provided error message and nulls the entire selection' do
|
153
|
+
expected = {
|
154
|
+
"data" => { "cow" => nil },
|
155
|
+
"errors" => [
|
156
|
+
{
|
157
|
+
"message" => "BOOM",
|
158
|
+
"locations" => [ { "line" => 1, "column" => 28 } ]
|
159
|
+
}
|
160
|
+
]
|
161
|
+
}
|
162
|
+
assert_equal(expected, result)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
135
166
|
describe "if the schema has a rescue handler" do
|
136
167
|
before do
|
137
168
|
schema.rescue_from(RuntimeError) { "Error was handled!" }
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GraphQL::Query::SerialExecution::ExecutionContext do
|
4
|
+
let(:query_string) { %|
|
5
|
+
query getFlavor($cheeseId: Int!) {
|
6
|
+
brie: cheese(id: 1) { ...cheeseFields, taste: flavor }
|
7
|
+
}
|
8
|
+
fragment cheeseFields on Cheese { flavor }
|
9
|
+
|}
|
10
|
+
let(:debug) { false }
|
11
|
+
let(:operation_name) { nil }
|
12
|
+
let(:query_variables) { {"cheeseId" => 2} }
|
13
|
+
let(:schema) { DummySchema }
|
14
|
+
let(:query) { GraphQL::Query.new(
|
15
|
+
schema,
|
16
|
+
query_string,
|
17
|
+
variables: query_variables,
|
18
|
+
debug: debug,
|
19
|
+
operation_name: operation_name,
|
20
|
+
)}
|
21
|
+
let(:execution_context) {
|
22
|
+
GraphQL::Query::SerialExecution::ExecutionContext.new(query, nil)
|
23
|
+
}
|
24
|
+
|
25
|
+
describe "add_error" do
|
26
|
+
let(:err) { StandardError.new("test") }
|
27
|
+
let(:expected) { [err] }
|
28
|
+
|
29
|
+
it "adds an error on the query context" do
|
30
|
+
execution_context.add_error(err)
|
31
|
+
assert_equal(expected, query.context.errors)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "get_type" do
|
36
|
+
it "returns the respective type from the schema" do
|
37
|
+
type = execution_context.get_type('Dairy')
|
38
|
+
assert_equal(DairyType, type)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "get_field" do
|
43
|
+
it "returns the respective field from the schema" do
|
44
|
+
field = execution_context.get_field(DairyType, 'cheese')
|
45
|
+
assert_equal('cheese', field.name)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "get_fragment" do
|
50
|
+
it "returns a fragment on the query by name" do
|
51
|
+
fragment = execution_context.get_fragment('cheeseFields')
|
52
|
+
assert_equal('cheeseFields', fragment.name)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -8,7 +8,7 @@ describe GraphQL::Query::Variables do
|
|
8
8
|
}
|
9
9
|
}
|
10
10
|
|}
|
11
|
-
let(:ast_variables) { GraphQL.parse(query_string).
|
11
|
+
let(:ast_variables) { GraphQL.parse(query_string).definitions.first.variables }
|
12
12
|
let(:variables) { GraphQL::Query::Variables.new(
|
13
13
|
DummySchema,
|
14
14
|
ast_variables,
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe GraphQL::StaticValidation::ComplexityValidator do
|
4
|
+
let(:document) { GraphQL.parse(query_string)}
|
5
|
+
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: DummySchema, rules: [complexity_validator]) }
|
6
|
+
let(:errors) { validator.validate(document) }
|
7
|
+
let(:complexity_validator) { GraphQL::StaticValidation::ComplexityValidator.new(max_fields: 6, list_multiplier: 2) }
|
8
|
+
|
9
|
+
describe "too many fields" do
|
10
|
+
it "adds errors if there are too many fields"
|
11
|
+
it "counts fields for each time they're included from fragments"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "multiplies fields inside list types"
|
15
|
+
end
|
@@ -9,6 +9,7 @@ describe GraphQL::StaticValidation::ArgumentLiteralsAreCompatible do
|
|
9
9
|
badSource: searchDairy(product: [{source: 1.1}]) { source }
|
10
10
|
missingSource: searchDairy(product: [{fatContent: 1.1}]) { source }
|
11
11
|
listCoerce: cheese(id: 1) { similarCheese(source: YAK) }
|
12
|
+
missingInputField: searchDairy(product: [{source: YAK, wacky: 1}])
|
12
13
|
}
|
13
14
|
|
14
15
|
fragment cheeseFields on Cheese {
|
@@ -54,7 +55,7 @@ describe GraphQL::StaticValidation::ArgumentLiteralsAreCompatible do
|
|
54
55
|
|
55
56
|
fragment_error = {
|
56
57
|
"message"=>"Argument 'source' on Field 'similarCheese' has an invalid value",
|
57
|
-
"locations"=>[{"line"=>
|
58
|
+
"locations"=>[{"line"=>13, "column"=>7}]
|
58
59
|
}
|
59
60
|
assert_includes(errors, fragment_error)
|
60
61
|
end
|
@@ -14,7 +14,7 @@ class DocumentErrorValidator
|
|
14
14
|
end
|
15
15
|
|
16
16
|
describe GraphQL::StaticValidation::Validator do
|
17
|
-
let(:document) { OpenStruct.new(name: "This is not a document", children: [],
|
17
|
+
let(:document) { OpenStruct.new(name: "This is not a document", children: [], definitions: []) }
|
18
18
|
let(:validator) { GraphQL::StaticValidation::Validator.new(schema: "This is not a schema", rules: [SchemaErrorValidator, DocumentErrorValidator]) }
|
19
19
|
let(:errors) { validator.validate(document) }
|
20
20
|
it 'uses rules' do
|
data/spec/support/dairy_app.rb
CHANGED
@@ -100,6 +100,16 @@ CowType = GraphQL::ObjectType.define do
|
|
100
100
|
field :id, !types.ID
|
101
101
|
field :name, types.String
|
102
102
|
field :last_produced_dairy, DairyProductUnion
|
103
|
+
|
104
|
+
field :cantBeNullButIs do
|
105
|
+
type !GraphQL::STRING_TYPE
|
106
|
+
resolve -> (t, a, c) { nil }
|
107
|
+
end
|
108
|
+
|
109
|
+
field :cantBeNullButRaisesExecutionError do
|
110
|
+
type !GraphQL::STRING_TYPE
|
111
|
+
resolve -> (t, a, c) { raise GraphQL::ExecutionError, "BOOM" }
|
112
|
+
end
|
103
113
|
end
|
104
114
|
|
105
115
|
DairyProductInputType = GraphQL::InputObjectType.define {
|
@@ -189,6 +199,11 @@ QueryType = GraphQL::ObjectType.define do
|
|
189
199
|
resolve -> (t, a, c) { raise("This error was raised on purpose") }
|
190
200
|
end
|
191
201
|
|
202
|
+
field :executionError do
|
203
|
+
type GraphQL::STRING_TYPE
|
204
|
+
resolve -> (t, a, c) { raise(GraphQL::ExecutionError, "There was an execution error") }
|
205
|
+
end
|
206
|
+
|
192
207
|
# To test possibly-null fields
|
193
208
|
field :maybeNull, MaybeNullType do
|
194
209
|
resolve -> (t, a, c) { OpenStruct.new(cheese: nil) }
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# This is the minimum required interface for an input object
|
2
|
+
class MinimumInputObject
|
3
|
+
KEY_VALUE_PAIRS = [["source", "COW"], ["fatContent", 0.4]]
|
4
|
+
|
5
|
+
def all?
|
6
|
+
KEY_VALUE_PAIRS.all? { |pair| yield(pair) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](key)
|
10
|
+
pair = KEY_VALUE_PAIRS.find { |k, v| k == key }
|
11
|
+
pair[1]
|
12
|
+
end
|
13
|
+
end
|
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: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parslet
|
@@ -198,6 +198,7 @@ files:
|
|
198
198
|
- lib/graphql/introspection/type_kind_enum.rb
|
199
199
|
- lib/graphql/introspection/type_type.rb
|
200
200
|
- lib/graphql/introspection/typename_field.rb
|
201
|
+
- lib/graphql/invalid_null_error.rb
|
201
202
|
- lib/graphql/language.rb
|
202
203
|
- lib/graphql/language/nodes.rb
|
203
204
|
- lib/graphql/language/parser.rb
|
@@ -208,16 +209,16 @@ files:
|
|
208
209
|
- lib/graphql/object_type.rb
|
209
210
|
- lib/graphql/query.rb
|
210
211
|
- lib/graphql/query/arguments.rb
|
211
|
-
- lib/graphql/query/base_execution.rb
|
212
|
-
- lib/graphql/query/base_execution/value_resolution.rb
|
213
212
|
- lib/graphql/query/context.rb
|
214
213
|
- lib/graphql/query/directive_chain.rb
|
215
214
|
- lib/graphql/query/executor.rb
|
216
215
|
- lib/graphql/query/literal_input.rb
|
217
216
|
- lib/graphql/query/serial_execution.rb
|
217
|
+
- lib/graphql/query/serial_execution/execution_context.rb
|
218
218
|
- lib/graphql/query/serial_execution/field_resolution.rb
|
219
219
|
- lib/graphql/query/serial_execution/operation_resolution.rb
|
220
220
|
- lib/graphql/query/serial_execution/selection_resolution.rb
|
221
|
+
- lib/graphql/query/serial_execution/value_resolution.rb
|
221
222
|
- lib/graphql/query/type_resolver.rb
|
222
223
|
- lib/graphql/query/variables.rb
|
223
224
|
- lib/graphql/repl.rb
|
@@ -236,6 +237,7 @@ files:
|
|
236
237
|
- lib/graphql/static_validation.rb
|
237
238
|
- lib/graphql/static_validation/all_rules.rb
|
238
239
|
- lib/graphql/static_validation/arguments_validator.rb
|
240
|
+
- lib/graphql/static_validation/complexity_validator.rb
|
239
241
|
- lib/graphql/static_validation/literal_validator.rb
|
240
242
|
- lib/graphql/static_validation/message.rb
|
241
243
|
- lib/graphql/static_validation/rules/argument_literals_are_compatible.rb
|
@@ -279,9 +281,10 @@ files:
|
|
279
281
|
- spec/graphql/list_type_spec.rb
|
280
282
|
- spec/graphql/object_type_spec.rb
|
281
283
|
- spec/graphql/query/arguments_spec.rb
|
282
|
-
- spec/graphql/query/base_execution/value_resolution_spec.rb
|
283
284
|
- spec/graphql/query/context_spec.rb
|
284
285
|
- spec/graphql/query/executor_spec.rb
|
286
|
+
- spec/graphql/query/serial_execution/execution_context_spec.rb
|
287
|
+
- spec/graphql/query/serial_execution/value_resolution_spec.rb
|
285
288
|
- spec/graphql/query/type_resolver_spec.rb
|
286
289
|
- spec/graphql/query/variables_spec.rb
|
287
290
|
- spec/graphql/query_spec.rb
|
@@ -294,6 +297,7 @@ files:
|
|
294
297
|
- spec/graphql/schema/type_reducer_spec.rb
|
295
298
|
- spec/graphql/schema/type_validator_spec.rb
|
296
299
|
- spec/graphql/schema_spec.rb
|
300
|
+
- spec/graphql/static_validation/complexity_validator.rb
|
297
301
|
- spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb
|
298
302
|
- spec/graphql/static_validation/rules/arguments_are_defined_spec.rb
|
299
303
|
- spec/graphql/static_validation/rules/directives_are_defined_spec.rb
|
@@ -317,6 +321,7 @@ files:
|
|
317
321
|
- spec/support/calculator_schema.rb
|
318
322
|
- spec/support/dairy_app.rb
|
319
323
|
- spec/support/dairy_data.rb
|
324
|
+
- spec/support/minimum_input_object.rb
|
320
325
|
- spec/support/star_wars_data.rb
|
321
326
|
- spec/support/star_wars_schema.rb
|
322
327
|
homepage: http://github.com/rmosolgo/graphql-ruby
|
@@ -362,9 +367,10 @@ test_files:
|
|
362
367
|
- spec/graphql/list_type_spec.rb
|
363
368
|
- spec/graphql/object_type_spec.rb
|
364
369
|
- spec/graphql/query/arguments_spec.rb
|
365
|
-
- spec/graphql/query/base_execution/value_resolution_spec.rb
|
366
370
|
- spec/graphql/query/context_spec.rb
|
367
371
|
- spec/graphql/query/executor_spec.rb
|
372
|
+
- spec/graphql/query/serial_execution/execution_context_spec.rb
|
373
|
+
- spec/graphql/query/serial_execution/value_resolution_spec.rb
|
368
374
|
- spec/graphql/query/type_resolver_spec.rb
|
369
375
|
- spec/graphql/query/variables_spec.rb
|
370
376
|
- spec/graphql/query_spec.rb
|
@@ -377,6 +383,7 @@ test_files:
|
|
377
383
|
- spec/graphql/schema/type_reducer_spec.rb
|
378
384
|
- spec/graphql/schema/type_validator_spec.rb
|
379
385
|
- spec/graphql/schema_spec.rb
|
386
|
+
- spec/graphql/static_validation/complexity_validator.rb
|
380
387
|
- spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb
|
381
388
|
- spec/graphql/static_validation/rules/arguments_are_defined_spec.rb
|
382
389
|
- spec/graphql/static_validation/rules/directives_are_defined_spec.rb
|
@@ -400,5 +407,6 @@ test_files:
|
|
400
407
|
- spec/support/calculator_schema.rb
|
401
408
|
- spec/support/dairy_app.rb
|
402
409
|
- spec/support/dairy_data.rb
|
410
|
+
- spec/support/minimum_input_object.rb
|
403
411
|
- spec/support/star_wars_data.rb
|
404
412
|
- spec/support/star_wars_schema.rb
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'graphql/query/base_execution/value_resolution'
|
2
|
-
|
3
|
-
module GraphQL
|
4
|
-
class Query
|
5
|
-
class BaseExecution
|
6
|
-
# This is the only required method for an Execution strategy.
|
7
|
-
# You could create a custom execution strategy and configure your schema to
|
8
|
-
# use that custom strategy instead.
|
9
|
-
#
|
10
|
-
# @param ast_operation [GraphQL::Language::Nodes::OperationDefinition] The operation definition to run
|
11
|
-
# @param root_type [GraphQL::ObjectType] either the query type or the mutation type
|
12
|
-
# @param query_obj [GraphQL::Query] the query object for this execution
|
13
|
-
# @return [Hash] a spec-compliant GraphQL result, as a hash
|
14
|
-
def execute(ast_operation, root_type, query_obj)
|
15
|
-
resolver = operation_resolution.new(ast_operation, root_type, query_obj, self)
|
16
|
-
resolver.result
|
17
|
-
end
|
18
|
-
|
19
|
-
def field_resolution
|
20
|
-
self.class::FieldResolution
|
21
|
-
end
|
22
|
-
|
23
|
-
def operation_resolution
|
24
|
-
self.class::OperationResolution
|
25
|
-
end
|
26
|
-
|
27
|
-
def selection_resolution
|
28
|
-
self.class::SelectionResolution
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|