graphql 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql.rb +10 -0
  3. data/lib/graphql/base_type.rb +8 -5
  4. data/lib/graphql/compatibility.rb +3 -0
  5. data/lib/graphql/compatibility/execution_specification.rb +414 -0
  6. data/lib/graphql/compatibility/query_parser_specification.rb +117 -0
  7. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +81 -0
  8. data/lib/graphql/compatibility/query_parser_specification/query_assertions.rb +78 -0
  9. data/lib/graphql/compatibility/schema_parser_specification.rb +239 -0
  10. data/lib/graphql/define/instance_definable.rb +53 -21
  11. data/lib/graphql/directive.rb +1 -1
  12. data/lib/graphql/enum_type.rb +31 -8
  13. data/lib/graphql/execution/directive_checks.rb +0 -6
  14. data/lib/graphql/input_object_type.rb +6 -4
  15. data/lib/graphql/introspection/arguments_field.rb +3 -1
  16. data/lib/graphql/introspection/enum_values_field.rb +10 -5
  17. data/lib/graphql/introspection/fields_field.rb +1 -1
  18. data/lib/graphql/introspection/input_fields_field.rb +2 -2
  19. data/lib/graphql/introspection/interfaces_field.rb +7 -1
  20. data/lib/graphql/introspection/possible_types_field.rb +1 -1
  21. data/lib/graphql/introspection/schema_type.rb +1 -1
  22. data/lib/graphql/introspection/type_by_name_field.rb +4 -2
  23. data/lib/graphql/introspection/type_type.rb +7 -6
  24. data/lib/graphql/language/lexer.rl +0 -4
  25. data/lib/graphql/language/parser.rb +1 -1
  26. data/lib/graphql/language/parser.y +1 -1
  27. data/lib/graphql/list_type.rb +3 -4
  28. data/lib/graphql/non_null_type.rb +4 -8
  29. data/lib/graphql/object_type.rb +5 -3
  30. data/lib/graphql/query.rb +48 -12
  31. data/lib/graphql/query/context.rb +7 -1
  32. data/lib/graphql/query/serial_execution/execution_context.rb +8 -3
  33. data/lib/graphql/query/serial_execution/field_resolution.rb +8 -5
  34. data/lib/graphql/query/serial_execution/operation_resolution.rb +2 -2
  35. data/lib/graphql/query/serial_execution/selection_resolution.rb +4 -21
  36. data/lib/graphql/query/serial_execution/value_resolution.rb +59 -99
  37. data/lib/graphql/query/variables.rb +7 -2
  38. data/lib/graphql/scalar_type.rb +1 -1
  39. data/lib/graphql/schema.rb +49 -18
  40. data/lib/graphql/schema/build_from_definition.rb +248 -0
  41. data/lib/graphql/schema/instrumented_field_map.rb +23 -0
  42. data/lib/graphql/schema/loader.rb +4 -11
  43. data/lib/graphql/schema/possible_types.rb +4 -2
  44. data/lib/graphql/schema/printer.rb +1 -1
  45. data/lib/graphql/schema/type_expression.rb +4 -4
  46. data/lib/graphql/schema/type_map.rb +1 -1
  47. data/lib/graphql/schema/validation.rb +4 -0
  48. data/lib/graphql/schema/warden.rb +114 -0
  49. data/lib/graphql/static_validation/literal_validator.rb +10 -7
  50. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -3
  51. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +1 -1
  52. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +1 -1
  53. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -14
  54. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +1 -1
  55. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
  56. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +3 -4
  57. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +2 -1
  58. data/lib/graphql/static_validation/validation_context.rb +7 -1
  59. data/lib/graphql/union_type.rb +6 -3
  60. data/lib/graphql/unresolved_type_error.rb +1 -2
  61. data/lib/graphql/version.rb +1 -1
  62. data/readme.md +1 -5
  63. data/spec/graphql/compatibility/execution_specification_spec.rb +3 -0
  64. data/spec/graphql/compatibility/query_parser_specification_spec.rb +5 -0
  65. data/spec/graphql/compatibility/schema_parser_specification_spec.rb +5 -0
  66. data/spec/graphql/define/instance_definable_spec.rb +20 -0
  67. data/spec/graphql/directive_spec.rb +11 -0
  68. data/spec/graphql/enum_type_spec.rb +20 -1
  69. data/spec/graphql/input_object_type_spec.rb +9 -9
  70. data/spec/graphql/introspection/directive_type_spec.rb +4 -4
  71. data/spec/graphql/introspection/input_value_type_spec.rb +6 -6
  72. data/spec/graphql/introspection/type_type_spec.rb +28 -26
  73. data/spec/graphql/language/parser_spec.rb +27 -17
  74. data/spec/graphql/list_type_spec.rb +2 -2
  75. data/spec/graphql/query/variables_spec.rb +1 -0
  76. data/spec/graphql/scalar_type_spec.rb +3 -3
  77. data/spec/graphql/schema/build_from_definition_spec.rb +693 -0
  78. data/spec/graphql/schema/type_expression_spec.rb +3 -3
  79. data/spec/graphql/schema/validation_spec.rb +7 -3
  80. data/spec/graphql/schema/warden_spec.rb +510 -0
  81. data/spec/graphql/schema_spec.rb +129 -0
  82. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +1 -1
  83. data/spec/graphql/static_validation/type_stack_spec.rb +3 -3
  84. data/spec/spec_helper.rb +27 -1
  85. data/spec/support/dairy_app.rb +8 -5
  86. metadata +21 -3
  87. data/lib/graphql/language/parser_tests.rb +0 -809
