graphql 1.8.0.pre6 → 1.8.0.pre7

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 (36) hide show
  1. checksums.yaml +5 -5
  2. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +14 -0
  3. data/lib/graphql/internal_representation/node.rb +3 -20
  4. data/lib/graphql/language/parser.rb +590 -598
  5. data/lib/graphql/language/parser.y +1 -2
  6. data/lib/graphql/query/context.rb +26 -0
  7. data/lib/graphql/schema.rb +77 -22
  8. data/lib/graphql/schema/argument.rb +11 -3
  9. data/lib/graphql/schema/field.rb +50 -3
  10. data/lib/graphql/schema/input_object.rb +6 -0
  11. data/lib/graphql/schema/interface.rb +0 -1
  12. data/lib/graphql/schema/member.rb +2 -16
  13. data/lib/graphql/schema/member/has_fields.rb +4 -0
  14. data/lib/graphql/schema/object.rb +5 -4
  15. data/lib/graphql/schema/union.rb +0 -12
  16. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -1
  17. data/lib/graphql/upgrader/member.rb +97 -10
  18. data/lib/graphql/version.rb +1 -1
  19. data/spec/fixtures/upgrader/starrable.original.rb +46 -0
  20. data/spec/fixtures/upgrader/starrable.transformed.rb +43 -0
  21. data/spec/fixtures/upgrader/subscribable.transformed.rb +32 -30
  22. data/spec/fixtures/upgrader/type_x.original.rb +14 -2
  23. data/spec/fixtures/upgrader/type_x.transformed.rb +12 -0
  24. data/spec/graphql/query/executor_spec.rb +2 -1
  25. data/spec/graphql/rake_task_spec.rb +3 -1
  26. data/spec/graphql/schema/field_spec.rb +94 -1
  27. data/spec/graphql/schema/input_object_spec.rb +6 -0
  28. data/spec/graphql/schema/interface_spec.rb +15 -0
  29. data/spec/graphql/schema/object_spec.rb +5 -3
  30. data/spec/graphql/schema/printer_spec.rb +19 -0
  31. data/spec/graphql/schema_spec.rb +10 -3
  32. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +10 -2
  33. data/spec/graphql/upgrader/member_spec.rb +2 -2
  34. data/spec/support/jazz.rb +21 -14
  35. data/spec/support/star_wars/schema.rb +1 -1
  36. metadata +7 -3
@@ -15,6 +15,12 @@ describe GraphQL::Schema::InputObject do
15
15
  it "assigns itself as the arguments_class" do
16
16
  assert_equal input_object, input_object.to_graphql.arguments_class
17
17
  end
18
+
19
+ it "accepts description: kwarg" do
20
+ input_obj_class = Jazz::InspectableInput
21
+ input_obj_type = input_obj_class.to_graphql
22
+ assert_equal "Test description kwarg", input_obj_type.arguments["stringValue"].description
23
+ end
18
24
  end
19
25
 
20
26
  describe "in queries" do
@@ -52,6 +52,21 @@ describe GraphQL::Schema::Interface do
52
52
  end
53
53
  end
54
54
 
55
+ it 'supports global_id_field' do
56
+ object = Class.new(GraphQL::Schema::Interface) do
57
+ graphql_name 'GlobalIdFieldTest'
58
+ global_id_field :uuid
59
+ end.to_graphql
60
+ uuid_field = object.fields["uuid"]
61
+
62
+ assert_equal GraphQL::NonNullType, uuid_field.type.class
63
+ assert_equal GraphQL::ScalarType, uuid_field.type.unwrap.class
64
+ assert_equal(
65
+ GraphQL::Schema::Member::GraphQLTypeNames::ID,
66
+ uuid_field.type.unwrap.name
67
+ )
68
+ end
69
+
55
70
  describe "in queries" do
56
71
  it "works" do
57
72
  query_str = <<-GRAPHQL
@@ -7,7 +7,7 @@ describe GraphQL::Schema::Object do
7
7
  it "tells type data" do
8
8
  assert_equal "Ensemble", object_class.graphql_name
9
9
  assert_equal "A group of musicians playing together", object_class.description
10
- assert_equal 5, object_class.fields.size
10
+ assert_equal 6, object_class.fields.size
11
11
  assert_equal 2, object_class.interfaces.size
12
12
  # Compatibility methods are delegated to the underlying BaseType
13
13
  assert object_class.respond_to?(:connection_type)
@@ -20,7 +20,7 @@ describe GraphQL::Schema::Object do
20
20
  end
21
21
 
22
22
  # one more than the parent class
