graphql 1.8.0.pre10 → 1.8.0.pre11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +5 -5
  2. data/lib/generators/graphql/install_generator.rb +14 -8
  3. data/lib/graphql.rb +1 -24
  4. data/lib/graphql/backtrace.rb +1 -1
  5. data/lib/graphql/deprecated_dsl.rb +2 -2
  6. data/lib/graphql/execution/execute.rb +6 -0
  7. data/lib/graphql/execution/lazy/lazy_method_map.rb +1 -1
  8. data/lib/graphql/introspection/base_object.rb +1 -0
  9. data/lib/graphql/language/document_from_schema_definition.rb +4 -1
  10. data/lib/graphql/language/nodes.rb +5 -2
  11. data/lib/graphql/language/parser.rb +288 -288
  12. data/lib/graphql/language/parser.y +1 -1
  13. data/lib/graphql/language/printer.rb +12 -2
  14. data/lib/graphql/non_null_type.rb +1 -1
  15. data/lib/graphql/query.rb +1 -1
  16. data/lib/graphql/query/arguments.rb +1 -1
  17. data/lib/graphql/query/context.rb +2 -2
  18. data/lib/graphql/query/null_context.rb +1 -1
  19. data/lib/graphql/query/result.rb +1 -1
  20. data/lib/graphql/query/variables.rb +21 -3
  21. data/lib/graphql/relay.rb +1 -0
  22. data/lib/graphql/relay/mongo_relation_connection.rb +40 -0
  23. data/lib/graphql/scalar_type.rb +14 -2
  24. data/lib/graphql/schema.rb +17 -1
  25. data/lib/graphql/schema/argument.rb +39 -7
  26. data/lib/graphql/schema/enum.rb +7 -0
  27. data/lib/graphql/schema/field.rb +145 -39
  28. data/lib/graphql/schema/finder.rb +4 -4
  29. data/lib/graphql/schema/input_object.rb +13 -2
  30. data/lib/graphql/schema/interface.rb +50 -16
  31. data/lib/graphql/schema/list.rb +28 -0
  32. data/lib/graphql/schema/member.rb +8 -106
  33. data/lib/graphql/schema/member/accepts_definition.rb +58 -24
  34. data/lib/graphql/schema/member/base_dsl_methods.rb +96 -0
  35. data/lib/graphql/schema/member/build_type.rb +15 -9
  36. data/lib/graphql/schema/member/cached_graphql_definition.rb +26 -0
  37. data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
  38. data/lib/graphql/schema/member/has_arguments.rb +1 -1
  39. data/lib/graphql/schema/member/has_fields.rb +91 -8
  40. data/lib/graphql/schema/member/type_system_helpers.rb +34 -0
  41. data/lib/graphql/schema/middleware_chain.rb +5 -1
  42. data/lib/graphql/schema/mutation.rb +24 -12
  43. data/lib/graphql/schema/non_null.rb +34 -0
  44. data/lib/graphql/schema/object.rb +24 -11
  45. data/lib/graphql/schema/relay_classic_mutation.rb +14 -11
  46. data/lib/graphql/schema/rescue_middleware.rb +8 -7
  47. data/lib/graphql/schema/scalar.rb +9 -2
  48. data/lib/graphql/schema/union.rb +4 -0
  49. data/lib/graphql/static_validation/definition_dependencies.rb +1 -1
  50. data/lib/graphql/static_validation/literal_validator.rb +16 -4
  51. data/lib/graphql/static_validation/validation_context.rb +1 -1
  52. data/lib/graphql/subscriptions.rb +90 -16
  53. data/lib/graphql/upgrader/member.rb +27 -89
  54. data/lib/graphql/version.rb +1 -1
  55. data/spec/dummy/app/channels/graphql_channel.rb +1 -1
  56. data/spec/dummy/log/test.log +206 -0
  57. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-x/-xYZjAnuuzgR79fcznLTQtSdh6AARxu8FcQ_J6p7L3U.cache +0 -0
  58. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/13/13HiV12xyoQvT-1L39ZzLwMZxjyaGMiENmfw7f-QTIc.cache +0 -0
  59. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3W/3Wtf5pCWdqq0AB-iB0Y9uUNrTkruRxIEf1XFn_BETU0.cache +1 -0
  60. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/5i/5iguGafb4hOn8262Kn8Q37ogNN9MxxQKGKNzHAzUcvI.cache +1 -0
  61. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8m/8mj2T6yy847Mc2Z7k3Xzh8O91hhVJt3NrPe8ASNDlIA.cache +1 -0
  62. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/DT/DTQyMpr4ABZYQetsdRJ5A7S4jf1r3ie4FGOR7GZBNSs.cache +3 -0
  63. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Dq/DqJ5_yJPrP5iLlOQyTQsjAVI5FE5LCVDkED0f7GgsSo.cache +3 -0
  64. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -0
  65. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -0
  66. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Rw/RwDuCV-XpnCtjNkvhpJfBuxXMk0b5AD3L9eR6M-wcy0.cache +3 -0
  67. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/UL/ULdjhhb0bRuqmaG7XSZlFYzGYCXTDnqZuJBTWRlzqgw.cache +0 -0
  68. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Up/UpPNgh0yYoUsyMDh5zWqe_U6qJIyTC6-dxMMAs1vvlM.cache +1 -0
  69. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Wg/Wguh-szFGTI1gaL6npYwPekMXflugRei7F_mOyRucXg.cache +0 -0
  70. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/X-/X-khLYMA9mqFRPg3zAi86mREDxpKl4bdKYp3uF6WHos.cache +0 -0
  71. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/bi/BIkdhfxsezxM4q-HZ4oCNTq97WEJTigcq0tpX2cDvbY.cache +0 -0
  72. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ff/FfxmA4CMHQZT7exx0G7NS1Wpcnny0vzp-Jhc2H36bp8.cache +1 -0
  73. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gE/gEiiG4GZNy_djEjK2pHm_NgA-gyhLZhdQvo0Yt96GqE.cache +0 -0
  74. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gn/gnA9ZSqpjccNL2m8pe_jBvY6SinXlCzXDWyop83Od8s.cache +1 -0
  75. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/lO/lOAan3cMwCE_Hli6gsDML88xFNfn0nxPmvrSkW7eEOw.cache +1 -0
  76. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m1/M1pv8MJEPLXGLvS8QxVh3DSO9cI4mRt5FHFWdrvUj6o.cache +2 -0
  77. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m7/m77qH7ZqH0_0SmwJbiKGDd-aLau1Dav847DC6ge46zY.cache +1 -0
  78. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sj/sjRjnjRB37lH2vrgtkdJ8Cz84__IJ978IuKTM7HcztI.cache +0 -0
  79. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/um/um1JrirR4hJhK-1rE-HywlyCi5ibgxHVrReiujZBWJM.cache +1 -0
  80. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v4/v4fwVytD7ITcE0_GDbslZEYud8a5Okm85fV1o7SDl6g.cache +0 -0
  81. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v_/v_0PAQt0iipQjFP5zjgkkk9Stnpf4VzvnMv67d1Keuw.cache +1 -0
  82. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wd/wdT9U4MKxe1PyqNjVuCKMpCl3dxGCIRJIlwUTfh2DQU.cache +1 -0
  83. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xI/xIaxut_fEIhKBDqljTNwYaADK9kj3gG0ESrfHs-5_og.cache +3 -0
  84. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/y0/y0SJOqIx2fn1SKqOkAihsQow0trRJrSIyAswufVuoA8.cache +0 -0
  85. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zg/zgpzeaX-KZErHyGJ1aBH3ZusweNXMneVZule88XsIJI.cache +1 -0
  86. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zy/zYFltDy-8VC-uKq2BVEiJJyYXNFvVzAKuMlR3ZIYZsk.cache +0 -0
  87. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  88. data/spec/fixtures/upgrader/photo.original.rb +10 -0
  89. data/spec/fixtures/upgrader/photo.transformed.rb +12 -0
  90. data/spec/fixtures/upgrader/starrable.original.rb +4 -1
  91. data/spec/fixtures/upgrader/starrable.transformed.rb +25 -22
  92. data/spec/fixtures/upgrader/subscribable.transformed.rb +32 -33
  93. data/spec/graphql/execution_error_spec.rb +18 -0
  94. data/spec/graphql/introspection/schema_type_spec.rb +1 -0
  95. data/spec/graphql/object_type_spec.rb +2 -1
  96. data/spec/graphql/query/variables_spec.rb +41 -0
  97. data/spec/graphql/relay/mongo_relation_connection_spec.rb +474 -0
  98. data/spec/graphql/schema/argument_spec.rb +65 -9
  99. data/spec/graphql/schema/build_from_definition_spec.rb +4 -2
  100. data/spec/graphql/schema/enum_spec.rb +1 -1
  101. data/spec/graphql/schema/field_spec.rb +79 -4
  102. data/spec/graphql/schema/input_object_spec.rb +56 -0
  103. data/spec/graphql/schema/instrumentation_spec.rb +4 -3
  104. data/spec/graphql/schema/interface_spec.rb +40 -25
  105. data/spec/graphql/schema/member/accepts_definition_spec.rb +38 -11
  106. data/spec/graphql/schema/member/has_fields_spec.rb +129 -0
  107. data/spec/graphql/schema/member/type_system_helpers_spec.rb +63 -0
  108. data/spec/graphql/schema/mutation_spec.rb +48 -0
  109. data/spec/graphql/schema/object_spec.rb +34 -8
  110. data/spec/graphql/schema/relay_classic_mutation_spec.rb +10 -0
  111. data/spec/graphql/schema/rescue_middleware_spec.rb +11 -0
  112. data/spec/graphql/schema/scalar_spec.rb +55 -0
  113. data/spec/graphql/subscriptions_spec.rb +31 -4
  114. data/spec/graphql/upgrader/member_spec.rb +14 -6
  115. data/spec/spec_helper.rb +7 -0
  116. data/spec/support/dummy/schema.rb +8 -0
  117. data/spec/support/jazz.rb +89 -19
  118. data/spec/support/star_trek/data.rb +109 -0
  119. data/spec/support/star_trek/schema.rb +388 -0
  120. metadata +80 -7
  121. data/lib/graphql/schema/field/dynamic_resolve.rb +0 -70
  122. data/lib/graphql/schema/field/unwrapped_resolve.rb +0 -20
  123. data/lib/graphql/schema/member/list_type_proxy.rb +0 -25
  124. data/lib/graphql/schema/member/non_null_type_proxy.rb +0 -25
