graphql 1.6.4 → 1.6.5

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/core.rb +47 -0
  3. data/lib/generators/graphql/install_generator.rb +15 -20
  4. data/lib/generators/graphql/mutation_generator.rb +31 -1
  5. data/lib/generators/graphql/templates/mutation.erb +2 -2
  6. data/lib/generators/graphql/templates/mutation_type.erb +5 -0
  7. data/lib/generators/graphql/templates/schema.erb +0 -1
  8. data/lib/graphql/argument.rb +6 -5
  9. data/lib/graphql/backwards_compatibility.rb +18 -4
  10. data/lib/graphql/base_type.rb +1 -1
  11. data/lib/graphql/compatibility/execution_specification/counter_schema.rb +1 -1
  12. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +1 -1
  13. data/lib/graphql/compatibility/lazy_execution_specification.rb +9 -2
  14. data/lib/graphql/define.rb +1 -0
  15. data/lib/graphql/define/defined_object_proxy.rb +1 -1
  16. data/lib/graphql/define/no_definition_error.rb +7 -0
  17. data/lib/graphql/enum_type.rb +4 -0
  18. data/lib/graphql/execution/execute.rb +3 -3
  19. data/lib/graphql/execution/field_result.rb +1 -1
  20. data/lib/graphql/execution/lazy/resolve.rb +10 -9
  21. data/lib/graphql/execution/multiplex.rb +6 -5
  22. data/lib/graphql/input_object_type.rb +5 -1
  23. data/lib/graphql/interface_type.rb +12 -3
  24. data/lib/graphql/query.rb +21 -5
  25. data/lib/graphql/query/context.rb +11 -0
  26. data/lib/graphql/schema.rb +48 -27
  27. data/lib/graphql/schema/build_from_definition.rb +1 -1
  28. data/lib/graphql/schema/build_from_definition/resolve_map.rb +2 -2
  29. data/lib/graphql/schema/loader.rb +1 -1
  30. data/lib/graphql/schema/traversal.rb +91 -0
  31. data/lib/graphql/schema/validation.rb +1 -1
  32. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +41 -7
  33. data/lib/graphql/union_type.rb +13 -2
  34. data/lib/graphql/version.rb +1 -1
  35. data/readme.md +1 -3
  36. data/spec/generators/graphql/install_generator_spec.rb +3 -1
  37. data/spec/generators/graphql/mutation_generator_spec.rb +14 -0
  38. data/spec/graphql/analysis/max_query_complexity_spec.rb +12 -1
  39. data/spec/graphql/analysis/query_complexity_spec.rb +1 -1
  40. data/spec/graphql/argument_spec.rb +29 -0
  41. data/spec/graphql/define/assign_argument_spec.rb +4 -4
  42. data/spec/graphql/define/instance_definable_spec.rb +1 -1
  43. data/spec/graphql/enum_type_spec.rb +8 -0
  44. data/spec/graphql/execution/lazy_spec.rb +30 -3
  45. data/spec/graphql/interface_type_spec.rb +44 -0
  46. data/spec/graphql/introspection/schema_type_spec.rb +3 -0
  47. data/spec/graphql/introspection/type_type_spec.rb +1 -0
  48. data/spec/graphql/object_type_spec.rb +8 -3
  49. data/spec/graphql/query/context_spec.rb +18 -0
  50. data/spec/graphql/query/executor_spec.rb +1 -1
  51. data/spec/graphql/query/literal_input_spec.rb +31 -15
  52. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +1 -1
  53. data/spec/graphql/query/variables_spec.rb +25 -1
  54. data/spec/graphql/query_spec.rb +24 -9
  55. data/spec/graphql/relay/mutation_spec.rb +1 -1
  56. data/spec/graphql/schema/build_from_definition_spec.rb +1 -1
  57. data/spec/graphql/schema/loader_spec.rb +1 -1
  58. data/spec/graphql/schema/printer_spec.rb +1 -1
  59. data/spec/graphql/schema/{reduce_types_spec.rb → traversal_spec.rb} +21 -4
  60. data/spec/graphql/schema/warden_spec.rb +1 -1
  61. data/spec/graphql/schema_spec.rb +23 -2
  62. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +133 -0
  63. data/spec/graphql/union_type_spec.rb +53 -0
  64. data/spec/spec_helper.rb +9 -0
  65. data/spec/support/dummy/data.rb +14 -5
  66. data/spec/support/dummy/schema.rb +46 -5
  67. data/spec/support/star_wars/data.rb +10 -6
  68. data/spec/support/star_wars/schema.rb +5 -2
  69. metadata +8 -7
  70. data/lib/graphql/schema/instrumented_field_map.rb +0 -40
  71. data/lib/graphql/schema/reduce_types.rb +0 -69
  72. data/lib/graphql/schema/type_map.rb +0 -31
