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
@@ -2,30 +2,86 @@
2
2
  require "spec_helper"
3
3
 
4
4
  describe GraphQL::Schema::Argument do
5
- class SchemaArgumentTest < GraphQL::Schema::Object
6
- field :field, String, null: false do
7
- argument :arg, String, description: "test", required: false
5
+ module SchemaArgumentTest
6
+ class Query < GraphQL::Schema::Object
7
+ field :field, String, null: false do
8
+ argument :arg, String, description: "test", required: false
8
9
 
9
- argument :argWithBlock, String, required: false do
10
- description "test"
10
+ argument :arg_with_block, String, required: false do
11
+ description "test"
12
+ end
13
+
14
+ argument :aliased_arg, String, required: false, as: :renamed
15
+ argument :prepared_arg, Int, required: false, prepare: :multiply
16
+ end
17
+
18
+ def field(**args)
19
+ args.inspect
11
20
  end
21
+
22
+ def multiply(val)
23
+ context[:multiply_by] * val
24
+ end
25
+ end
26
+
27
+ class Schema < GraphQL::Schema
28
+ query(Query)
29
+ end
30
+ end
31
+
32
+
33
+
34
+ describe "#name" do
35
+ it "reflects camelization" do
36
+ assert_equal "argWithBlock", SchemaArgumentTest::Query.fields["field"].arguments["argWithBlock"].name
37
+ end
38
+ end
39
+
40
+ describe "#type" do
41
+ let(:argument) { SchemaArgumentTest::Query.fields["field"].arguments["arg"] }
42
+ it "returns the type" do
43
+ assert_equal GraphQL::STRING_TYPE, argument.type
12
44
  end
13
45
  end
14
46
 
15
47
  describe "graphql definition" do
16
48
  it "calls block" do
17
- assert_equal "test", SchemaArgumentTest.fields["field"].arguments["argWithBlock"].description
49
+ assert_equal "test", SchemaArgumentTest::Query.fields["field"].arguments["argWithBlock"].description
18
50
  end
19
51
  end
20
52
 
21
53
  describe "#description" do
22
54
  it "sets description" do
23
- SchemaArgumentTest.fields["field"].arguments["arg"].description "new description"
24
- assert_equal "new description", SchemaArgumentTest.fields["field"].arguments["arg"].description
55
+ SchemaArgumentTest::Query.fields["field"].arguments["arg"].description "new description"
56
+ assert_equal "new description", SchemaArgumentTest::Query.fields["field"].arguments["arg"].description
25
57
  end
26
58
 
27
59
  it "returns description" do
28
- assert_equal "test", SchemaArgumentTest.fields["field"].arguments["argWithBlock"].description
60
+ assert_equal "test", SchemaArgumentTest::Query.fields["field"].arguments["argWithBlock"].description
61
+ end
62
+ end
63
+
64
+ describe "as:" do
65
+ it "uses that Symbol for Ruby kwargs" do
66
+ query_str = <<-GRAPHQL
67
+ { field(aliasedArg: "x") }
68
+ GRAPHQL
69
+
70
+ res = SchemaArgumentTest::Schema.execute(query_str)
71
+ # Make sure it's getting the renamed symbol:
72
+ assert_equal '{:renamed=>"x"}', res["data"]["field"]
73
+ end
74
+ end
75
+
76
+ describe "prepare:" do
77
+ it "calls the method on the field's owner" do
78
+ query_str = <<-GRAPHQL
79
+ { field(preparedArg: 5) }
80
+ GRAPHQL
81
+
82
+ res = SchemaArgumentTest::Schema.execute(query_str, context: {multiply_by: 3})
83
+ # Make sure it's getting the renamed symbol:
84
+ assert_equal '{:prepared_arg=>15}', res["data"]["field"]
29
85
  end
30
86
  end
31
87
  end