@@ -6,6 +6,29 @@ describe GraphQL::Schema::Member::AcceptsDefinition do
6
6
  accepts_definition :set_metadata
7
7
  set_metadata :a, 999
8
8
 
9
+ class BaseField < GraphQL::Schema::Field
10
+ class BaseField < GraphQL::Schema::Argument
11
+ accepts_definition :metadata
12
+ end
13
+ argument_class BaseField
14
+ accepts_definition :metadata
15
+ end
16
+
17
+ GraphQL::Schema::Object.accepts_definition(:metadata2)
18
+
19
+ class BaseObject < GraphQL::Schema::Object
20
+ field_class BaseField
21
+ accepts_definition :metadata
22
+ end
23
+
24
+ GraphQL::Schema::Interface.accepts_definition(:metadata2)
25
+
26
+ module BaseInterface
27
+ include GraphQL::Schema::Interface
28
+ field_class BaseField
29
+ accepts_definition :metadata
30
+ end
31
+
9
32
  class Option < GraphQL::Schema::Enum
10
33
  class EnumValue < GraphQL::Schema::EnumValue
11
34
  accepts_definition :metadata
@@ -17,33 +40,37 @@ describe GraphQL::Schema::Member::AcceptsDefinition do
17
40
  value "B"
18
41
  end