@@ -24,6 +24,13 @@ describe GraphQL::Query::Context do
24
24
  field :pushContext, types.Int do
25
25
  resolve ->(t,a,c) { CTX << c; 1 }
26
26
  end
27
+
28
+ field :pushQueryError, types.Int do
29
+ resolve ->(t,a,c) {
30
+ c.query.context.add_error(GraphQL::ExecutionError.new("Query-level error"))
31
+ 1
32
+ }
33
+ end
27
34
  }}
28
35
  let(:schema) { GraphQL::Schema.define(query: query_type, mutation: nil)}
29
36
  let(:result) { schema.execute(query_string, context: {"some_key" => "some value"})}
@@ -118,4 +125,15 @@ describe GraphQL::Query::Context do
118
125
  assert_equal [2, 9], [err.ast_node.line, err.ast_node.col]
119
126
  end
120
127
  end
128
+
129
+ describe "query-level errors" do
130
+ let(:query_string) { %|
131
+ { pushQueryError }
132
+ |}
133
+
134
+ it "allows query-level errors" do
135
+ expected_err = { "message" => "Query-level error" }
136
+ assert_equal [expected_err], result["errors"]
137
+ end
138
+ end
121
139
  end
@@ -119,7 +119,7 @@ describe GraphQL::Query::Executor do
119
119
  end
120
120
  end
121
121
 
122
- GraphQL::Schema.define(query: DummyQueryType, mutation: Dummy::DairyAppMutationType, resolve_type: :pass, id_from_object: :pass)
122
+ GraphQL::Schema.define(query: DummyQueryType, mutation: Dummy::DairyAppMutationType, resolve_type: ->(a,b,c) { :pass }, id_from_object: :pass)
123
123
  }
124
124
  let(:variables) { nil }
