graphql 0.18.5 → 0.18.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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