19
42
 
20
- class Query < GraphQL::Schema::Object
21
- class Field < GraphQL::Schema::Field
22
- class Argument < GraphQL::Schema::Argument
23
- accepts_definition :metadata
24
- end
25
- argument_class Argument
26
- accepts_definition :metadata
27
- end
28
- field_class Field
29
- accepts_definition :metadata
43
+ module Thing
44
+ include BaseInterface
45
+ metadata :z, 888
46
+ metadata2 :a, :bc
47
+ end
48
+
49
+ class Query < BaseObject
30
50
  metadata :a, :abc
51
+ metadata2 :xyz, :zyx
31
52
 
32
53
  field :option, Option, null: false do
33
54
  metadata :a, :def
34
55
  argument :value, Integer, required: true, metadata: [:a, :ghi]
35
56
  end
57
+
58
+ field :thing, Thing, null: false
36
59
  end
37
60
 
38
61
  query(Query)
39
62
  end
40
63
 
41
-
42
64
  it "passes along configs for types" do
43
65
  assert_equal [:a, 123], AcceptsDefinitionSchema::Option.metadata
44
66
  assert_equal 123, AcceptsDefinitionSchema::Option.graphql_definition.metadata[:a]
45
67
  assert_equal [:a, :abc], AcceptsDefinitionSchema::Query.metadata