125
125
  let(:query_string) { %|
@@ -5,8 +5,8 @@ describe GraphQL::Query::LiteralInput do
5
5
  describe ".from_arguments" do
6
6
  describe "arguments are prepared" do
7
7
  let(:schema) {
8
- query = GraphQL::ObjectType.define do
9
- name "Query"
8
+ type = GraphQL::ObjectType.define do
9
+ name "SomeType"
10
10
 
11
11
  field :addToArgumentValue do
12
12
  type !types.Int
@@ -35,40 +35,56 @@ describe GraphQL::Query::LiteralInput do
35
35
  end
36
36
  end
37
37
 
38
+ query = GraphQL::ObjectType.define do
39
+ name "Query"
40
+
41
+ field :top, type, resolve: ->(_, _, _) { true }
42
+ end
43
+
38
44
  GraphQL::Schema.define(query: query)
39
45
  }
40
46
 
41
47
  it "prepares values from query literals" do
42
- result = schema.execute("{ addToArgumentValue(value: 1) }", context: { val: 1 })
43
- assert_equal(result["data"]["addToArgumentValue"], 2)
48
+ result = schema.execute("{ top { addToArgumentValue(value: 1) } }", context: { val: 1 })
49
+ assert_equal(result["data"]["top"]["addToArgumentValue"], 2)
44
50
  end
45
51
 
46
52
  it "prepares default values" do
47
- result = schema.execute("{ addToArgumentValue }", context: { val: 4 })
48
- assert_equal(7, result["data"]["addToArgumentValue"])
53
+ result = schema.execute("{ top { addToArgumentValue } }", context: { val: 4 })
54
+ assert_equal(7, result["data"]["top"]["addToArgumentValue"])
49
55
  end
50
56
 
51
57
  it "raises an execution error if the default value is bad" do
52
- result = schema.execute("{ fieldWithArgumentThatIsBadByDefault }", context: { })
53
- assert_equal(result["errors"], [{"message" => "Always bad"}])
58
+ result = schema.execute("{ top { fieldWithArgumentThatIsBadByDefault } }", context: { })
59
+ assert_equal(result["data"], {
60
+ "top"=>{
61
+ "fieldWithArgumentThatIsBadByDefault"=>nil}
62
+ })
63
+ assert_equal(result["errors"], [
64
+ {"message"=>"Always bad",
65
+ "locations"=>[{"line"=>1, "column"=>9}],
66
+ "path"=>["top", "fieldWithArgumentThatIsBadByDefault"]}
67
+ ])
54
68
  end
55
69
 
56
70
  it "prepares values from variables" do
57
- result = schema.execute("query ($value: Int!) { addToArgumentValue(value: $value) }", variables: { "value" => 1}, context: { val: 2 } )
58
- assert_equal(result["data"]["addToArgumentValue"], 3)
71
+ result = schema.execute("query ($value: Int!) { top { addToArgumentValue(value: $value) } }", variables: { "value" => 1}, context: { val: 2 } )
72
+ assert_equal(result["data"]["top"]["addToArgumentValue"], 3)
59
73
  end
60
74
 
61
75
  it "prepares values correctly if called multiple times with different arguments" do
62
- result = schema.execute("{ first: addToArgumentValue(value: 1) second: addToArgumentValue(value: 2) }", context: { val: 3 })
63
- assert_equal(result["data"]["first"], 4)
64
- assert_equal(result["data"]["second"], 5)
76
+ result = schema.execute("{ top { first: addToArgumentValue(value: 1) second: addToArgumentValue(value: 2) } }", context: { val: 3 })
77
+ assert_equal(result["data"]["top"]["first"], 4)
78
+ assert_equal(result["data"]["top"]["second"], 5)
65
79
  end
66
80
 
67
81
  it "adds message to errors key if an ExecutionError is returned from the prepare function" do
68
- result = schema.execute("{ addToArgumentValue(value: 999) }")
82
+ result = schema.execute("{ top { addToArgumentValue(value: 999) } }")
83
+ assert_equal(result["data"]["top"], nil)
69
84
  assert_equal(result["errors"][0]["message"], "Can't return more than 3 digits")
70
85
  assert_equal(result["errors"][0]["locations"][0]["line"], 1)
71
- assert_equal(result["errors"][0]["locations"][0]["column"], 22)
86
+ assert_equal(result["errors"][0]["locations"][0]["column"], 28)
87
+ assert_equal(result["errors"][0]["path"], ["top", "addToArgumentValue"])
72
88
  end
73
89
  end
74
90
  end
@@ -45,7 +45,7 @@ describe GraphQL::Query::SerialExecution::ValueResolution do
45
45
  GraphQL::Schema.define do
46
46
  query(query_root)
47
47
  orphan_types [some_object]
48
- resolve_type ->(obj, ctx) do
48
+ resolve_type ->(type, obj, ctx) do
49
49
  if obj.is_a?(Symbol)
50
50
  other_object
51
51
  else
@@ -16,7 +16,8 @@ describe GraphQL::Query::Variables do
16
16
  |}
17
17
  let(:ast_variables) { GraphQL.parse(query_string).definitions.first.variables }
18
18
  let(:schema) { Dummy::Schema }
