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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql.rb +8 -5
  3. data/lib/graphql/definition_helpers/defined_by_config.rb +2 -1
  4. data/lib/graphql/field.rb +34 -7
  5. data/lib/graphql/input_object_type.rb +4 -3
  6. data/lib/graphql/invalid_null_error.rb +22 -0
  7. data/lib/graphql/language/nodes.rb +165 -58
  8. data/lib/graphql/language/transform.rb +5 -6
  9. data/lib/graphql/non_null_type.rb +0 -4
  10. data/lib/graphql/query.rb +1 -2
  11. data/lib/graphql/query/arguments.rb +39 -7
  12. data/lib/graphql/query/literal_input.rb +1 -1
  13. data/lib/graphql/query/serial_execution.rb +30 -1
  14. data/lib/graphql/query/serial_execution/execution_context.rb +30 -0
  15. data/lib/graphql/query/serial_execution/field_resolution.rb +27 -21
  16. data/lib/graphql/query/serial_execution/operation_resolution.rb +9 -6
  17. data/lib/graphql/query/serial_execution/selection_resolution.rb +49 -56
  18. data/lib/graphql/query/{base_execution → serial_execution}/value_resolution.rb +35 -24
  19. data/lib/graphql/static_validation/complexity_validator.rb +27 -0
  20. data/lib/graphql/static_validation/literal_validator.rb +4 -4
  21. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -0
  22. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +1 -1
  23. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  24. data/lib/graphql/static_validation/validator.rb +1 -1
  25. data/lib/graphql/version.rb +1 -1
  26. data/readme.md +8 -4
  27. data/spec/graphql/execution_error_spec.rb +7 -1
  28. data/spec/graphql/field_spec.rb +53 -0
  29. data/spec/graphql/input_object_type_spec.rb +8 -1
  30. data/spec/graphql/introspection/schema_type_spec.rb +2 -1
  31. data/spec/graphql/language/transform_spec.rb +14 -14
  32. data/spec/graphql/object_type_spec.rb +7 -0
  33. data/spec/graphql/query/arguments_spec.rb +5 -5
  34. data/spec/graphql/query/executor_spec.rb +31 -0
  35. data/spec/graphql/query/serial_execution/execution_context_spec.rb +55 -0
  36. data/spec/graphql/query/{base_execution → serial_execution}/value_resolution_spec.rb +1 -1
  37. data/spec/graphql/query/variables_spec.rb +1 -1
  38. data/spec/graphql/static_validation/complexity_validator.rb +15 -0
  39. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +2 -1
  40. data/spec/graphql/static_validation/validator_spec.rb +1 -1
  41. data/spec/support/dairy_app.rb +15 -0
  42. data/spec/support/minimum_input_object.rb +13 -0
  43. metadata +14 -6
  44. 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
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe GraphQL::Query::BaseExecution::ValueResolution do
3
+ describe GraphQL::Query::SerialExecution::ValueResolution do
4
4
  let(:debug) { false }
5
5
  let(:query_root) {
6
6
  day_of_week_enum = GraphQL::EnumType.define do
@@ -8,7 +8,7 @@ describe GraphQL::Query::Variables do
8
8
  }
9
9
  }
10
10
  |}
11
- let(:ast_variables) { GraphQL.parse(query_string).parts.first.variables }
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"=>12, "column"=>7}]
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: [], parts: []) }
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
@@ -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.10.9
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-01-15 00:00:00.000000000 Z
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