46
68
  assert_equal :abc, AcceptsDefinitionSchema::Query.graphql_definition.metadata[:a]
69
+ assert_equal :zyx, AcceptsDefinitionSchema::Query.graphql_definition.metadata[:xyz]
70
+
71
+ assert_equal [:z, 888], AcceptsDefinitionSchema::Thing.metadata
72
+ assert_equal 888, AcceptsDefinitionSchema::Thing.graphql_definition.metadata[:z]
73
+ assert_equal :bc, AcceptsDefinitionSchema::Thing.graphql_definition.metadata[:a]
47
74
  end
48
75
 
49
76
  it "passes along configs for fields and arguments" do
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
3
+
4
+ describe GraphQL::Schema::Member::HasFields do
5
+ module SuperTest
6
+ class BaseObject < GraphQL::Schema::Object
7
+ end
8
+
9
+ module BaseInterface
10
+ include GraphQL::Schema::Interface
11
+ end
12
+
13
+ module InterfaceWithFloatField
14
+ include BaseInterface
15
+ field :float, Float, null: false
16
+ def float
17
+ # This should call the default implementation
18
+ super * 0.5
19
+ end
20
+ end
21
+
22
+ module SubInterfaceWithFloatField
23
+ include InterfaceWithFloatField
24
+ def float
25
+ # This should call `InterfaceWithFloatField#float`
26
+ super * 0.1
27
+ end
28
+ end
29
+
30
+ class ObjectWithFloatField < BaseObject
31
+ implements InterfaceWithFloatField
32
+ end
33
+
34
+ class ObjectWithSubFloatField < BaseObject
35
+ implements SubInterfaceWithFloatField
36
+ end
37
+
38
+ module InterfaceWithStringField
39
+ include BaseInterface
40
+ field :string, String, null: false
41
+ def string
42
+ # Return a literal value to ensure this method was called
43
+ "here's a string"
44
+ end
45
+ end
46
+
47
+ class ObjectWithStringField < BaseObject
48
+ implements InterfaceWithStringField
49
+ def string
50
+ # This should call to `InterfaceWithStringField#string`
51
+ super.upcase
52
+ end
53
+ end
54
+
55
+ class SubObjectWithStringField < ObjectWithStringField
56
+ def string
57
+ # This should call to `ObjectWithStringField#string`
58
+ super.reverse
59
+ end
60
+ end
61
+
62
+ class SubSubObjectWithStringField < SubObjectWithStringField
63
+ field :string, String, null: false
64
+ end
65
+
66
+ class Query < BaseObject
67
+ field :int, Integer, null: false
68
+ def int
69
+ # This should call default resolution
70
+ super * 2
71
+ end
72
+
73
+ field :string1, ObjectWithStringField, null: false, method: :object
74
+ field :string2, SubObjectWithStringField, null: false, method: :object
75
+ field :string3, SubSubObjectWithStringField, null: false, method: :object
76
+ field :float1, ObjectWithFloatField, null: false, method: :object
77
+ field :float2, ObjectWithSubFloatField, null: false, method: :object
78
+ end
79
+
80
+ class Schema < GraphQL::Schema
81
+ query(Query)
82
+ end
83
+ end
84
+
85
+ describe "Calling super in field methods" do
86
+ # Test that calling `super` in field methods "works", which means:
87
+ # - If there is a super method in the user-created hierarchy (either a class or module), it is called
88
+ # This is tested by putting random transformations in method bodies,
89
+ # then asserting that they are called.
90
+ # - If there's no user-defined super method, it calls the built-in default behavior
91
+ # This is tested by putting values in the `root_value` hash.
92
+ # The default behavior is to fetch hash values by key, so we assert that
93
+ # those values are subject to the specified transformations.
94
+
95
+ describe "Object methods" do
96
+ it "may call super to default implementation" do
97
+ res = SuperTest::Schema.execute("{ int }", root_value: { int: 4 })
98
+ assert_equal 8, res["data"]["int"]
99
+ end
100
+
101
+ it "may call super to interface method" do
102
+ res = SuperTest::Schema.execute(" { string1 { string } }", root_value: {})
103
+ assert_equal "HERE'S A STRING", res["data"]["string1"]["string"]
104
+ end
105
+
106
+ it "may call super to superclass method" do
107
+ res = SuperTest::Schema.execute(" { string2 { string } }", root_value: {})
108
+ assert_equal "GNIRTS A S'EREH", res["data"]["string2"]["string"]
109
+ end
110
+
111
+ it "can get a super method from a newly-added field" do
112
+ res = SuperTest::Schema.execute(" { string3 { string } }", root_value: {})
113
+ assert_equal "GNIRTS A S'EREH", res["data"]["string3"]["string"]
114
+ end
115
+ end
116
+
117
+ describe "Interface methods" do
118
+ it "may call super to interface method" do
119
+ res = SuperTest::Schema.execute(" { float1 { float } }", root_value: { float: 6.0 })
120
+ assert_equal 3.0, res["data"]["float1"]["float"]
121
+ end
122
+
123
+ it "may call super to superclass method" do
124
+ res = SuperTest::Schema.execute(" { float2 { float } }", root_value: { float: 6.0 })
125
+ assert_in_delta 0.001, 0.3, res["data"]["float2"]["float"]
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
3
+
4
+ describe GraphQL::Schema::Member::TypeSystemHelpers do
5
+ let(:object) {
6
+ Class.new(GraphQL::Schema::Object) do
7
+ graphql_name "Thing"
8
+
9
+ field :int, Integer, null: true
10
+ field :int2, Integer, null: false
11
+ field :int_list, [Integer], null: true
12
+ field :int_list2, [Integer], null: false
13
+ end
14
+ }
15
+
16
+ let(:int_field) { object.fields["int"] }
17
+ let(:int2_field) { object.fields["int2"] }
18
+ let(:int_list_field) { object.fields["intList"] }
19
+ let(:int_list2_field) { object.fields["intList2"] }
20
+
21
+ describe "#list?" do
22
+ it "is true for lists, including non-null lists, otherwise false" do
23
+ assert int_list_field.type.list?
24
+ assert int_list2_field.type.list?
25
+ refute int_field.type.list?
26
+ refute int2_field.type.list?
27
+ end
28
+ end
29
+
30
+ describe "#non_null?" do
31
+ it "is true for required types" do
32
+ assert int2_field.type.non_null?
33
+ assert int_list2_field.type.non_null?
34
+ refute int_field.type.non_null?
35
+ refute int_list_field.type.non_null?
36
+ end
37
+ end
38
+
39
+ describe "#kind" do
40
+ let(:pairs) {{
41
+ GraphQL::Schema::Object => "OBJECT",
42
+ GraphQL::Schema::Union => "UNION",
43
+ GraphQL::Schema::Interface => "INTERFACE",
44
+ GraphQL::Schema::Enum => "ENUM",
45
+ GraphQL::Schema::InputObject => "INPUT_OBJECT",
46
+ GraphQL::Schema::Scalar => "SCALAR",
47
+ }}
48
+ it "returns the TypeKind instance" do
49
+ pairs.each do |type_class, type_kind_name|
50
+ type = if type_class.is_a?(Class)
51
+ Class.new(type_class)
52
+ else
53
+ Module.new { include(type_class) }
54
+ end
55
+
56
+ assert_equal type_kind_name, type.kind.name
57
+ end
58
+
59
+ assert_equal "LIST", GraphQL::Schema::Object.to_list_type.kind.name
60
+ assert_equal "NON_NULL", GraphQL::Schema::Object.to_non_null_type.kind.name
61
+ end
62
+ end
63
+ end
@@ -21,6 +21,14 @@ describe GraphQL::Schema::Mutation do
21
21
  end
