graphql 0.18.5 → 0.18.6

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.
@@ -21,7 +21,7 @@ module GraphQL
21
21
  # end
22
22
  #
23
23
  class ObjectType < GraphQL::BaseType
24
- accepts_definitions :interfaces, field: GraphQL::Define::AssignObjectField
24
+ accepts_definitions :interfaces, :fields, field: GraphQL::Define::AssignObjectField
25
25
 
26
26
  # @return [Hash<String => GraphQL::Field>] Map String fieldnames to their {GraphQL::Field} implementations
27
27
  lazy_defined_attr_accessor :fields
@@ -0,0 +1,133 @@
1
+ module GraphQL
2
+ class Schema
3
+ # You can use the result of {GraphQL::Introspection::INTROSPECTION_QUERY}
4
+ # to make a schema. This schema is missing some important details like
5
+ # `resolve` functions, but it does include the full type system,
6
+ # so you can use it to validate queries.
7
+ module Loader
8
+ extend self
9
+
10
+ # Create schema with the result of an introspection query.
11
+ # @param introspection_result [Hash] A response from {GraphQL::Introspection::INTROSPECTION_QUERY}
12
+ # @return [GraphQL::Schema] the schema described by `input`
13
+ def load(introspection_result)
14
+ schema = introspection_result.fetch("data").fetch("__schema")
15
+
16
+ types = {}
17
+ type_resolver = -> (type) { -> { resolve_type(types, type) } }
18
+
19
+ schema.fetch("types").each do |type|
20
+ next if type.fetch("name").start_with?("__")
21
+ type_object = define_type(type, type_resolver)
22
+ types[type_object.name] = type_object
23
+ end
24
+
25
+ query = types.fetch(schema.fetch("queryType").fetch("name"))
26
+
27
+ Schema.new(query: query, types: types.values)
28
+ end
29
+
30
+ class << self
31
+ private
32
+
33
+ def resolve_type(types, type)
34
+ case kind = type.fetch("kind")
35
+ when "ENUM", "INTERFACE", "INPUT_OBJECT", "OBJECT", "SCALAR", "UNION"
36
+ types.fetch(type.fetch("name"))
37
+ when "LIST"
38
+ ListType.new(of_type: resolve_type(types, type.fetch("ofType")))
39
+ when "NON_NULL"
40
+ NonNullType.new(of_type: resolve_type(types, type.fetch("ofType")))
41
+ else
42
+ fail NotImplementedError, "#{kind} not implemented"
43
+ end
44
+ end
45
+
46
+ def define_type(type, type_resolver)
47
+ case type.fetch("kind")
48
+ when "ENUM"
49
+ EnumType.define(
50
+ name: type["name"],
51
+ description: type["description"],
52
+ values: type["enumValues"].map { |enum|
53
+ EnumType::EnumValue.new(
54
+ name: enum["name"],
55
+ description: enum["description"],
56
+ deprecation_reason: enum["deprecationReason"],
57
+ value: enum["value"]
58
+ )
59
+ })
60
+ when "INTERFACE"
61
+ InterfaceType.define(
62
+ name: type["name"],
63
+ description: type["description"],
64
+ fields: Hash[type["fields"].map { |field|
65
+ [field["name"], define_type(field.merge("kind" => "FIELD"), type_resolver)]
66
+ }]
67
+ )
68
+ when "INPUT_OBJECT"
69
+ InputObjectType.define(
70
+ name: type["name"],
71
+ description: type["description"],
72
+ arguments: Hash[type["inputFields"].map { |arg|
73
+ [arg["name"], define_type(arg.merge("kind" => "ARGUMENT"), type_resolver)]
74
+ }]
75
+ )
76
+ when "OBJECT"
77
+ ObjectType.define(
78
+ name: type["name"],
79
+ description: type["description"],
80
+ fields: Hash[type["fields"].map { |field|
81
+ [field["name"], define_type(field.merge("kind" => "FIELD"), type_resolver)]
82
+ }]
83
+ )
84
+ when "FIELD"
85
+ Field.define(
86
+ name: type["name"],
87
+ type: type_resolver.call(type["type"]),
88
+ description: type["description"],
89
+ arguments: Hash[type["args"].map { |arg|
90
+ [arg["name"], define_type(arg.merge("kind" => "ARGUMENT"), type_resolver)]
91
+ }]
92
+ )
93
+ when "ARGUMENT"
94
+ Argument.define(
95
+ name: type["name"],
96
+ type: type_resolver.call(type["type"]),
97
+ description: type["description"],
98
+ default_value: type["defaultValue"]
99
+ )
100
+ when "SCALAR"
101
+ case type.fetch("name")
102
+ when "Int"
103
+ INT_TYPE
104
+ when "String"
105
+ STRING_TYPE
106
+ when "Float"
107
+ FLOAT_TYPE
108
+ when "Boolean"
109
+ BOOLEAN_TYPE
110
+ when "ID"
111
+ ID_TYPE
112
+ else
113
+ ScalarType.define(
114
+ name: type["name"],
115
+ description: type["description"]
116
+ )
117
+ end
118
+ when "UNION"
119
+ UnionType.define(
120
+ name: type["name"],
121
+ description: type["description"],
122
+ possible_types: type["possibleTypes"].map { |possible_type|
123
+ type_resolver.call(possible_type)
124
+ }
125
+ )
126
+ else
127
+ fail NotImplementedError, "#{type["kind"]} not implemented"
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -1,3 +1,3 @@
1
1
  module GraphQL