23
- assert_equal 6, new_object_class.fields.size
23
+ assert_equal 7, new_object_class.fields.size
24
24
  # inherited interfaces are present
25
25
  assert_equal 2, new_object_class.interfaces.size
26
26
  # The new field is present
@@ -49,6 +49,7 @@ describe GraphQL::Schema::Object do
49
49
  hashyEnsemble {
50
50
  name
51
51
  musicians { name }
52
+ formedAt
52
53
  }
53
54
  }
54
55
  GRAPHQL
@@ -56,6 +57,7 @@ describe GraphQL::Schema::Object do
56
57
  ensemble = res["data"]["hashyEnsemble"]
57
58
  assert_equal "The Grateful Dead", ensemble["name"]
58
59
  assert_equal ["Jerry Garcia"], ensemble["musicians"].map { |m| m["name"] }
60
+ assert_equal "May 5, 1965", ensemble["formedAt"]
59
61
  end
60
62
  end
61
63
 
@@ -64,7 +66,7 @@ describe GraphQL::Schema::Object do
64
66
  it "returns a matching GraphQL::ObjectType" do
65
67
  assert_equal "Ensemble", obj_type.name
66
68
  assert_equal "A group of musicians playing together", obj_type.description
67
- assert_equal 5, obj_type.all_fields.size
69
+ assert_equal 6, obj_type.all_fields.size
68
70
 
69
71
  name_field = obj_type.all_fields[2]
70
72
  assert_equal "name", name_field.name
@@ -481,6 +481,25 @@ SCHEMA
481
481
 
482
482
  assert_equal expected.chomp, GraphQL::Schema::Printer.print_schema(schema)
483
483
  end
484
+
485
+ it 'prints a schema without directives' do
486
+ query_type = Class.new(GraphQL::Schema::Object) do
487
+ graphql_name 'Query'
488
+
489
+ field :foobar, Integer, null: false
490
+
491
+ def foobar
492
+ 152
493
+ end
494
+ end
495
+
496
+ schema = Class.new(GraphQL::Schema) do
497
+ query query_type
498
+ end
499
+
500
+ expected = "type Query {\n foobar: Int!\n}"
501
+ assert_equal expected, GraphQL::Schema::Printer.new(schema).print_schema
502
+ end
484
503
  end
485
504
 
486
505
  it "applies an `only` filter" do
@@ -7,12 +7,12 @@ describe GraphQL::Schema do
7
7
  let(:empty_schema) { GraphQL::Schema.define }
8
8
 
9
9
  describe "#rescue_from" do
10
- let(:rescue_middleware) { schema.middleware.first }
11
-
12
10
  it "adds handlers to the rescue middleware" do
11
+ schema_defn = schema.graphql_definition
12
+ rescue_middleware = schema_defn.middleware.first
13
13
  assert_equal(1, rescue_middleware.rescue_table.length)
14
14
  # normally, you'd use a real class, not a symbol:
15
- schema.rescue_from(:error_class) { "my custom message" }
15
+ schema_defn.rescue_from(:error_class) { "my custom message" }
16
16
  assert_equal(2, rescue_middleware.rescue_table.length)
17
17
  end
18
18
  end
@@ -433,6 +433,13 @@ type Query {
433
433
  end
434
434
  end
435
435
 
436
+ describe "#as_json" do
437
+ it "returns a hash" do
438
+ result = schema.execute(GraphQL::Introspection::INTROSPECTION_QUERY)
439
+ assert_equal result.as_json.class, Hash
440
+ end
441
+ end
442
+
436
443
  describe "#get_field" do
437
444
  it "returns fields by type or type name" do
438
445
  field = schema.get_field("Cheese", "id")
@@ -8,18 +8,19 @@ describe GraphQL::StaticValidation::FieldsHaveAppropriateSelections do
8
8
  okCheese: cheese(id: 1) { fatContent, similarCheese(source: YAK) { source } }
9
9
  missingFieldsCheese: cheese(id: 1)
10
10
  illegalSelectionCheese: cheese(id: 1) { id { something, ... someFields } }
11
+ incorrectFragmentSpread: cheese(id: 1) { flavor { ... on String { __typename } } }
11
12
  }
12
13
  "}
13
14
 
14
15
  it "adds errors for selections on scalars" do
15
- assert_equal(2, errors.length)
16
+ assert_equal(3, errors.length)
16
17
 
17
18
  illegal_selection_error = {
18
19
  "message"=>"Selections can't be made on scalars (field 'id' returns Int but has selections [something, someFields])",
19
20
  "locations"=>[{"line"=>5, "column"=>47}],
20
21
  "fields"=>["query getCheese", "illegalSelectionCheese", "id"],
21
22
  }