22
22
  end
23
23
 
24
+ describe "argument prepare" do
25
+ it "calls methods on the mutation, uses `as:`" do
26
+ query_str = 'mutation { prepareInput(input: 4) }'
27
+ res = Jazz::Schema.execute(query_str)
28
+ assert_equal 16, res["data"]["prepareInput"], "It's squared by the prepare method"
29
+ end
30
+ end
31
+
24
32
  describe ".field" do
25
33
  it "returns a GraphQL::Field instance, for backwards compat" do
26
34
  field = mutation.field
@@ -96,4 +104,44 @@ describe GraphQL::Schema::Mutation do
96
104
  assert_equal 7, response["data"]["addInstrument"]["entries"].size
97
105
  end
98
106
  end
107
+
108
+ describe ".null" do
109
+ it "overrides whether or not the field can be null" do
110
+ non_nullable_mutation_class = Class.new(GraphQL::Schema::Mutation) do
111
+ graphql_name "Thing1"
112
+ null(false)
113
+ end
114
+
115
+ nullable_mutation_class = Class.new(GraphQL::Schema::Mutation) do
116
+ graphql_name "Thing2"
117
+ null(true)
118
+ end
119
+
120
+ default_mutation_class = Class.new(GraphQL::Schema::Mutation) do
121
+ graphql_name "Thing3"
122
+ end
123
+
124
+ assert default_mutation_class.graphql_field.instance_variable_get("@return_type_null")
125
+ assert nullable_mutation_class.graphql_field.instance_variable_get("@return_type_null")
126
+ refute non_nullable_mutation_class.graphql_field.instance_variable_get("@return_type_null")
127
+ end
128
+
129
+ it "should inherit and override in subclasses" do
130
+ base_mutation = Class.new(GraphQL::Schema::Mutation) do
131
+ null(false)
132
+ end
133
+
134
+ inheriting_mutation = Class.new(base_mutation) do
135
+ graphql_name "Thing"
136
+ end
137
+
138
+ override_mutation = Class.new(base_mutation) do
139
+ graphql_name "Thing2"
140
+ null(true)
141
+ end
142
+
143
+ assert_equal false, inheriting_mutation.graphql_field.instance_variable_get("@return_type_null")
144
+ assert override_mutation.graphql_field.instance_variable_get("@return_type_null")
145
+ end
146
+ end
99
147
  end