2
- VERSION = "0.18.5"
2
+ VERSION = "0.18.6"
3
3
  end
@@ -17,4 +17,9 @@ describe GraphQL::Argument do
17
17
  expected_error = %|Query is invalid: field "invalid" argument "invalid" default value ["123"] is not valid for type Float|
18
18
  assert_equal expected_error, err.message
19
19
  end
20
+
21
+ it "accepts proc type" do
22
+ argument = GraphQL::Argument.define(name: :favoriteFood, type: -> { GraphQL::STRING_TYPE })
23
+ assert_equal GraphQL::STRING_TYPE, argument.type
24
+ end
20
25
  end
@@ -28,4 +28,11 @@ describe GraphQL::EnumType do
28
28
  assert(!result.valid?)
29
29
  end
30
30
  end
31
+
32
+ it "accepts values array" do
33
+ cow = GraphQL::EnumType::EnumValue.define(name: "COW")
34
+ goat = GraphQL::EnumType::EnumValue.define(name: "GOAT")
35
+ enum = GraphQL::EnumType.define(name: "DairyAnimal", values: [cow, goat])
36
+ assert_equal({ "COW" => cow, "GOAT" => goat }, enum.values)
37
+ end
31
38
  end
@@ -17,6 +17,12 @@ describe GraphQL::Field do
17
17
  assert_equal(DairyProductUnion, field.type)
18
18
  end
19
19
 
20
+ it "accepts arguments definition" do
21
+ number = GraphQL::Argument.define(name: :number, type: -> { GraphQL::INT_TYPE })
22
+ field = GraphQL::Field.define(type: DairyProductUnion, arguments: [number])
23
+ assert_equal([number], field.arguments)
24
+ end
25
+
20
26
  describe ".property " do
21
27
  let(:field) do
22
28
  GraphQL::Field.define do
@@ -1,562 +1,7 @@
1
1
  require "spec_helper"
2
+ require 'graphql/language/parser_tests'
2
3
 
3
4
  describe GraphQL::Language::Parser do