19
- let(:variables) { GraphQL::Query::Variables.new(
19
+ let(:variables) {
20
+ GraphQL::Query::Variables.new(
20
21
  OpenStruct.new({
21
22
  schema: schema,
22
23
  warden: GraphQL::Schema::Warden.new(schema.default_filter, schema: schema, context: nil),
@@ -34,6 +35,29 @@ describe GraphQL::Query::Variables do
34
35
  end
35
36
  end
36
37
 
38
+ describe "validating input objects" do
39
+ let(:query_string) {%|
40
+ query searchMyDairy (
41
+ $product: DairyProductInput
42
+ ) {
43
+ searchDairy(product: $product) {
44
+ ... on Cheese {
45
+ flavor
46
+ }
47
+ }
48
+ }
49
+ |}
50
+
51
+ describe "when provided input is an array" do
52
+ let(:provided_variables) { { "product" => [] } }
53
+
54
+ it "validates invalid input objects" do
55
+ expected = "Variable product of type DairyProductInput was provided invalid value"
56
+ assert_equal expected, variables.errors.first.message
57
+ end
58
+ end
59
+ end
60
+
37
61
  describe "nullable variables" do
38
62
  module ObjectWithThingsCount
39
63
  def self.thingsCount(args, ctx) # rubocop:disable Style/MethodName
@@ -45,15 +45,15 @@ describe GraphQL::Query do
45
45
  let(:result) { query.result }
46
46
 
47
47
  describe "when passed no query string or document" do
48
- it 'fails with an ArgumentError' do
49
- assert_raises(ArgumentError) {
50
- GraphQL::Query.new(
51
- schema,
52
- variables: query_variables,
53
- operation_name: operation_name,
54
- max_depth: max_depth,
55
- ).result
56
- }
48
+ it 'returns an error to the client' do
49
+ res = GraphQL::Query.new(
50
+ schema,
51
+ variables: query_variables,
52
+ operation_name: operation_name,
53
+ max_depth: max_depth,
54
+ ).result
55
+ assert_equal 1, res["errors"].length
56
+ assert_equal "No query string was present", res["errors"][0]["message"]
57
57
  end
58
58
 
59
59
  it 'can be assigned later' do
@@ -94,6 +94,21 @@ describe GraphQL::Query do
94
94
  assert_equal "q3", query.selected_operation_name
95
95
  end
96
96
  end
97
+
98
+ describe "assigning operation_name=" do
99
+ let(:query_string) { <<-GRAPHQL
100
+ query q3 { manchego: cheese(id: 3) { flavor } }
101
+ query q2 { gouda: cheese(id: 2) { flavor } }
102
+ GRAPHQL
103
+ }
104
+
105
+ it "runs the assigned name" do
106
+ query = GraphQL::Query.new(Dummy::Schema, query_string, operation_name: "q3")
107
+ query.operation_name = "q2"
108
+ res = query.result
109
+ assert_equal "Gouda", res["data"]["gouda"]["flavor"]
110
+ end
111
+ end
97
112
  end
98
113
 
99
114
  describe "when passed a document instance" do
@@ -258,7 +258,7 @@ describe GraphQL::Relay::Mutation do
258
258
 
259
259
  GraphQL::Schema.define do
260
260
  mutation(mutation_root)
261
- resolve_type ->(obj, ctx) { "not really used" }
261
+ resolve_type NO_OP_RESOLVE_TYPE
262
262
  end
263
263
  }
264
264
 
@@ -735,7 +735,7 @@ SCHEMA
735
735
  val.to_f
736
736
  }
737
737
  },
738
- resolve_type: ->(obj, ctx) {
738
+ resolve_type: ->(type, obj, ctx) {
739
739
  return ctx.schema.types['A']
740
740
  },
741
741
  Query: {
@@ -125,7 +125,7 @@ describe GraphQL::Schema::Loader do
125
125
  query: query_root,
126
126
  mutation: mutation_root,
127
127
  orphan_types: [audio_type, video_type],
128
- resolve_type: :pass,
128
+ resolve_type: ->(a,b,c) { :pass },
129
129
  )
130
130
  }
131
131
 
@@ -123,7 +123,7 @@ describe GraphQL::Schema::Printer do
123
123
  query: query_root,
124
124
  mutation: mutation_root,
125
125
  subscription: subscription_root,
126
- resolve_type: :pass,
126
+ resolve_type: ->(a,b,c) { :pass },
127
127
  orphan_types: [media_union_type]
128
128
  )
129
129
  }
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
  require "spec_helper"
3
3
 
4
- describe GraphQL::Schema::ReduceTypes do
4
+ describe GraphQL::Schema::Traversal do
5
5
  def reduce_types(types)
6
- GraphQL::Schema::ReduceTypes.reduce(types)
6
+ schema = GraphQL::Schema.define(orphan_types: types, resolve_type: :dummy)
7
+ traversal = GraphQL::Schema::Traversal.new(schema, introspection: false)
8
+ traversal.type_map
7
9
  end
8
10
 
9
11
  it "finds types from a single type and its fields" do
@@ -12,13 +14,14 @@ describe GraphQL::Schema::ReduceTypes do
12
14
  "Float" => GraphQL::FLOAT_TYPE,
13
15
  "String" => GraphQL::STRING_TYPE,
14
16
  "Edible" => Dummy::EdibleInterface,
17
+ "EdibleAsMilk" => Dummy::EdibleAsMilkInterface,
15
18
  "DairyAnimal" => Dummy::DairyAnimalEnum,
16
19
  "Int" => GraphQL::INT_TYPE,
17
20
  "AnimalProduct" => Dummy::AnimalProductInterface,
18
21
  "LocalProduct" => Dummy::LocalProductInterface,
19
22
  }