22
- assert_includes(errors, illegal_selection_error, "finds illegal selections on scalarss")
23
+ assert_includes(errors, illegal_selection_error, "finds illegal selections on scalars")
23
24
 
24
25
  selection_required_error = {
25
26
  "message"=>"Objects must have selections (field 'cheese' returns Cheese but has no selections)",
@@ -27,6 +28,13 @@ describe GraphQL::StaticValidation::FieldsHaveAppropriateSelections do
27
28
  "fields"=>["query getCheese", "missingFieldsCheese"],
28
29
  }
29
30
  assert_includes(errors, selection_required_error, "finds objects without selections")
31
+
32
+ incorrect_fragment_error = {
33
+ "message"=>"Selections can't be made on scalars (field 'flavor' returns String but has inline fragments [String])",
34
+ "locations"=>[{"line"=>6, "column"=>48}],
35
+ "fields"=>["query getCheese", "incorrectFragmentSpread", "flavor"],
36
+ }
37
+ assert_includes(errors, incorrect_fragment_error, "finds scalar fields with selections")
30
38
  end
31
39
 
32
40
  describe "anonymous operations" do
@@ -300,12 +300,12 @@ describe GraphQL::Upgrader::Member do
300
300
  new = %{field :name, Name.connection_type, "names", null: false, connection: true}
301
301
  assert_equal new, upgrade(old)
302
302
 
303
- old = %{field :names, types[types.String]}
303
+ old = %{field :names, types[!types.String]}
304
304
  new = %{field :names, [String], null: true}
305
305
  assert_equal new, upgrade(old)
306
306
 
307
307
  old = %{field :names, !types[types.String]}
308
- new = %{field :names, [String], null: false}
308
+ new = %{field :names, [String, null: true], null: false}
309
309
  assert_equal new, upgrade(old)
310
310
 