4
- let(:document) { GraphQL::Language::Parser.parse(query_string) }
5
- let(:query_string) {%|
6
- query getStuff($someVar: Int = 1, $anotherVar: [String!] ) @skip(if: false) {
7
- myField: someField(someArg: $someVar, ok: 1.4) @skip(if: $anotherVar) @thing(or: "Whatever")
8
-
9
- anotherField(someArg: [1,2,3]) {
10
- nestedField
11
- ... moreNestedFields @skip(if: true)
12
- }
13
-
14
- ... on OtherType @include(unless: false){
15
- field(arg: [{key: "value", anotherKey: 0.9, anotherAnotherKey: WHATEVER}])
16
- anotherField
17
- }
18
-
19
- ... {
20
- id
21
- }
22
- }
23
-
24
- fragment moreNestedFields on NestedType @or(something: "ok") {
25
- anotherNestedField
26
- }
27
- |}
28
-
29
- describe ".parse" do
30
- it "parses queries" do
31
- assert document
32
- end
33
-
34
- describe "visited nodes" do
35
- let(:query) { document.definitions.first }
36
- let(:fragment_def) { document.definitions.last }
37
-
38
- it "creates a valid document" do
39
- assert document.is_a?(GraphQL::Language::Nodes::Document)
40
- assert_equal 2, document.definitions.length
41
- end
42
-
43
- it "creates a valid operation" do
44
- assert query.is_a?(GraphQL::Language::Nodes::OperationDefinition)
45
- assert_equal "getStuff", query.name
46
- assert_equal "query", query.operation_type
47
- assert_equal 2, query.variables.length
48
- assert_equal 4, query.selections.length
49
- assert_equal 1, query.directives.length
50
- assert_equal [2, 5], [query.line, query.col]
51
- end
52
-
53
- it "creates a valid fragment definition" do
54
- assert fragment_def.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
55
- assert_equal "moreNestedFields", fragment_def.name
56
- assert_equal 1, fragment_def.selections.length
57
- assert_equal "NestedType", fragment_def.type
58
- assert_equal 1, fragment_def.directives.length
59
- assert_equal [20, 5], fragment_def.position
60
- end
61
-
62
- describe "variable definitions" do
63
- let(:optional_var) { query.variables.first }
64
- it "gets name and type" do
65
- assert_equal "someVar", optional_var.name
66
- assert_equal "Int", optional_var.type.name
67
- end
68
-
69
- it "gets default value" do
70
- assert_equal 1, optional_var.default_value
71
- end
72
-
73
- it "gets position info" do
74
- assert_equal [2, 20], optional_var.position
75
- end
76
- end
77
-
78
- describe "fields" do
79
- let(:leaf_field) { query.selections.first }
80
- let(:parent_field) { query.selections[1] }
81
-
82
- it "gets name, alias, arguments and directives" do
83
- assert_equal "someField", leaf_field.name
84
- assert_equal "myField", leaf_field.alias
85
- assert_equal 2, leaf_field.directives.length
86
- assert_equal 2, leaf_field.arguments.length
87
- end
88
-
89
- it "gets nested fields" do
90
- assert_equal 2, parent_field.selections.length
91
- end
92
-
93
- it "gets location info" do
94
- assert_equal [3 ,7], leaf_field.position
95
- end
96
-
97
- describe "when the arguments list is empty" do
98
- let(:query_string) { "{ field() }"}
99
- let(:field) { query.selections.first }
100
- it "has zero arguments" do
101
- assert_equal 0, field.arguments.length
102
- end
103
- end
104
-
105
- describe "when selections are empty" do
106
- let(:query_string) { "{ field { } }"}
107
- let(:field) { query.selections.first }
108
- it "has zero selections" do
109
- assert_equal 0, field.selections.length
110
- end
111
- end
112
- end
113
-
114
- describe "arguments" do
115
- let(:literal_argument) { query.selections.first.arguments.last }
116
- let(:variable_argument) { query.selections.first.arguments.first }
117
-
118
- it "gets name and literal value" do
119
- assert_equal "ok", literal_argument.name
120
- assert_equal 1.4, literal_argument.value
121
- end
122
-
123
- it "gets name and variable value" do
124
- assert_equal "someArg", variable_argument.name
125
- assert_equal "someVar", variable_argument.value.name
126
- end
127
-
128
-
129
- it "gets position info" do
130
- assert_equal [3, 26], variable_argument.position
131
- end
132
- end
133
-
134
- describe "fragment spreads" do
135
- let(:fragment_spread) { query.selections[1].selections.last }
136
- it "gets the name and directives" do
137
- assert_equal "moreNestedFields", fragment_spread.name
138
- assert_equal 1, fragment_spread.directives.length
139
- end
140
-
141
- it "gets position info" do
142
- assert_equal [7, 9], fragment_spread.position
143
- end
144
- end
145
-
146
- describe "directives" do
147
- let(:variable_directive) { query.selections.first.directives.first }
148
-
149
- it "gets the name and arguments" do
150
- assert_equal "skip", variable_directive.name
151
- assert_equal "if", variable_directive.arguments.first.name
152
- assert_equal 1, variable_directive.arguments.length
153
- end
154
-
155
- it "gets position info" do
156
- assert_equal [3, 54], variable_directive.position
157
- end
158
- end
159
-
160
- describe "inline fragments" do
161
- let(:inline_fragment) { query.selections[2] }
162
- let(:typeless_inline_fragment) { query.selections[3] }
163
-
164
- it "gets the type and directives" do
165
- assert_equal "OtherType", inline_fragment.type
166
- assert_equal 2, inline_fragment.selections.length
167
- assert_equal 1, inline_fragment.directives.length
168
- end
169
-
170
- it "gets inline fragments without type conditions" do
171
- assert_equal nil, typeless_inline_fragment.type
172
- assert_equal 1, typeless_inline_fragment.selections.length
173
- assert_equal 0, typeless_inline_fragment.directives.length
174
- end
175
-
176
- it "gets position info" do
177
- assert_equal [10, 7], inline_fragment.position
178
- end
179
- end
180
-
181
- describe "inputs" do
182
- let(:query_string) {%|
183
- {
184
- field(
185
- int: 3,
186
- float: 4.7e-24,
187
- bool: false,
188
- string: "☀︎🏆\\n escaped \\" unicode \\u00b6 /",
189
- enum: ENUM_NAME,
190
- array: [7, 8, 9]
191
- object: {a: [1,2,3], b: {c: "4"}}
192
- unicode_bom: "\xef\xbb\xbfquery"
193
- keywordEnum: on
194
- )
195
- }
196
- |}
197
-
198
- let(:inputs) { document.definitions.first.selections.first.arguments }
199
-
200
- it "parses ints" do
201
- assert_equal 3, inputs[0].value
202
- end
203
-
204
- it "parses floats" do
205
- assert_equal 0.47e-23, inputs[1].value
206
- end
207
-
208
- it "parses booleans" do
209
- assert_equal false, inputs[2].value
210
- end
211
-
212
- it "parses UTF-8 strings" do
213
- assert_equal %|☀︎🏆\n escaped " unicode ¶ /|, inputs[3].value
214
- end
215
-
216
- it "parses enums" do
217
- assert_instance_of GraphQL::Language::Nodes::Enum, inputs[4].value
218
- assert_equal "ENUM_NAME", inputs[4].value.name
219
- end
220
-
221
- it "parses arrays" do
222
- assert_equal [7,8,9], inputs[5].value
223
- end
224
-
225
- it "parses objects" do
226
- obj = inputs[6].value
227
- assert_equal "a", obj.arguments[0].name
228
- assert_equal [1,2,3], obj.arguments[0].value
229
- assert_equal "b", obj.arguments[1].name
230
- assert_equal "c", obj.arguments[1].value.arguments[0].name
231
- assert_equal "4", obj.arguments[1].value.arguments[0].value
232
- end
233
-
234
- it "parses unicode bom" do
235
- obj = inputs[7].value
236
- assert_equal %|\xef\xbb\xbfquery|, inputs[7].value
237
- end
238
-
239
- it "parses enum 'on''" do
240
- assert_equal "on", inputs[8].value.name
241
- end
242
- end
243
- end
244
-
245
- describe "unnamed queries" do
246
- let(:query_string) {%|
247
- { name, age, height }
248
- |}
249
- let(:operation) { document.definitions.first }
250
-
251
- it "parses unnamed queries" do
252
- assert_equal 1, document.definitions.length
253
- assert_equal "query", operation.operation_type
254
- assert_equal nil, operation.name
255
- assert_equal 3, operation.selections.length
256
- end
257
- end
258
-
259
- describe "introspection query" do
260
- let(:query_string) { GraphQL::Introspection::INTROSPECTION_QUERY }
261
-
262
- it "parses a big ol' query" do
263
- assert(document)
264
- end
265
- end
266
-
267
- describe "schema" do
268
- it "parses the test schema" do
269
- schema = DummySchema
270
- schema_string = GraphQL::Schema::Printer.print_schema(schema)
271
- document = GraphQL::Language::Parser.parse(schema_string)
272
-
273
- assert_equal schema_string, document.to_query_string
274
- end
275
-
276
- it "parses mimal schema definition" do
277
- document = GraphQL::Language::Parser.parse('schema { query: QueryRoot }')
278
-
279
- schema = document.definitions.first
280
- assert_equal 'QueryRoot', schema.query
281
- assert_equal nil, schema.mutation
282
- assert_equal nil, schema.subscription
283
- end
284
-
285
- it "parses full schema definitions" do
286
- document = GraphQL::Language::Parser.parse('
287
- schema {
288
- query: QueryRoot
289
- mutation: MutationRoot
290
- subscription: SubscriptionRoot
291
- }
292
- ')
293
-
294
- schema = document.definitions.first
295
- assert_equal 'QueryRoot', schema.query
296
- assert_equal 'MutationRoot', schema.mutation
297
- assert_equal 'SubscriptionRoot', schema.subscription
298
- end
299
-
300
- it "parses object types" do
301
- document = GraphQL::Language::Parser.parse('
302
- type Comment implements Node {
303
- id: ID!
304
- }
305
- ')
306
-
307
- type = document.definitions.first
308
- assert_equal GraphQL::Language::Nodes::ObjectTypeDefinition, type.class
309
- assert_equal 'Comment', type.name
310
- assert_equal ['Node'], type.interfaces
311
- assert_equal ['id'], type.fields.map(&:name)
312
- assert_equal [], type.fields[0].arguments
313
- assert_equal 'ID', type.fields[0].type.of_type.name
314
- end
315
-
316
- it "parses field arguments" do
317
- document = GraphQL::Language::Parser.parse('
318
- type Mutation {
319
- post(id: ID!, data: PostData = { message: "First!1!", type: BLOG, tags: ["Test", "Annoying"] }): Post
320
- }
321
- ')
322
-
323
- field = document.definitions.first.fields.first
324
- assert_equal ['id', 'data'], field.arguments.map(&:name)
325
- data_arg = field.arguments[1]
326
- assert_equal 'PostData', data_arg.type.name
327
- assert_equal ['message', 'type', 'tags'], data_arg.default_value.arguments.map(&:name)
328
- tags_arg = data_arg.default_value.arguments[2]
329
- assert_equal ['Test', 'Annoying'], tags_arg.value
330
- end
331
-
332
- it "parses scalar types" do
333
- document = GraphQL::Language::Parser.parse('scalar DateTime')
334
-
335
- type = document.definitions.first
336
- assert_equal GraphQL::Language::Nodes::ScalarTypeDefinition, type.class
337
- assert_equal 'DateTime', type.name
338
- end
339
-
340
- it "parses interface types" do
341
- document = GraphQL::Language::Parser.parse('
342
- interface Node {
343
- id: ID!
344
- }
345
- ')
346
-
347
- type = document.definitions.first
348
- assert_equal GraphQL::Language::Nodes::InterfaceTypeDefinition, type.class
349
- assert_equal 'Node', type.name
350
- assert_equal ['id'], type.fields.map(&:name)
351
- assert_equal [], type.fields[0].arguments
352
- assert_equal 'ID', type.fields[0].type.of_type.name
353
- end
354
-
355
- it "parses enum types" do
356
- document = GraphQL::Language::Parser.parse('
357
- enum DogCommand { SIT, DOWN, HEEL }
358
- ')
359
-
360
- type = document.definitions.first
361
- assert_equal GraphQL::Language::Nodes::EnumTypeDefinition, type.class
362
- assert_equal 'DogCommand', type.name
363
- assert_equal ['SIT', 'DOWN', 'HEEL'], type.values
364
- end
365
-
366
- it "parses input object types" do
367
- document = GraphQL::Language::Parser.parse('
368
- input EmptyMutationInput {
369
- clientMutationId: String
370
- }
371
- ')
372
-
373
- type = document.definitions.first
374
- assert_equal GraphQL::Language::Nodes::InputObjectTypeDefinition, type.class
375
- assert_equal 'EmptyMutationInput', type.name
376
- assert_equal ['clientMutationId'], type.fields.map(&:name)
377
- assert_equal 'String', type.fields[0].type.name
378
- assert_equal nil, type.fields[0].default_value
379
- end
380
- end
381
- end
382
-
383
- describe "errors" do
384
- let(:query_string) {%| query doSomething { bogus { } |}
385
- it "raises a parse error" do
386
- err = assert_raises(GraphQL::ParseError) { document }
387
- end
388
-
389
- it "correctly identifies parse error location and content" do
390
- e = assert_raises(GraphQL::ParseError) do
391
- GraphQL.parse("
392
- query getCoupons {
393
- allCoupons: {data{id}}
394
- }
395
- ")
396
- end
397
- assert_includes(e.message, '"{"')
398
- assert_includes(e.message, "RCURLY")
399
- assert_equal(3, e.line)
400
- assert_equal(25, e.col)
401
- end
402
-
403
- it "handles unexpected ends" do
404
- err = assert_raises(GraphQL::ParseError) { GraphQL.parse("{ ") }
405
- assert_equal "Unexpected end of document", err.message
406
- end
407
-
408
- it "rejects unsupported characters" do
409
- e = assert_raises(GraphQL::ParseError) do
410
- GraphQL.parse("{ field; }")
411
- end
412
-
413
- assert_includes(e.message, "Parse error on \";\"")
414
- end
415
-
416
- it "rejects control characters" do
417
- e = assert_raises(GraphQL::ParseError) do
418
- GraphQL.parse("{ \afield }")
419
- end
420
-
421
- assert_includes(e.message, "Parse error on \"\\a\"")
422
- end
423
-
424
- it "rejects partial BOM" do
425
- e = assert_raises(GraphQL::ParseError) do
426
- GraphQL.parse("{ \xeffield }")
427
- end
428
-
429
- assert_includes(e.message, "Parse error on \"\\xEF\"")
430
- end
431
-
432
- it "rejects vertical tabs" do
433
- e = assert_raises(GraphQL::ParseError) do
434
- GraphQL.parse("{ \vfield }")
435
- end
436
-
437
- assert_includes(e.message, "Parse error on \"\\v\"")
438
- end
439
-
440
- it "rejects form feed" do
441
- e = assert_raises(GraphQL::ParseError) do
442
- GraphQL.parse("{ \ffield }")
443
- end
444
-
445
- assert_includes(e.message, "Parse error on \"\\f\"")
446
- end
447
-
448
- it "rejects no break space" do
449
- e = assert_raises(GraphQL::ParseError) do
450
- GraphQL.parse("{ \xa0field }")
451
- end
452
-
453
- assert_includes(e.message, "Parse error on \"\\xA0\"")
454
- end
455
-
456
- it "rejects unterminated strings" do
457
- e = assert_raises(GraphQL::ParseError) do
458
- GraphQL.parse("\"")
459
- end
460
-
461
- assert_includes(e.message, "Parse error on \"\\\"\"")
462
-
463
- e = assert_raises(GraphQL::ParseError) do
464
- GraphQL.parse("\"\n\"")
465
- end
466
-
467
- assert_includes(e.message, "Parse error on \"\\n\"")
468
- end
469
-
470
- it "rejects bad escape sequence in strings" do
471
- e = assert_raises(GraphQL::ParseError) do
472
- GraphQL.parse("{ field(arg:\"\\x\") }")
473
- end
474
-
475
- assert_includes(e.message, "Parse error on bad Unicode escape sequence")
476
- end
477
-
478
- it "rejects incomplete escape sequence in strings" do
479
- e = assert_raises(GraphQL::ParseError) do
480
- GraphQL.parse("{ field(arg:\"\\u1\") }")
481
- end
482
-
483
- assert_includes(e.message, "bad Unicode escape sequence")
484
- end
485
-
486
- it "rejects unicode escape with bad chars" do
487
- e = assert_raises(GraphQL::ParseError) do
488
- GraphQL.parse("{ field(arg:\"\\u0XX1\") }")
489
- end
490
-
491
- assert_includes(e.message, "bad Unicode escape sequence")
492
-
493
- e = assert_raises(GraphQL::ParseError) do
494
- GraphQL.parse("{ field(arg:\"\\uXXXX\") }")
495
- end
496
-
497
- assert_includes(e.message, "bad Unicode escape sequence")
498
-
499
-
500
- e = assert_raises(GraphQL::ParseError) do
501
- GraphQL.parse("{ field(arg:\"\\uFXXX\") }")
502
- end
503
-
504
- assert_includes(e.message, "bad Unicode escape sequence")
505
-
506
-
507
- e = assert_raises(GraphQL::ParseError) do
508
- GraphQL.parse("{ field(arg:\"\\uXXXF\") }")
509
- end
510
-
511
- assert_includes(e.message, "bad Unicode escape sequence")
512
- end
513
-
514
- it "rejects fragments named 'on'" do
515
- e = assert_raises(GraphQL::ParseError) do
516
- GraphQL.parse("fragment on on on { on }")
517
- end
518
-
519
- assert_includes(e.message, "Parse error on \"on\"")
520
- end
521
-
522
- it "rejects fragment spread of 'on'" do
523
- e = assert_raises(GraphQL::ParseError) do
524
- GraphQL.parse("{ ...on }")
525
- end
526
-
527
- assert_includes(e.message, "Parse error on \"}\"")
528
- end
529
-
530
- it "rejects null value" do
531
- e = assert_raises(GraphQL::ParseError) do
532
- GraphQL.parse("{ fieldWithNullableStringInput(input: null) }")
533
- end
534
-
535
- assert_includes(e.message, "Parse error on \"null\"")
536
- end
537
- end
538
-
539
-
540
- describe "whitespace" do
541
- describe "whitespace-only queries" do
542
- let(:query_string) { " " }
543
- it "doesn't blow up" do
544
- assert_equal [], document.definitions
545
- end
546
- end
547
-
548
- describe "empty string queries" do
549
- let(:query_string) { "" }
550
- it "doesn't blow up" do
551
- assert_equal [], document.definitions
552
- end
553
- end
554
-
555
- describe "using tabs as whitespace" do
556
- let(:query_string) { "\t{\t\tid, \tname}"}
557
- it "parses the query" do
558
- assert_equal 1, document.definitions.length
559
- end
560
- end
561
- end
5
+ include GraphQL::Language::ParserTests
6
+ subject { GraphQL::Language::Parser }
562
7
  end