20
23
  result = reduce_types([Dummy::CheeseType])
21
- assert_equal(expected.keys, result.keys)
24
+ assert_equal(expected.keys.sort, result.keys.sort)
22
25
  assert_equal(expected, result.to_h)
23
26
  end
24
27
 
@@ -27,6 +30,20 @@ describe GraphQL::Schema::ReduceTypes do
27
30
  assert_equal(Dummy::DairyProductInputType, result["DairyProductInput"])
28
31
  end
29
32
 
33
+ it "finds types from field instrumentation" do
34
+ type = GraphQL::ObjectType.define do
35
+ name "ArgTypeTest"
36
+ connection :t, type.connection_type
37
+ end
38
+
39
+ result = reduce_types([type])
40
+ expected_types = [
41
+ "ArgTypeTest", "ArgTypeTestConnection", "ArgTypeTestEdge",
42
+ "Boolean", "Int", "PageInfo", "String"
43
+ ]
44
+ assert_equal expected_types, result.keys.sort
45
+ end
46
+
30
47
  it "finds types from nested InputObjectTypes" do
31
48
  type_child = GraphQL::InputObjectType.define do
32
49
  name "InputTypeChild"
@@ -92,7 +109,7 @@ describe GraphQL::Schema::ReduceTypes do
92
109
  describe "when getting a type which doesnt exist" do
93
110
  it "raises an error" do
94
111
  type_map = reduce_types([])
95
- assert_raises(RuntimeError) { type_map["SomeType"] }
112
+ assert_raises(KeyError) { type_map.fetch("SomeType") }
96
113
  end
97
114
  end
98
115
 
@@ -120,7 +120,7 @@ module MaskHelpers
120
120
  query QueryType
121
121
  mutation MutationType
122
122
  subscription MutationType
123
- resolve_type ->(obj, ctx) { PhonemeType }
123
+ resolve_type ->(type, obj, ctx) { PhonemeType }
124
124
  instrument :query, FilterInstrumentation
125
125
  end
126
126
 
@@ -99,7 +99,7 @@ describe GraphQL::Schema do
99
99
  assert_raises(NotImplementedError) {
100
100
  GraphQL::Schema.define do
101
101
  query(query_type)
102
- resolve_type ->(obj, ctx) { :whatever }
102
+ resolve_type NO_OP_RESOLVE_TYPE
103
103
  end
104
104
  }
105
105
  end
@@ -125,7 +125,7 @@ describe GraphQL::Schema do
125
125
  assert_raises(NotImplementedError) {
126
126
  GraphQL::Schema.define do
127
127
  query(query_type)
128
- resolve_type ->(obj, ctx) { :whatever }
128
+ resolve_type NO_OP_RESOLVE_TYPE
129
129
  end
130
130
  }
131
131
  end