@@ -0,0 +1,693 @@
1
+ require "spec_helper"
2
+
3
+ describe GraphQL::Schema::BuildFromDefinition do
4
+ def build_schema_and_compare_output(definition)
5
+ built_schema = GraphQL::Schema.from_definition(definition)
6
+ assert_equal definition, GraphQL::Schema::Printer.print_schema(built_schema)
7
+ end
8
+
9
+ describe '.build' do
10
+ it 'can build a schema with a simple type' do
11
+ schema = <<-SCHEMA
12
+ schema {
13
+ query: HelloScalars
14
+ }
15
+
16
+ type HelloScalars {
17
+ str: String!
18
+ int: Int
19
+ float: Float
20
+ id: ID
21
+ bool: Boolean
22
+ }
23
+ SCHEMA
24
+
25
+ build_schema_and_compare_output(schema.chop)
26
+ end
27
+
28
+ it 'can build a schema with directives' do
29
+ schema = <<-SCHEMA
30
+ schema {
31
+ query: Hello
32
+ }
33
+
34
+ directive @foo(arg: Int) on FIELD
35
+
36
+ type Hello {
37
+ str: String
38
+ }
39
+ SCHEMA
40
+
41
+ build_schema_and_compare_output(schema.chop)
42
+ end
43
+
44
+ it 'supports descriptions' do
45
+ schema = <<-SCHEMA
46
+ schema {
47
+ query: Hello
48
+ }
49
+
50
+ # This is a directive
51
+ directive @foo(
52
+ # It has an argument
53
+ arg: Int
54
+ ) on FIELD
55
+
56
+ # With an enum
57
+ enum Color {
58
+ RED
59
+
60
+ # Not a creative color
61
+ GREEN
62
+ BLUE
63
+ }
64
+
65
+ # What a great type
66
+ type Hello {
67
+ # And a field to boot
68
+ str: String
69
+ }
70
+ SCHEMA
71
+
72
+ build_schema_and_compare_output(schema.chop)
73
+ end
74
+
75
+ it 'maintains built-in directives' do
76
+ schema = <<-SCHEMA
77
+ schema {
78
+ query: Hello
79
+ }
80
+
81
+ type Hello {
82
+ str: String
83
+ }
84
+ SCHEMA
85
+
86
+ built_schema = GraphQL::Schema.from_definition(schema)
87
+ assert_equal ['deprecated', 'include', 'skip'], built_schema.directives.keys.sort
88
+ end
89
+
90
+ it 'supports overriding built-in directives' do
91
+ schema = <<-SCHEMA
92
+ schema {
93
+ query: Hello
94
+ }
95
+
96
+ directive @skip on FIELD
97
+ directive @include on FIELD
98
+ directive @deprecated on FIELD_DEFINITION
99
+
100
+ type Hello {
101
+ str: String
102
+ }
103
+ SCHEMA
104
+
105
+ built_schema = GraphQL::Schema.from_definition(schema)
106
+
107
+ refute built_schema.directives['skip'] == GraphQL::Directive::SkipDirective
108
+ refute built_schema.directives['include'] == GraphQL::Directive::IncludeDirective
109
+ refute built_schema.directives['deprecated'] == GraphQL::Directive::DeprecatedDirective
110
+ end
111
+
112
+ it 'supports adding directives while maintaining built-in directives' do
113
+ schema = <<-SCHEMA
114
+ schema {
115
+ query: Hello
116
+ }
117
+
118
+ directive @foo(arg: Int) on FIELD
119
+
120
+ type Hello {
121
+ str: String
122
+ }
123
+ SCHEMA
124
+
125
+ built_schema = GraphQL::Schema.from_definition(schema)
126
+
127
+ assert built_schema.directives.keys.include?('skip')
128
+ assert built_schema.directives.keys.include?('include')
129
+ assert built_schema.directives.keys.include?('deprecated')
130
+ assert built_schema.directives.keys.include?('foo')
131
+ end
132
+
133
+ it 'supports type modifiers' do
134
+ schema = <<-SCHEMA
135
+ schema {
136
+ query: HelloScalars
137
+ }
138
+
139
+ type HelloScalars {
140
+ nonNullStr: String!
141
+ listOfStrs: [String]
142
+ listOfNonNullStrs: [String!]
143
+ nonNullListOfStrs: [String]!
144
+ nonNullListOfNonNullStrs: [String!]!
145
+ }
146
+ SCHEMA
147
+
148
+ build_schema_and_compare_output(schema.chop)
149
+ end
150
+
151
+ it 'supports recursive type' do
152
+ schema = <<-SCHEMA
153
+ schema {
154
+ query: Recurse
155
+ }
156
+
157
+ type Recurse {
158
+ str: String
159
+ recurse: Recurse
160
+ }
161
+ SCHEMA
162
+
163
+ build_schema_and_compare_output(schema.chop)
164
+ end
165
+
166
+ it 'supports two types circular' do
167
+ schema = <<-SCHEMA
168
+ schema {
169
+ query: TypeOne
170
+ }
171
+
172
+ type TypeOne {
173
+ str: String
174
+ typeTwo: TypeTwo
175
+ }
176
+
177
+ type TypeTwo {
178
+ str: String
179
+ typeOne: TypeOne
180
+ }
181
+ SCHEMA
182
+
183
+ build_schema_and_compare_output(schema.chop)
184
+ end
185
+
186
+ it 'supports single argument fields' do
187
+ schema = <<-SCHEMA
188
+ schema {
189
+ query: Hello
190
+ }
191
+
192
+ type Hello {
193
+ str(int: Int): String
194
+ floatToStr(float: Float): String
195
+ idToStr(id: ID): String
196
+ booleanToStr(bool: Boolean): String
197
+ strToStr(bool: String): String
198
+ }
199
+ SCHEMA
200
+
201
+ build_schema_and_compare_output(schema.chop)
202
+ end
203
+
204
+ it 'supports simple type with multiple arguments' do
205
+ schema = <<-SCHEMA
206
+ schema {
207
+ query: Hello
208
+ }
209
+
210
+ type Hello {
211
+ str(int: Int, bool: Boolean): String
212
+ }
213
+ SCHEMA
214
+
215
+ build_schema_and_compare_output(schema.chop)
216
+ end
217
+
218
+ it 'supports simple type with interface' do
219
+ schema = <<-SCHEMA
220
+ schema {
221
+ query: Hello
222
+ }
223
+
224
+ type Hello implements WorldInterface {
225
+ str: String
226
+ }
227
+
228
+ interface WorldInterface {
229
+ str: String
230
+ }
231
+ SCHEMA
232
+
233
+ build_schema_and_compare_output(schema.chop)
234
+ end
235
+
236
+ it 'supports simple output enum' do
237
+ schema = <<-SCHEMA
238
+ schema {
239
+ query: OutputEnumRoot
240
+ }
241
+
242
+ enum Hello {
243
+ WORLD
244
+ }
245
+
246
+ type OutputEnumRoot {
247
+ hello: Hello
248
+ }
249
+ SCHEMA
250
+
251
+ build_schema_and_compare_output(schema.chop)
252
+ end
253
+
254
+ it 'supports simple input enum' do
255
+ schema = <<-SCHEMA
256
+ schema {
257
+ query: InputEnumRoot
258
+ }
259
+
260
+ enum Hello {
261
+ WORLD
262
+ }
263
+
264
+ type InputEnumRoot {
265
+ str(hello: Hello): String
266
+ }
267
+ SCHEMA
268
+
269
+ build_schema_and_compare_output(schema.chop)
270
+ end
271
+
272
+ it 'supports multiple value enum' do
273
+ schema = <<-SCHEMA
274
+ schema {
275
+ query: OutputEnumRoot
276
+ }
277
+
278
+ enum Hello {
279
+ WO
280
+ RLD
281
+ }
282
+
283
+ type OutputEnumRoot {
284
+ hello: Hello
285
+ }
286
+ SCHEMA
287
+
288
+ build_schema_and_compare_output(schema.chop)
289
+ end
290
+
291
+ it 'supports simple union' do
292
+ schema = <<-SCHEMA
293
+ schema {
294
+ query: Root
295
+ }
296
+
297
+ union Hello = World
298
+
299
+ type Root {
300
+ hello: Hello
301
+ }
302
+
303
+ type World {
304
+ str: String
305
+ }
306
+ SCHEMA
307
+
308
+ build_schema_and_compare_output(schema.chop)
309
+ end
310
+
311
+ it 'supports multiple union' do
312
+ schema = <<-SCHEMA
313
+ schema {
314
+ query: Root
315
+ }
316
+
317
+ union Hello = WorldOne | WorldTwo
318
+
319
+ type Root {
320
+ hello: Hello
321
+ }
322
+
323
+ type WorldOne {
324
+ str: String
325
+ }
326
+
327
+ type WorldTwo {
328
+ str: String
329
+ }
330
+ SCHEMA
331
+
332
+ build_schema_and_compare_output(schema.chop)
333
+ end
334
+
335
+ it 'supports custom scalar' do
336
+ schema = <<-SCHEMA
337
+ schema {
338
+ query: Root
339
+ }
340
+
341
+ scalar CustomScalar
342
+
343
+ type Root {
344
+ customScalar: CustomScalar
345
+ }
346
+ SCHEMA
347
+
348
+ build_schema_and_compare_output(schema.chop)
349
+ end
350
+
351
+ it 'supports input object' do
352
+ schema = <<-SCHEMA
353
+ schema {
354
+ query: Root
355
+ }
356
+
357
+ input Input {
358
+ int: Int
359
+ }
360
+
361
+ type Root {
362
+ field(in: Input): String
363
+ }
364
+ SCHEMA
365
+
366
+ build_schema_and_compare_output(schema.chop)
367
+ end
368
+
369
+ it 'supports simple argument field with default value' do
370
+ schema = <<-SCHEMA
371
+ schema {
372
+ query: Hello
373
+ }
374
+
375
+ enum Color {
376
+ RED
377
+ BLUE
378
+ }
379
+
380
+ type Hello {
381
+ str(int: Int = 2): String
382
+ hello(color: Color = RED): String
383
+ }
384
+ SCHEMA
385
+
386
+ build_schema_and_compare_output(schema.chop)
387
+ end
388
+
389
+ it 'supports simple type with mutation' do
390
+ schema = <<-SCHEMA
391
+ schema {
392
+ query: HelloScalars
393
+ mutation: Mutation
394
+ }
395
+
396
+ type HelloScalars {
397
+ str: String
398
+ int: Int
399
+ bool: Boolean
400
+ }
401
+
402
+ type Mutation {
403
+ addHelloScalars(str: String, int: Int, bool: Boolean): HelloScalars
404
+ }
405
+ SCHEMA
406
+
407
+ build_schema_and_compare_output(schema.chop)
408
+ end
409
+
410
+ it 'supports simple type with mutation and default values' do
411
+ schema = <<-SCHEMA
412
+ enum Color {
413
+ RED
414
+ BLUE
415
+ }
416
+
417
+ type Mutation {
418
+ hello(str: String, int: Int, color: Color = RED): String
419
+ }
420
+
421
+ type Query {
422
+ str: String
423
+ }
424
+ SCHEMA
425
+
426
+ build_schema_and_compare_output(schema.chop)
427
+ end
428
+
429
+ it 'supports simple type with subscription' do
430
+ schema = <<-SCHEMA
431
+ schema {
432
+ query: HelloScalars
433
+ subscription: Subscription
434
+ }
435
+
436
+ type HelloScalars {
437
+ str: String
438
+ int: Int
439
+ bool: Boolean
440
+ }
441
+
442
+ type Subscription {
443
+ subscribeHelloScalars(str: String, int: Int, bool: Boolean): HelloScalars
444
+ }
445
+ SCHEMA
446
+
447
+ build_schema_and_compare_output(schema.chop)
448
+ end
449
+
450
+ it 'supports unreferenced type implementing referenced interface' do
451
+ schema = <<-SCHEMA
452
+ type Concrete implements Iface {
453
+ key: String
454
+ }
455
+
456
+ interface Iface {
457
+ key: String
458
+ }
459
+
460
+ type Query {
461
+ iface: Iface
462
+ }
463
+ SCHEMA
464
+
465
+ build_schema_and_compare_output(schema.chop)
466
+ end
467
+
468
+ it 'supports unreferenced type implementing referenced union' do
469
+ schema = <<-SCHEMA
470
+ type Concrete {
471
+ key: String
472
+ }
473
+
474
+ type Query {
475
+ union: Union
476
+ }
477
+
478
+ union Union = Concrete
479
+ SCHEMA
480
+
481
+ build_schema_and_compare_output(schema.chop)
482
+ end
483
+
484
+ it 'supports @deprecated' do
485
+ schema = <<-SCHEMA
486
+ enum MyEnum {
487
+ VALUE
488
+ OLD_VALUE @deprecated
489
+ OTHER_VALUE @deprecated(reason: "Terrible reasons")
490
+ }
491
+
492
+ type Query {
493
+ field1: String @deprecated
494
+ field2: Int @deprecated(reason: "Because I said so")
495
+ enum: MyEnum
496
+ }
497
+ SCHEMA
498
+
499
+ build_schema_and_compare_output(schema.chop)
500
+ end
501
+ end
502
+
503
+ describe 'Failures' do
504
+ it 'Requires a schema definition or Query type' do
505
+ schema = <<-SCHEMA
506
+ type Hello {
507
+ bar: Bar
508
+ }
509
+ SCHEMA
510
+ err = assert_raises(GraphQL::Schema::InvalidDocumentError) do
511
+ GraphQL::Schema.from_definition(schema)
512
+ end
513
+ assert_equal 'Must provide schema definition with query type or a type named Query.', err.message
514
+ end
515
+
516
+ it 'Allows only a single schema definition' do
517
+ schema = <<-SCHEMA
518
+ schema {
519
+ query: Hello
520
+ }
521
+
522
+ schema {
523
+ query: Hello
524
+ }
525
+
526
+ type Hello {
527
+ bar: Bar
528
+ }
529
+ SCHEMA
530
+
531
+ err = assert_raises(GraphQL::Schema::InvalidDocumentError) do
532
+ GraphQL::Schema.from_definition(schema)
533
+ end
534
+ assert_equal 'Must provide only one schema definition.', err.message
535
+ end
536
+
537
+ it 'Requires a query type' do
538
+ schema = <<-SCHEMA
539
+ schema {
540
+ mutation: Hello
541
+ }
542
+
543
+ type Hello {
544
+ bar: Bar
545
+ }
546
+ SCHEMA
547
+
548
+ err = assert_raises(GraphQL::Schema::InvalidDocumentError) do
549
+ GraphQL::Schema.from_definition(schema)
550
+ end
551
+ assert_equal 'Must provide schema definition with query type or a type named Query.', err.message
552
+ end
553
+
554
+ it 'Unknown type referenced' do
555
+ schema = <<-SCHEMA
556
+ schema {
557
+ query: Hello
558
+ }
559
+
560
+ type Hello {
561
+ bar: Bar
562
+ }
563
+ SCHEMA
564
+
565
+ err = assert_raises(GraphQL::Schema::InvalidDocumentError) do
566
+ GraphQL::Schema.from_definition(schema)
567
+ end
568
+ assert_equal 'Type "Bar" not found in document.', err.message
569
+ end
570
+
571
+ it 'Unknown type in interface list' do
572
+ schema = <<-SCHEMA
573
+ schema {
574
+ query: Hello
575
+ }
576
+
577
+ type Hello implements Bar {
578
+ str: String
579
+ }
580
+ SCHEMA
581
+
582
+ err = assert_raises(GraphQL::Schema::InvalidDocumentError) do
583
+ GraphQL::Schema.from_definition(schema)
584
+ end
585
+ assert_equal 'Type "Bar" not found in document.', err.message
586
+ end
587
+
588
+ it 'Unknown type in union list' do
589
+ schema = <<-SCHEMA
590
+ schema {
591
+ query: Hello
592
+ }
593
+
594
+ union TestUnion = Bar
595
+
596
+ type Hello { testUnion: TestUnion }
597
+ SCHEMA
598
+
599
+ err = assert_raises(GraphQL::Schema::InvalidDocumentError) do
600
+ GraphQL::Schema.from_definition(schema)
601
+ end
602
+ assert_equal 'Type "Bar" not found in document.', err.message
603
+ end
604
+
605
+ it 'Unknown query type' do
606
+ schema = <<-SCHEMA
607
+ schema {
608
+ query: Wat
609
+ }
610
+
611
+ type Hello {
612
+ str: String
613
+ }
614
+ SCHEMA
615
+
616
+ err = assert_raises(GraphQL::Schema::InvalidDocumentError) do
617
+ GraphQL::Schema.from_definition(schema)
618
+ end
619
+ assert_equal 'Specified query type "Wat" not found in document.', err.message
620
+ end
621
+
622
+ it 'Unknown mutation type' do
623
+ schema = <<-SCHEMA
624
+ schema {
625
+ query: Hello
626
+ mutation: Wat
627
+ }
628
+
629
+ type Hello {
630
+ str: String
631
+ }
632
+ SCHEMA
633
+
634
+ err = assert_raises(GraphQL::Schema::InvalidDocumentError) do
635
+ GraphQL::Schema.from_definition(schema)
636
+ end
637
+ assert_equal 'Specified mutation type "Wat" not found in document.', err.message
638
+ end
639
+
640
+ it 'Unknown subscription type' do
641
+ schema = <<-SCHEMA
642
+ schema {
643
+ query: Hello
644
+ mutation: Wat
645
+ subscription: Awesome
646
+ }
647
+
648
+ type Hello {
649
+ str: String
650
+ }
651
+
652
+ type Wat {
653
+ str: String
654
+ }
655
+ SCHEMA
656
+
657
+ err = assert_raises(GraphQL::Schema::InvalidDocumentError) do
658
+ GraphQL::Schema.from_definition(schema)
659
+ end
660
+ assert_equal 'Specified subscription type "Awesome" not found in document.', err.message
661
+ end
662
+
663
+ it 'Does not consider operation names' do
664
+ schema = <<-SCHEMA
665
+ schema {
666
+ query: Foo
667
+ }
668
+
669
+ query Foo { field }
670
+ SCHEMA
671
+
672
+ err = assert_raises(GraphQL::Schema::InvalidDocumentError) do
673
+ GraphQL::Schema.from_definition(schema)
674
+ end
675
+ assert_equal 'Specified query type "Foo" not found in document.', err.message
676
+ end
677
+
678
+ it 'Does not consider fragment names' do
679
+ schema = <<-SCHEMA
680
+ schema {
681
+ query: Foo
682
+ }
683
+
684
+ fragment Foo on Type { field }
685
+ SCHEMA
686
+
687
+ err = assert_raises(GraphQL::Schema::InvalidDocumentError) do
688
+ GraphQL::Schema.from_definition(schema)
689
+ end
690
+ assert_equal 'Specified query type "Foo" not found in document.', err.message
691
+ end
692
+ end
693
+ end