311
311
  old = %{
data/spec/support/jazz.rb CHANGED
@@ -156,7 +156,7 @@ module Jazz
156
156
  field :upcase_name, String, null: false, upcase: true
157
157
 
158
158
  def upcase_name
159
- @object.name # upcase is applied by the superclass
159
+ object.name # upcase is applied by the superclass
160
160
  end
161
161
  end
162
162
 
@@ -168,6 +168,7 @@ module Jazz
168
168
  # Test string type names:
169
169
  field :name, "String", null: false
170
170
  field :musicians, "[Jazz::Musician]", null: false
171
+ field :formed_at, String, null: true, hash_key: "formedAtDate"
171
172
  end
172
173
 
173
174
  class Family < BaseEnum
@@ -221,7 +222,7 @@ module Jazz
221
222
  field :favorite_key, Key, null: true
222
223
  # Test lists with nullable members:
223
224
  field :inspect_context, [String, null: true], null: false
224
-
225
+ field :add_error, String, null: false, extras: [:execution_errors]
225
226
  def inspect_context
226
227
  [
227
228
  @context.custom_method,
@@ -230,6 +231,11 @@ module Jazz
230
231
  nil,
231
232
  ]
232
233
  end
234
+
235
+ def add_error(execution_errors:)
236
+ execution_errors.add("this has a path")
237
+ "done"
238
+ end
233
239
  end
234
240
 
235
241
  LegacyInputType = GraphQL::InputObjectType.define do
@@ -238,15 +244,15 @@ module Jazz
238
244
  end
239
245
 
240
246
  class InspectableInput < GraphQL::Schema::InputObject
241
- argument :string_value, String, required: true
247
+ argument :string_value, String, required: true, description: "Test description kwarg"
242
248
  argument :nested_input, InspectableInput, required: false
243
249
  argument :legacy_input, LegacyInputType, required: false
244
250
  def helper_method
245
251
  [
246
252
  # Context is available in the InputObject
247
- @context[:message],
253
+ context[:message],
248
254
  # A GraphQL::Query::Arguments instance is available
249
- @arguments[:stringValue],
255
+ arguments[:stringValue],
250
256
  # Legacy inputs have underscored method access too
251
257
  legacy_input ? legacy_input.int_value : "-",
252
258
  # Access by method call is available
@@ -264,8 +270,8 @@ module Jazz
264
270
  class PerformingAct < GraphQL::Schema::Union
265
271
  possible_types Musician, Ensemble
266
272
 
267
- def resolve_type
268
- if @object.is_a?(Models::Ensemble)
273
+ def self.resolve_type(object, context)
274
+ if object.is_a?(Models::Ensemble)
269
275
  Ensemble
270
276
  else
271
277
  Musician
@@ -300,7 +306,7 @@ module Jazz
300
306
 
301
307
  def find(id:)
302
308
  if id == "MagicalSkipId"
303
- @context.skip
309
+ context.skip
304
310
  else
305
311
  GloballyIdentifiableType.find(id)
306
312
  end
@@ -333,9 +339,9 @@ module Jazz
333
339
 
334
340
  def inspect_context
335
341
  [
336
- @context.custom_method,
337
- @context[:magic_key],
338
- @context[:normal_key]
342
+ context.custom_method,
343
+ context[:magic_key],
344
+ context[:normal_key]
339
345
  ]
340
346
  end
341
347
 
@@ -347,6 +353,7 @@ module Jazz
347
353
  "musicians" => [
348
354
  OpenStruct.new(name: "Jerry Garcia"),
349
355
  ],
356
+ "formedAtDate" => "May 5, 1965",
350
357
  }
351
358
  end
352
359
  end
@@ -390,7 +397,7 @@ module Jazz
390
397
  module Introspection
391
398
  class TypeType < GraphQL::Introspection::TypeType
392
399
  def name
393
- @object.name.upcase
400
+ object.name.upcase
394
401
  end
395
402
  end
396
403
 
@@ -404,7 +411,7 @@ module Jazz
404
411
  end
405
412
 
406
413
  class DynamicFields < GraphQL::Introspection::DynamicFields
407
- field :__typename_length, Integer, null: false, extras: [:irep_node]
414
+ field :__typename_length, Int, null: false, extras: [:irep_node]
408
415
  field :__ast_node_class, String, null: false, extras: [:ast_node]
409
416
  def __typename_length(irep_node:)
410
417
  __typename(irep_node: irep_node).length
@@ -418,7 +425,7 @@ module Jazz
418
425
  class EntryPoints < GraphQL::Introspection::EntryPoints
419
426
  field :__classname, String, "The Ruby class name of the root object", null: false
420
427
  def __classname
421
- @object.class.name
428
+ object.class.name
422
429
  end
423
430
  end
424
431
  end
@@ -119,7 +119,7 @@ module StarWars
119
119
  argument :nameIncludes, String, required: false
120
120
  end
121
121
 
122
- field :shipsWithMaxPageSize, max_page_size: 2, function: ShipsWithMaxPageSize.new
122
+ field :shipsWithMaxPageSize, "Ships with max page size", max_page_size: 2, function: ShipsWithMaxPageSize.new
123
123
 
124
124
  field :bases, BaseConnectionWithTotalCountType, null: true, connection: true, resolve: ->(obj, args, ctx) {
125
125
  all_bases = Base.where(id: obj.bases)
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.8.0.pre6
4
+ version: 1.8.0.pre7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-05 00:00:00.000000000 Z
11
+ date: 2018-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ips
@@ -910,6 +910,8 @@ files:
910
910
  - spec/fixtures/upgrader/gist_order_field.transformed.rb
911
911
  - spec/fixtures/upgrader/release_order.original.rb
912
912
  - spec/fixtures/upgrader/release_order.transformed.rb
913
+ - spec/fixtures/upgrader/starrable.original.rb
914
+ - spec/fixtures/upgrader/starrable.transformed.rb
913
915
  - spec/fixtures/upgrader/subscribable.original.rb
914
916
  - spec/fixtures/upgrader/subscribable.transformed.rb
915
917
  - spec/fixtures/upgrader/type_x.original.rb
@@ -1092,7 +1094,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1092
1094
  version: 1.3.1
1093
1095
  requirements: []
1094
1096
  rubyforge_project:
1095
- rubygems_version: 2.6.11
1097
+ rubygems_version: 2.7.3
1096
1098
  signing_key:
1097
1099
  specification_version: 4
1098
1100
  summary: A GraphQL language and runtime for Ruby
@@ -1409,6 +1411,8 @@ test_files:
1409
1411
  - spec/fixtures/upgrader/gist_order_field.transformed.rb
1410
1412
  - spec/fixtures/upgrader/release_order.original.rb
1411
1413
  - spec/fixtures/upgrader/release_order.transformed.rb
1414
+ - spec/fixtures/upgrader/starrable.original.rb
1415
+ - spec/fixtures/upgrader/starrable.transformed.rb
1412
1416
  - spec/fixtures/upgrader/subscribable.original.rb
1413
1417
  - spec/fixtures/upgrader/subscribable.transformed.rb
1414
1418
  - spec/fixtures/upgrader/type_x.original.rb