@@ -132,11 +132,12 @@ type Hello {
132
132
 
133
133
  it 'supports adding directives while maintaining built-in directives' do
134
134
  schema = <<-SCHEMA
135
- schema {
135
+ schema @custom(thing: true) {
136
136
  query: Hello
137
137
  }
138
138
 
139
139
  directive @foo(arg: Int) on FIELD
140
+ directive @custom(thing: Boolean) on SCHEMA
140
141
 
141
142
  type Hello {
142
143
  str: String
@@ -615,7 +616,7 @@ type Query {
615
616
 
616
617
  it "tracks original AST node" do
617
618
  schema_definition = <<-GRAPHQL
618
- schema {
619
+ schema @custom(thing: true) {
619
620
  query: Query
620
621
  }
621
622
 
@@ -653,6 +654,7 @@ type Type implements Interface {
653
654
  schema = GraphQL::Schema.from_definition(schema_definition)
654
655
 
655
656
  assert_equal [1, 1], schema.ast_node.position
657
+ assert_equal [1, 8], schema.ast_node.directives.first.position
656
658
  assert_equal [5, 1], schema.types["Enum"].ast_node.position
657
659
  assert_equal [6, 3], schema.types["Enum"].values["VALUE"].ast_node.position
658
660
  assert_equal [9, 1], schema.types["Query"].ast_node.position
@@ -67,7 +67,7 @@ describe GraphQL::Schema::Enum do
67
67
  it "works as input" do
68
68
  query_str = "query($family: Family!) { instruments(family: $family) { name } }"
69
69
  expected_names = ["Piano", "Organ"]
70
- result = Jazz::Schema.execute(query_str, variables: { "family" => "KEYS" })
70
+ result = Jazz::Schema.execute(query_str, variables: { family: "KEYS" })
71
71
  assert_equal expected_names, result["data"]["instruments"].map { |i| i["name"] }
72
72
  end
73
73
  end
@@ -4,15 +4,20 @@ require "spec_helper"
4
4
  describe GraphQL::Schema::Field do
5
5
  describe "graphql definition" do
6
6
  let(:object_class) { Jazz::Query }
7
- let(:field) { object_class.fields["inspect_input"] }
7
+ let(:field) { object_class.fields["inspectInput"] }
8
8
 
9
9
  it "uses the argument class" do
10
10
  arg_defn = field.graphql_definition.arguments.values.first
11
11
  assert_equal :ok, arg_defn.metadata[:custom]
12
12
  end
13
13
 
14
+ it "attaches itself to its graphql_definition as type_class" do
15
+ assert_equal field, field.graphql_definition.metadata[:type_class]
16
+ end
17
+
14
18
  it "camelizes the field name, unless camelize: false" do
15
19
  assert_equal 'inspectInput', field.graphql_definition.name
20
+ assert_equal 'inspectInput', field.name
16
21
 
17
22
  underscored_field = GraphQL::Schema::Field.new(:underscored_field, String, null: false, camelize: false, owner: nil) do
18
23
  argument :underscored_arg, String, required: true, camelize: false
@@ -25,11 +30,11 @@ describe GraphQL::Schema::Field do
25
30
  end
26
31
 
27
32
  it "exposes the method override" do
28
- assert_nil field.method
29
33
  object = Class.new(Jazz::BaseObject) do
30
34
  field :t, String, method: :tt, null: true
31
35
  end
32
- assert_equal :tt, object.fields["t"].method
36
+ assert_equal :tt, object.fields["t"].method_sym
37
+ assert_equal "tt", object.fields["t"].method_str
33
38
  end
34
39
 
35
40
  it "accepts a block for definition" do
@@ -84,6 +89,17 @@ describe GraphQL::Schema::Field do
84
89
  assert_equal Jazz::Query, field.owner
85
90
  end
86
91
 
92
+ describe "type" do
93
+ it "tells the return type" do
94
+ assert_equal "[String!]!", field.type.graphql_definition.to_s
95
+ end
96
+
97
+ it "returns the type class" do
98
+ field = Jazz::Query.fields["nowPlaying"]
99
+ assert_equal Jazz::PerformingAct, field.type.of_type
100
+ end
101
+ end
102
+
87
103
  describe "complexity" do
88
104
  it "accepts a keyword argument" do
89
105
  object = Class.new(Jazz::BaseObject) do
@@ -158,10 +174,69 @@ describe GraphQL::Schema::Field do
158
174
  end
159
175
 
160
176
  err = assert_raises ArgumentError do
161
- thing.fields["stuff"].to_graphql.type
177
+ thing.fields["stuff"].type
178
+ end
179
+
180
+ assert_includes err.message, "Thing.stuff"
181
+ assert_includes err.message, "Unexpected class/module"
182
+ end
183
+
184
+ it "makes a suggestion when the type is false" do
185
+ thing = Class.new(GraphQL::Schema::Object) do
186
+ graphql_name "Thing"
187
+ # False might come from an invalid `!`
188
+ field :stuff, false, null: false
189
+ end
190
+
191
+ err = assert_raises ArgumentError do
192
+ thing.fields["stuff"].type
162
193
  end
163
194
 
164
195
  assert_includes err.message, "Thing.stuff"
196
+ assert_includes err.message, "Received `false` instead of a type, maybe a `!` should be replaced with `null: true` (for fields) or `required: true` (for arguments)"
197
+ end
198
+
199
+ it "makes a suggestion when the type is a GraphQL::Field" do
200
+ err = assert_raises ArgumentError do
201
+ Class.new(GraphQL::Schema::Object) do
202
+ graphql_name "Thing"
203
+ # Previously, field was a valid second argument
204
+ field :stuff, GraphQL::Relay::Node.field, null: false
205
+ end
206
+ end
207
+
208
+ assert_includes err.message, "use the `field:` keyword for this instead"
209
+ end
210
+ end
211
+
212
+ describe "mutation" do
213
+ let(:mutation) do
214
+ Class.new(GraphQL::Schema::Mutation) do
215
+ graphql_name "Thing"
216
+
217
+ field :stuff, String, null: false
218
+ end
219
+ end
220
+ let(:error_message) { "when keyword `mutation:` is present, all arguments are ignored, please remove them" }
221
+
222
+ it "fails when including null option as true" do
223
+ error = assert_raises(ArgumentError) do
224
+ GraphQL::Schema::Field.new(:my_field, mutation: mutation, null: true)
225
+ end
226
+
227
+ assert_equal error.message, error_message
228
+ end
229
+
230
+ it "fails when including null option as false" do
231
+ error = assert_raises(ArgumentError) do
232
+ GraphQL::Schema::Field.new(:my_field, mutation: mutation, null: false)
233
+ end
234
+
235
+ assert_equal error.message, error_message
236
+ end
237
+
238
+ it "passes when not including extra arguments" do
239
+ assert_equal GraphQL::Schema::Field.new(:my_field, mutation: mutation).mutation, mutation
165
240
  end
166
241
  end
167
242
  end
@@ -14,6 +14,22 @@ describe GraphQL::Schema::InputObject do
14
14
  argument = input_object.arguments["name"]
15
15
  assert_equal input_object, argument.owner
16
16
  end
17
+
18
+ it "inherits arguments" do
19
+ base_class = Class.new(GraphQL::Schema::InputObject) do
20
+ argument :arg1, String, required: true
21
+ argument :arg2, String, required: true
22
+ end
23
+
24
+ subclass = Class.new(base_class) do
25
+ argument :arg2, Integer, required: true
26
+ argument :arg3, Integer, required: true
27
+ end
28
+
29
+ assert_equal 3, subclass.arguments.size
30
+ assert_equal ["arg1", "arg2", "arg3"], subclass.arguments.keys
31
+ assert_equal ["String!", "Int!", "Int!"], subclass.arguments.values.map { |a| a.type.to_s }
32
+ end
17
33
  end
18
34
 
19
35
  describe ".to_graphql" do
@@ -28,6 +44,46 @@ describe GraphQL::Schema::InputObject do
28
44
  end
29
45
  end
30
46
 
47
+ describe "prepare: / as:" do
48
+ module InputObjectPrepareTest
49
+ class InputObj < GraphQL::Schema::InputObject
50
+ argument :a, Integer, required: true
51
+ argument :b, Integer, required: true, as: :b2
52
+ argument :c, Integer, required: true, prepare: :prep
53
+ argument :d, Integer, required: true, prepare: :prep, as: :d2
54
+ argument :e, Integer, required: true, prepare: ->(val, ctx) { val * ctx[:multiply_by] * 2 }, as: :e2
55
+
56
+ def prep(val)
57
+ val * context[:multiply_by]
58
+ end
59
+ end
60
+
61
+ class Query < GraphQL::Schema::Object
62
+ field :inputs, String, null: false do
63
+ argument :input, InputObj, required: true
64
+ end
65
+
66
+ def inputs(input:)
67
+ input.to_kwargs.inspect
68
+ end
69
+ end
70
+
71
+ class Schema < GraphQL::Schema
72
+ query(Query)
73
+ end
74
+ end
75
+
76
+ it "calls methods on the input object" do
77
+ query_str = <<-GRAPHQL
78
+ { inputs(input: { a: 1, b: 2, c: 3, d: 4, e: 5 }) }
79
+ GRAPHQL
80
+
81
+ res = InputObjectPrepareTest::Schema.execute(query_str, context: { multiply_by: 3 })
82
+ expected_obj = { a: 1, b2: 2, c: 9, d2: 12, e2: 30 }.inspect
83
+ assert_equal expected_obj, res["data"]["inputs"]
84
+ end
85
+ end
86
+
31
87
  describe "in queries" do
32
88
  it "is passed to the field method" do
33
89
  query_str = <<-GRAPHQL
@@ -2,8 +2,9 @@
2
2
  require "spec_helper"
3
3
 
4
4
  module InstrumentationSpec
5
- class SomeInterface < GraphQL::Schema::Interface
6
- field :neverCalled, String, null: false
5
+ module SomeInterface
6
+ include GraphQL::Schema::Interface
7
+ field :never_called, String, null: false
7
8
 
8
9
  def never_called
9
10
  "should never be called"
@@ -15,7 +16,7 @@ module InstrumentationSpec
15
16
  end
16
17
 
17
18
  class Query < GraphQL::Schema::Object
18
- field :someField, [SomeInterface], null: true
19
+ field :some_field, [SomeInterface], null: true
19
20
 
20
21
  def some_field
21
22
  nil
@@ -10,21 +10,17 @@ describe GraphQL::Schema::Interface do
10
10
  assert_equal 2, interface.fields.size
11
11
  end
12
12
 
13
- class NewInterface1 < Jazz::GloballyIdentifiableType
14
- # TODO not great
15
- module Implementation
16
- include Jazz::GloballyIdentifiableType::Implementation
17
- end
13
+ module NewInterface1
14
+ include Jazz::GloballyIdentifiableType
18
15
  end
19
16
 
20
- class NewInterface2 < Jazz::GloballyIdentifiableType
21
- module Implementation
22
- def new_method
23
- end
17
+ module NewInterface2
18
+ include Jazz::GloballyIdentifiableType
19
+ def new_method
24
20
  end
25
21
  end
26
22
 
27
- it "can override Implementation" do
23
+ it "can override methods" do
28
24
  new_object_1 = Class.new(GraphQL::Schema::Object) do
29
25
  implements NewInterface1
30
26
  end
@@ -33,14 +29,19 @@ describe GraphQL::Schema::Interface do
33
29
  assert new_object_1.method_defined?(:id)
34
30
 
35
31
  new_object_2 = Class.new(GraphQL::Schema::Object) do
32
+ graphql_name "XYZ"
36
33
  implements NewInterface2
34
+ field :id, "ID", null: false, description: "The ID !!!!!"
37
35
  end
38
36
 
39
37
  assert_equal 2, new_object_2.fields.size
40
38
  # It got the new method
41
39
  assert new_object_2.method_defined?(:new_method)
42
- # But not the old method
43
- refute new_object_2.method_defined?(:id)
40
+ # And the inherited method
41
+ assert new_object_2.method_defined?(:id)
42
+
43
+ # It gets an overridden description:
44
+ assert_equal "The ID !!!!!", new_object_2.graphql_definition.fields["id"].description
44
45
  end
45
46
  end
46
47
 
@@ -57,25 +58,25 @@ describe GraphQL::Schema::Interface do
57
58
  end
58
59
 
59
60
  it "can specify a resolve_type method" do
60
- interface = Class.new(GraphQL::Schema::Interface) do
61
- def self.resolve_type(_object, _context)
62
- "MyType"
63
- end
64
-
65
- def self.name
66
- "MyInterface"
61
+ interface = Module.new do
62
+ include GraphQL::Schema::Interface
63
+ graphql_name "MyInterface"
64
+
65
+ module self::DefinitionMethods # rubocop:disable Style/ClassAndModuleChildren
66
+ def resolve_type(_object, _context)
67
+ "MyType"
68
+ end
67
69
  end
68
70
  end
71
+
69
72
  interface_type = interface.to_graphql
70
73
  assert_equal "MyType", interface_type.resolve_type_proc.call(nil, nil)
71
74
  end
72
75
 
73
76
  it "can specify orphan types" do
74
- interface = Class.new(GraphQL::Schema::Interface) do
75
- def self.name
76
- "MyInterface"
77
- end
78
-
77
+ interface = Module.new do
78
+ include GraphQL::Schema::Interface
79
+ graphql_name "MyInterface"
79
80
  orphan_types Dummy::CheeseType, Dummy::HoneyType
80
81
  end
81
82
 
@@ -85,10 +86,12 @@ describe GraphQL::Schema::Interface do
85
86
  end
86
87
 
87
88
  it 'supports global_id_field' do
88
- object = Class.new(GraphQL::Schema::Interface) do
89
+ object = Module.new do
90
+ include GraphQL::Schema::Interface
89
91
  graphql_name 'GlobalIdFieldTest'
90
92
  global_id_field :uuid
91
93
  end.to_graphql
94
+
92
95
  uuid_field = object.fields["uuid"]
93
96
 
94
97
  assert_equal GraphQL::NonNullType, uuid_field.type.class
@@ -99,6 +102,18 @@ describe GraphQL::Schema::Interface do
99
102
  )
100
103
  end
101
104
 
105
+ describe "using `include`" do
106
+ it "raises" do
107
+ err = assert_raises RuntimeError do
108
+ Class.new(GraphQL::Schema::Object) do
109
+ include(Jazz::GloballyIdentifiableType)
110
+ end
111
+ end
112
+
113
+ assert_includes err.message, "implements(Jazz::GloballyIdentifiableType)"
114
+ end
115
+ end
116
+
102
117
  describe "in queries" do
103
118
  it "works" do
104
119
  query_str = <<-GRAPHQL