@@ -293,6 +293,27 @@ type Query {
293
293
  res = schema.execute("query { int(value: 2) } ")
294
294
  assert_equal 24, res["data"]["int"]
295
295
  end
296
+
297
+ class CyclicalDependencyInstrumentation
298
+ def initialize(schema)
299
+ @schema = schema
300
+ end
301
+
302
+ def instrument(type, field)
303
+ @schema.types # infinite loop
304
+ field
305
+ end
306
+ end
307
+
308
+ describe "field instrumenters which cause loops" do
309
+ it "has a nice error message" do
310
+ assert_raises(GraphQL::Schema::CyclicalDefinitionError) do
311
+ schema.redefine {
312
+ instrument(:field, CyclicalDependencyInstrumentation.new(self.target))
313
+ }
314
+ end
315
+ end
316
+ end
296
317
  end
297
318
 
298
319
  describe "#lazy? / #lazy_method_name" do
@@ -80,4 +80,137 @@ describe GraphQL::StaticValidation::VariableUsagesAreAllowed do
80
80
  assert_equal "Argument 'id' on Field 'cheese' has an invalid value. Expected type 'Int!'.", errors[0]["message"]
81
81
  end
82
82
  end
83
+
84
+ describe "list-type variables" do
85
+ let(:schema) {
86
+ GraphQL::Schema.from_definition <<-GRAPHQL
87
+ input ImageSize {
88
+ height: Int
89
+ width: Int
90
+ scale: Int
91
+ }
92
+
93
+ type Query {
94
+ imageUrl(height: Int, width: Int, size: ImageSize, sizes: [ImageSize!]): String!
95
+ }
96
+ GRAPHQL
97
+ }
98
+
99
+ describe "nullability mismatch" do
100
+ let(:query_string) {
101
+ <<-GRAPHQL
102
+ # This variable _should_ be [ImageSize!]
103
+ query ($sizes: [ImageSize]) {
104
+ imageUrl(sizes: $sizes)
105
+ }
106
+ GRAPHQL
107
+ }
108
+
109
+ it "finds invalid inner definitions" do
110
+ assert_equal 1, errors.size
111
+ expected_message = "Nullability mismatch on variable $sizes and argument sizes ([ImageSize] / [ImageSize!])"
112
+ assert_equal [expected_message], errors.map { |e| e["message"] }
113
+ end
114
+ end
115
+
116
+ describe "list dimension mismatch" do
117
+ let(:query_string) {
118
+ <<-GRAPHQL
119
+ query ($sizes: [ImageSize]) {
120
+ imageUrl(sizes: [$sizes])
121
+ }
122
+ GRAPHQL
123
+ }
124
+
125
+ it "finds invalid inner definitions" do
126
+ assert_equal 1, errors.size
127
+ expected_message = "List dimension mismatch on variable $sizes and argument sizes ([[ImageSize]] / [ImageSize!])"
128
+ assert_equal [expected_message], errors.map { |e| e["message"] }
129
+ end
130
+ end
131
+
132
+ describe 'list is in the argument' do
133
+ let(:query_string) {
134
+ <<-GRAPHQL
135
+ query ($size: ImageSize!) {
136
+ imageUrl(sizes: [$size])
137
+ }
138
+ GRAPHQL
139
+ }
140
+
141
+ it "is a valid query" do
142
+ assert_equal 0, errors.size
143
+ end
144
+
145
+ describe "mixed with invalid literals" do
146
+ let(:query_string) {
147
+ <<-GRAPHQL
148
+ query ($size: ImageSize!) {
149
+ imageUrl(sizes: [$size, 1, true])
150
+ }
151
+ GRAPHQL
152
+ }
153
+
154
+ it "is an invalid query" do
155
+ assert_equal 1, errors.size
156
+ end
157
+ end
158
+
159
+ describe "mixed with invalid variables" do
160
+ let(:query_string) {
161
+ <<-GRAPHQL
162
+ query ($size: ImageSize!, $wrongSize: Boolean!) {
163
+ imageUrl(sizes: [$size, $wrongSize])
164
+ }
165
+ GRAPHQL
166
+ }
167
+
168
+ it "is an invalid query" do
169
+ assert_equal 1, errors.size
170
+ end
171
+ end
172
+
173
+ describe "mixed with valid literals and invalid variables" do
174
+ let(:query_string) {
175
+ <<-GRAPHQL
176
+ query ($size: ImageSize!, $wrongSize: Boolean!) {
177
+ imageUrl(sizes: [$size, {height: 100} $wrongSize])
178
+ }
179
+ GRAPHQL
180
+ }
181
+
182
+ it "is an invalid query" do
183
+ assert_equal 1, errors.size
184
+ end
185
+ end
186
+ end
187
+
188
+ describe 'argument contains a list with literal values' do
189
+ let(:query_string) {
190
+ <<-GRAPHQL
191
+ query {
192
+ imageUrl(sizes: [{height: 100, width: 100, scale: 1}])
193
+ }
194
+ GRAPHQL
195
+ }
196
+
197
+ it "is a valid query" do
198
+ assert_equal 0, errors.size
199
+ end
200
+ end
201
+
202
+ describe 'argument contains a list with both literal and variable values' do
203
+ let(:query_string) {
204
+ <<-GRAPHQL
205
+ query($size1: ImageSize!, $size2: ImageSize!) {
206
+ imageUrl(sizes: [{height: 100, width: 100, scale: 1}, $size1, {height: 1920, width: 1080, scale: 2}, $size2])
207
+ }
208
+ GRAPHQL
209
+ }
210
+
211
+ it "is a valid query" do
212
+ assert_equal 0, errors.size
213
+ end
214
+ end
215
+ end
83
216
  end