@@ -8,7 +8,7 @@ describe GraphQL::Schema::Object do
8
8
  assert_equal "Ensemble", object_class.graphql_name
9
9
  assert_equal "A group of musicians playing together", object_class.description
10
10
  assert_equal 6, object_class.fields.size
11
- assert_equal 2, object_class.interfaces.size
11
+ assert_equal 3, object_class.interfaces.size
12
12
  # Compatibility methods are delegated to the underlying BaseType
13
13
  assert object_class.respond_to?(:connection_type)
14
14
  end
@@ -22,7 +22,7 @@ describe GraphQL::Schema::Object do
22
22
  # one more than the parent class
23
23
  assert_equal 7, new_object_class.fields.size
24
24
  # inherited interfaces are present
25
- assert_equal 2, new_object_class.interfaces.size
25
+ assert_equal 3, new_object_class.interfaces.size
26
26
  # The new field is present
27
27
  assert new_object_class.fields.key?("newField")
28
28
  # The overridden field is present:
@@ -40,6 +40,18 @@ describe GraphQL::Schema::Object do
40
40
  assert_equal "NewSubclass", new_subclass_2.graphql_name
41
41
  assert_equal object_class.description, new_subclass_2.description
42
42
  end
43
+
44
+ it "should take Ruby name (without Type suffix) as default graphql name" do
45
+ TestingClassType = Class.new(GraphQL::Schema::Object)
46
+ assert_equal "TestingClass", TestingClassType.graphql_name
47
+ end
48
+
49
+ it "raise on anonymous class without declared graphql name" do
50
+ anonymous_class = Class.new(GraphQL::Schema::Object)
51
+ assert_raises NotImplementedError do
52
+ anonymous_class.graphql_name
53
+ end
54
+ end
43
55
  end
44
56
 
45
57
  describe "wrapping a Hash" do
@@ -47,7 +59,6 @@ describe GraphQL::Schema::Object do
47
59
  query_str = <<-GRAPHQL
48
60
  {
49
61
  hashyEnsemble {
50
- name
51
62
  musicians { name }
52
63
  formedAt
53
64
  }
@@ -55,10 +66,21 @@ describe GraphQL::Schema::Object do
55
66
  GRAPHQL
56
67
  res = Jazz::Schema.execute(query_str)
57
68
  ensemble = res["data"]["hashyEnsemble"]
58
- assert_equal "The Grateful Dead", ensemble["name"]
59
69
  assert_equal ["Jerry Garcia"], ensemble["musicians"].map { |m| m["name"] }
60
70
  assert_equal "May 5, 1965", ensemble["formedAt"]
61
71
  end
72
+
73
+ it "works with strings and symbols" do
74
+ query_str = <<-GRAPHQL
75
+ {
76
+ hashByString { falsey }
77
+ hashBySym { falsey }
78
+ }
79
+ GRAPHQL
80
+ res = Jazz::Schema.execute(query_str)
81
+ assert_equal false, res["data"]["hashByString"]["falsey"]
82
+ assert_equal false, res["data"]["hashBySym"]["falsey"]
83
+ end
62
84
  end
63
85
 
64
86
  describe ".to_graphql_type" do
@@ -86,7 +108,7 @@ describe GraphQL::Schema::Object do
86
108
  GRAPHQL
87
109
 
88
110
  res = Jazz::Schema.execute(query_str)
89
- assert_equal ["BELA FLECK AND THE FLECKTONES"], res["data"]["ensembles"].map { |e| e["upcaseName"] }
111
+ assert_equal ["BELA FLECK AND THE FLECKTONES", "ROBERT GLASPER EXPERIMENT"], res["data"]["ensembles"].map { |e| e["upcaseName"] }
90
112
  end
91
113
  end
92
114
 
@@ -104,7 +126,11 @@ describe GraphQL::Schema::Object do
104
126
  }
105
127
  GRAPHQL
106
128
  res = Jazz::Schema.execute(query_str)
107
- assert_equal [{"name" => "Bela Fleck and the Flecktones"}], res["data"]["ensembles"]
129
+ expected_ensembles = [
130
+ {"name" => "Bela Fleck and the Flecktones"},
131
+ {"name" => "ROBERT GLASPER Experiment"},
132
+ ]
133
+ assert_equal expected_ensembles, res["data"]["ensembles"]
108
134
  assert_equal({"name" => "Banjo"}, res["data"]["instruments"].first)
109
135
  end
110
136
 
@@ -127,10 +153,10 @@ describe GraphQL::Schema::Object do
127
153
  }
128
154
  GRAPHQL
129
155
 
130
- res = Jazz::Schema.execute(mutation_str, variables: { "name" => "Miles Davis Quartet" })
156
+ res = Jazz::Schema.execute(mutation_str, variables: { name: "Miles Davis Quartet" })
131
157
  new_id = res["data"]["addEnsemble"]["id"]
132
158
 
133
- res2 = Jazz::Schema.execute(query_str, variables: { "id" => new_id })
159
+ res2 = Jazz::Schema.execute(query_str, variables: { id: new_id })
134
160
  assert_equal "Miles Davis Quartet", res2["data"]["find"]["name"]
135
161
  end
136
162
 
@@ -25,4 +25,14 @@ describe GraphQL::Schema::RelayClassicMutation do
25
25
  assert_equal mutation, mutation.input_type.graphql_definition.mutation
26
26
  end
27
27
  end
28
+
29
+ describe ".null" do
30
+ it "is inherited as true" do
31
+ mutation = Class.new(GraphQL::Schema::RelayClassicMutation) do
32
+ graphql_name "Test"
33
+ end
34
+
35
+ assert mutation.null
36
+ end
37
+ end
28
38
  end