1from textwrap import dedent
2from typing import List, Optional, Tuple
3
4from pytest import raises
5
6from graphql.error import GraphQLSyntaxError
7from graphql.language import (
8    ArgumentNode,
9    BooleanValueNode,
10    DirectiveDefinitionNode,
11    DirectiveNode,
12    DocumentNode,
13    EnumTypeDefinitionNode,
14    EnumValueDefinitionNode,
15    FieldDefinitionNode,
16    InputObjectTypeDefinitionNode,
17    InputValueDefinitionNode,
18    InterfaceTypeDefinitionNode,
19    InterfaceTypeExtensionNode,
20    ListTypeNode,
21    NameNode,
22    NamedTypeNode,
23    NonNullTypeNode,
24    ObjectTypeDefinitionNode,
25    ObjectTypeExtensionNode,
26    OperationType,
27    OperationTypeDefinitionNode,
28    ScalarTypeDefinitionNode,
29    SchemaDefinitionNode,
30    SchemaExtensionNode,
31    StringValueNode,
32    TypeNode,
33    UnionTypeDefinitionNode,
34    ValueNode,
35    parse,
36)
37
38from ..fixtures import kitchen_sink_sdl  # noqa: F401
39
40Location = Optional[Tuple[int, int]]
41
42
43def assert_syntax_error(text: str, message: str, location: Location) -> None:
44    with raises(GraphQLSyntaxError) as exc_info:
45        parse(text)
46    error = exc_info.value
47    assert error.message == f"Syntax Error: {message}"
48    assert error.description == message
49    assert error.locations == [location]
50
51
52def assert_definitions(body: str, loc: Location, num=1):
53    doc = parse(body)
54    assert isinstance(doc, DocumentNode)
55    assert doc.loc == loc
56    definitions = doc.definitions
57    assert isinstance(definitions, list)
58    assert len(definitions) == num
59    return definitions[0] if num == 1 else definitions
60
61
62def type_node(name: str, loc: Location):
63    return NamedTypeNode(name=name_node(name, loc), loc=loc)
64
65
66def name_node(name: str, loc: Location):
67    return NameNode(value=name, loc=loc)
68
69
70def field_node(name: NameNode, type_: TypeNode, loc: Location):
71    return field_node_with_args(name, type_, [], loc)
72
73
74def field_node_with_args(name: NameNode, type_: TypeNode, args: List, loc: Location):
75    return FieldDefinitionNode(
76        name=name, arguments=args, type=type_, directives=[], loc=loc, description=None
77    )
78
79
80def non_null_type(type_: TypeNode, loc: Location):
81    return NonNullTypeNode(type=type_, loc=loc)
82
83
84def enum_value_node(name: str, loc: Location):
85    return EnumValueDefinitionNode(
86        name=name_node(name, loc), directives=[], loc=loc, description=None
87    )
88
89
90def input_value_node(
91    name: NameNode, type_: TypeNode, default_value: Optional[ValueNode], loc: Location
92):
93    return InputValueDefinitionNode(
94        name=name,
95        type=type_,
96        default_value=default_value,
97        directives=[],
98        loc=loc,
99        description=None,
100    )
101
102
103def boolean_value_node(value: bool, loc: Location):
104    return BooleanValueNode(value=value, loc=loc)
105
106
107def string_value_node(value: str, block: Optional[bool], loc: Location):
108    return StringValueNode(value=value, block=block, loc=loc)
109
110
111def list_type_node(type_: TypeNode, loc: Location):
112    return ListTypeNode(type=type_, loc=loc)
113
114
115def schema_extension_node(
116    directives: List[DirectiveNode],
117    operation_types: List[OperationTypeDefinitionNode],
118    loc: Location,
119):
120    return SchemaExtensionNode(
121        directives=directives, operation_types=operation_types, loc=loc
122    )
123
124
125def operation_type_definition(operation: OperationType, type_: TypeNode, loc: Location):
126    return OperationTypeDefinitionNode(operation=operation, type=type_, loc=loc)
127
128
129def directive_node(name: NameNode, arguments: List[ArgumentNode], loc: Location):
130    return DirectiveNode(name=name, arguments=arguments, loc=loc)
131
132
133def describe_schema_parser():
134    def simple_type():
135        body = dedent(
136            """
137            type Hello {
138              world: String
139            }
140            """
141        )
142        definition = assert_definitions(body, (0, 32))
143        assert isinstance(definition, ObjectTypeDefinitionNode)
144        assert definition.name == name_node("Hello", (6, 11))
145        assert definition.description is None
146        assert definition.interfaces == []
147        assert definition.directives == []
148        assert definition.fields == [
149            field_node(
150                name_node("world", (16, 21)), type_node("String", (23, 29)), (16, 29)
151            )
152        ]
153        assert definition.loc == (1, 31)
154
155    def parses_type_with_description_string():
156        body = dedent(
157            """
158            "Description"
159            type Hello {
160              world: String
161            }
162            """
163        )
164        definition = assert_definitions(body, (0, 46))
165        assert isinstance(definition, ObjectTypeDefinitionNode)
166        assert definition.name == name_node("Hello", (20, 25))
167        description = definition.description
168        assert description == string_value_node("Description", False, (1, 14))
169
170    def parses_type_with_description_multi_line_string():
171        body = dedent(
172            '''
173            """
174            Description
175            """
176            # Even with comments between them
177            type Hello {
178              world: String
179            }'''
180        )
181        definition = assert_definitions(body, (0, 85))
182        assert isinstance(definition, ObjectTypeDefinitionNode)
183        assert definition.name == name_node("Hello", (60, 65))
184        description = definition.description
185        assert description == string_value_node("Description", True, (1, 20))
186
187    def parses_schema_with_description_string():
188        body = dedent(
189            """
190            "Description"
191            schema {
192              query: Foo
193            }
194            """
195        )
196        definition = assert_definitions(body, (0, 39))
197        assert isinstance(definition, SchemaDefinitionNode)
198        description = definition.description
199        assert description == string_value_node("Description", False, (1, 14))
200
201    def description_followed_by_something_other_than_type_system_definition_throws():
202        assert_syntax_error('"Description" 1', "Unexpected Int '1'.", (1, 15))
203
204    def simple_extension():
205        body = dedent(
206            """
207            extend type Hello {
208              world: String
209            }
210            """
211        )
212        extension = assert_definitions(body, (0, 39))
213        assert isinstance(extension, ObjectTypeExtensionNode)
214        assert extension.name == name_node("Hello", (13, 18))
215        assert extension.interfaces == []
216        assert extension.directives == []
217        assert extension.fields == [
218            field_node(
219                name_node("world", (23, 28)), type_node("String", (30, 36)), (23, 36)
220            )
221        ]
222        assert extension.loc == (1, 38)
223
224    def object_extension_without_fields():
225        body = "extend type Hello implements Greeting"
226        extension = assert_definitions(body, (0, 37))
227        assert isinstance(extension, ObjectTypeExtensionNode)
228        assert extension.name == name_node("Hello", (12, 17))
229        assert extension.interfaces == [type_node("Greeting", (29, 37))]
230        assert extension.directives == []
231        assert extension.fields == []
232        assert extension.loc == (0, 37)
233
234    def interface_extension_without_fields():
235        body = "extend interface Hello implements Greeting"
236        extension = assert_definitions(body, (0, 42))
237        assert isinstance(extension, InterfaceTypeExtensionNode)
238        assert extension.name == name_node("Hello", (17, 22))
239        assert extension.interfaces == [type_node("Greeting", (34, 42))]
240        assert extension.directives == []
241        assert extension.fields == []
242        assert extension.loc == (0, 42)
243
244    def object_extension_without_fields_followed_by_extension():
245        body = (
246            "\n      extend type Hello implements Greeting\n\n"
247            "      extend type Hello implements SecondGreeting\n    "
248        )
249        extensions = assert_definitions(body, (0, 100), 2)
250        extension = extensions[0]
251        assert isinstance(extension, ObjectTypeExtensionNode)
252        assert extension.name == name_node("Hello", (19, 24))
253        assert extension.interfaces == [type_node("Greeting", (36, 44))]
254        assert extension.directives == []
255        assert extension.fields == []
256        assert extension.loc == (7, 44)
257        extension = extensions[1]
258        assert isinstance(extension, ObjectTypeExtensionNode)
259        assert extension.name == name_node("Hello", (64, 69))
260        assert extension.interfaces == [type_node("SecondGreeting", (81, 95))]
261        assert extension.directives == []
262        assert extension.fields == []
263        assert extension.loc == (52, 95)
264
265    def extension_without_anything_throws():
266        assert_syntax_error("extend scalar Hello", "Unexpected <EOF>.", (1, 20))
267        assert_syntax_error("extend type Hello", "Unexpected <EOF>.", (1, 18))
268        assert_syntax_error("extend interface Hello", "Unexpected <EOF>.", (1, 23))
269        assert_syntax_error("extend union Hello", "Unexpected <EOF>.", (1, 19))
270        assert_syntax_error("extend enum Hello", "Unexpected <EOF>.", (1, 18))
271        assert_syntax_error("extend input Hello", "Unexpected <EOF>.", (1, 19))
272
273    def interface_extension_without_fields_followed_by_extension():
274        body = (
275            "\n      extend interface Hello implements Greeting\n\n"
276            "      extend interface Hello implements SecondGreeting\n    "
277        )
278        extensions = assert_definitions(body, (0, 110), 2)
279        extension = extensions[0]
280        assert isinstance(extension, InterfaceTypeExtensionNode)
281        assert extension.name == name_node("Hello", (24, 29))
282        assert extension.interfaces == [type_node("Greeting", (41, 49))]
283        assert extension.directives == []
284        assert extension.fields == []
285        assert extension.loc == (7, 49)
286        extension = extensions[1]
287        assert isinstance(extension, InterfaceTypeExtensionNode)
288        assert extension.name == name_node("Hello", (74, 79))
289        assert extension.interfaces == [type_node("SecondGreeting", (91, 105))]
290        assert extension.directives == []
291        assert extension.fields == []
292        assert extension.loc == (57, 105)
293
294    def object_extension_do_not_include_descriptions():
295        assert_syntax_error(
296            """
297            "Description"
298            extend type Hello {
299              world: String
300            }""",
301            "Unexpected Name 'extend'.",
302            (3, 13),
303        )
304        assert_syntax_error(
305            """
306            extend "Description" type Hello {
307              world: String
308            }""",
309            "Unexpected String 'Description'.",
310            (2, 20),
311        )
312
313    def interface_extension_do_not_include_descriptions():
314        assert_syntax_error(
315            """
316            "Description"
317            extend interface Hello {
318              world: String
319            }""",
320            "Unexpected Name 'extend'.",
321            (3, 13),
322        )
323        assert_syntax_error(
324            """
325            extend "Description" interface Hello {
326              world: String
327            }""",
328            "Unexpected String 'Description'.",
329            (2, 20),
330        )
331
332    def schema_extension():
333        body = """
334            extend schema {
335              mutation: Mutation
336            }"""
337        doc = parse(body)
338        assert isinstance(doc, DocumentNode)
339        assert doc.loc == (0, 75)
340        assert doc.definitions == [
341            schema_extension_node(
342                [],
343                [
344                    operation_type_definition(
345                        OperationType.MUTATION,
346                        type_node("Mutation", (53, 61)),
347                        (43, 61),
348                    )
349                ],
350                (13, 75),
351            )
352        ]
353
354    def schema_extension_with_only_directives():
355        body = "extend schema @directive"
356        doc = parse(body)
357        assert isinstance(doc, DocumentNode)
358        assert doc.loc == (0, 24)
359        assert doc.definitions == [
360            schema_extension_node(
361                [directive_node(name_node("directive", (15, 24)), [], (14, 24))],
362                [],
363                (0, 24),
364            )
365        ]
366
367    def schema_extension_without_anything_throws():
368        assert_syntax_error("extend schema", "Unexpected <EOF>.", (1, 14))
369
370    def schema_extension_with_invalid_operation_type_throws():
371        assert_syntax_error(
372            "extend schema { unknown: SomeType }", "Unexpected Name 'unknown'.", (1, 17)
373        )
374
375    def simple_non_null_type():
376        body = dedent(
377            """
378            type Hello {
379              world: String!
380            }
381            """
382        )
383        definition = assert_definitions(body, (0, 33))
384        assert isinstance(definition, ObjectTypeDefinitionNode)
385        assert definition.name == name_node("Hello", (6, 11))
386        assert definition.description is None
387        assert definition.interfaces == []
388        assert definition.directives == []
389        assert definition.fields == [
390            field_node(
391                name_node("world", (16, 21)),
392                non_null_type(type_node("String", (23, 29)), (23, 30)),
393                (16, 30),
394            )
395        ]
396        assert definition.loc == (1, 32)
397
398    def simple_interface_inheriting_interface():
399        body = "interface Hello implements World { field: String }"
400        definition = assert_definitions(body, (0, 50))
401        assert isinstance(definition, InterfaceTypeDefinitionNode)
402        assert definition.name == name_node("Hello", (10, 15))
403        assert definition.description is None
404        assert definition.interfaces == [type_node("World", (27, 32))]
405        assert definition.directives == []
406        assert definition.fields == [
407            field_node(
408                name_node("field", (35, 40)), type_node("String", (42, 48)), (35, 48)
409            )
410        ]
411        assert definition.loc == (0, 50)
412
413    def simple_type_inheriting_interface():
414        body = "type Hello implements World { field: String }"
415        definition = assert_definitions(body, (0, 45))
416        assert isinstance(definition, ObjectTypeDefinitionNode)
417        assert definition.name == name_node("Hello", (5, 10))
418        assert definition.description is None
419        assert definition.interfaces == [type_node("World", (22, 27))]
420        assert definition.directives == []
421        assert definition.fields == [
422            field_node(
423                name_node("field", (30, 35)), type_node("String", (37, 43)), (30, 43)
424            )
425        ]
426        assert definition.loc == (0, 45)
427
428    def simple_type_inheriting_multiple_interfaces():
429        body = "type Hello implements Wo & rld { field: String }"
430        definition = assert_definitions(body, (0, 48))
431        assert isinstance(definition, ObjectTypeDefinitionNode)
432        assert definition.name == name_node("Hello", (5, 10))
433        assert definition.description is None
434        assert definition.interfaces == [
435            type_node("Wo", (22, 24)),
436            type_node("rld", (27, 30)),
437        ]
438        assert definition.directives == []
439        assert definition.fields == [
440            field_node(
441                name_node("field", (33, 38)), type_node("String", (40, 46)), (33, 46)
442            )
443        ]
444        assert definition.loc == (0, 48)
445
446    def simple_interface_inheriting_multiple_interfaces():
447        body = "interface Hello implements Wo & rld { field: String }"
448        definition = assert_definitions(body, (0, 53))
449        assert isinstance(definition, InterfaceTypeDefinitionNode)
450        assert definition.name == name_node("Hello", (10, 15))
451        assert definition.description is None
452        assert definition.interfaces == [
453            type_node("Wo", (27, 29)),
454            type_node("rld", (32, 35)),
455        ]
456        assert definition.directives == []
457        assert definition.fields == [
458            field_node(
459                name_node("field", (38, 43)), type_node("String", (45, 51)), (38, 51)
460            )
461        ]
462        assert definition.loc == (0, 53)
463
464    def simple_type_inheriting_multiple_interfaces_with_leading_ampersand():
465        body = "type Hello implements & Wo & rld { field: String }"
466        definition = assert_definitions(body, (0, 50))
467        assert isinstance(definition, ObjectTypeDefinitionNode)
468        assert definition.name == name_node("Hello", (5, 10))
469        assert definition.description is None
470        assert definition.interfaces == [
471            type_node("Wo", (24, 26)),
472            type_node("rld", (29, 32)),
473        ]
474        assert definition.directives == []
475        assert definition.fields == [
476            field_node(
477                name_node("field", (35, 40)), type_node("String", (42, 48)), (35, 48)
478            )
479        ]
480        assert definition.loc == (0, 50)
481
482    def simple_interface_inheriting_multiple_interfaces_with_leading_ampersand():
483        body = "interface Hello implements & Wo & rld { field: String }"
484        definition = assert_definitions(body, (0, 55))
485        assert isinstance(definition, InterfaceTypeDefinitionNode)
486        assert definition.name == name_node("Hello", (10, 15))
487        assert definition.description is None
488        assert definition.interfaces == [
489            type_node("Wo", (29, 31)),
490            type_node("rld", (34, 37)),
491        ]
492        assert definition.directives == []
493        assert definition.fields == [
494            field_node(
495                name_node("field", (40, 45)), type_node("String", (47, 53)), (40, 53)
496            )
497        ]
498        assert definition.loc == (0, 55)
499
500    def single_value_enum():
501        body = "enum Hello { WORLD }"
502        definition = assert_definitions(body, (0, 20))
503        assert isinstance(definition, EnumTypeDefinitionNode)
504        assert definition.name == name_node("Hello", (5, 10))
505        assert definition.description is None
506        assert definition.directives == []
507        assert definition.values == [enum_value_node("WORLD", (13, 18))]
508        assert definition.loc == (0, 20)
509
510    def double_value_enum():
511        body = "enum Hello { WO, RLD }"
512        definition = assert_definitions(body, (0, 22))
513        assert isinstance(definition, EnumTypeDefinitionNode)
514        assert definition.name == name_node("Hello", (5, 10))
515        assert definition.description is None
516        assert definition.directives == []
517        assert definition.values == [
518            enum_value_node("WO", (13, 15)),
519            enum_value_node("RLD", (17, 20)),
520        ]
521        assert definition.loc == (0, 22)
522
523    def simple_interface():
524        body = dedent(
525            """
526            interface Hello {
527              world: String
528            }
529            """
530        )
531        definition = assert_definitions(body, (0, 37))
532        assert isinstance(definition, InterfaceTypeDefinitionNode)
533        assert definition.name == name_node("Hello", (11, 16))
534        assert definition.description is None
535        assert definition.interfaces == []
536        assert definition.directives == []
537        assert definition.fields == [
538            field_node(
539                name_node("world", (21, 26)), type_node("String", (28, 34)), (21, 34)
540            )
541        ]
542        assert definition.loc == (1, 36)
543
544    def simple_field_with_arg():
545        body = dedent(
546            """
547            type Hello {
548              world(flag: Boolean): String
549            }
550            """
551        )
552        definition = assert_definitions(body, (0, 47))
553        assert isinstance(definition, ObjectTypeDefinitionNode)
554        assert definition.name == name_node("Hello", (6, 11))
555        assert definition.description is None
556        assert definition.interfaces == []
557        assert definition.directives == []
558        assert definition.fields == [
559            field_node_with_args(
560                name_node("world", (16, 21)),
561                type_node("String", (38, 44)),
562                [
563                    input_value_node(
564                        name_node("flag", (22, 26)),
565                        type_node("Boolean", (28, 35)),
566                        None,
567                        (22, 35),
568                    )
569                ],
570                (16, 44),
571            )
572        ]
573        assert definition.loc == (1, 46)
574
575    def simple_field_with_arg_with_default_value():
576        body = dedent(
577            """
578            type Hello {
579              world(flag: Boolean = true): String
580            }
581            """
582        )
583        definition = assert_definitions(body, (0, 54))
584        assert isinstance(definition, ObjectTypeDefinitionNode)
585        assert definition.name == name_node("Hello", (6, 11))
586        assert definition.description is None
587        assert definition.interfaces == []
588        assert definition.directives == []
589        assert definition.fields == [
590            field_node_with_args(
591                name_node("world", (16, 21)),
592                type_node("String", (45, 51)),
593                [
594                    input_value_node(
595                        name_node("flag", (22, 26)),
596                        type_node("Boolean", (28, 35)),
597                        boolean_value_node(True, (38, 42)),
598                        (22, 42),
599                    )
600                ],
601                (16, 51),
602            )
603        ]
604        assert definition.loc == (1, 53)
605
606    def simple_field_with_list_arg():
607        body = dedent(
608            """
609            type Hello {
610              world(things: [String]): String
611            }
612            """
613        )
614        definition = assert_definitions(body, (0, 50))
615        assert isinstance(definition, ObjectTypeDefinitionNode)
616        assert definition.name == name_node("Hello", (6, 11))
617        assert definition.description is None
618        assert definition.interfaces == []
619        assert definition.directives == []
620        assert definition.fields == [
621            field_node_with_args(
622                name_node("world", (16, 21)),
623                type_node("String", (41, 47)),
624                [
625                    input_value_node(
626                        name_node("things", (22, 28)),
627                        list_type_node(type_node("String", (31, 37)), (30, 38)),
628                        None,
629                        (22, 38),
630                    )
631                ],
632                (16, 47),
633            )
634        ]
635        assert definition.loc == (1, 49)
636
637    def simple_field_with_two_args():
638        body = dedent(
639            """
640          type Hello {
641            world(argOne: Boolean, argTwo: Int): String
642          }
643          """
644        )
645        definition = assert_definitions(body, (0, 62))
646        assert isinstance(definition, ObjectTypeDefinitionNode)
647        assert definition.name == name_node("Hello", (6, 11))
648        assert definition.description is None
649        assert definition.interfaces == []
650        assert definition.directives == []
651        assert definition.fields == [
652            field_node_with_args(
653                name_node("world", (16, 21)),
654                type_node("String", (53, 59)),
655                [
656                    input_value_node(
657                        name_node("argOne", (22, 28)),
658                        type_node("Boolean", (30, 37)),
659                        None,
660                        (22, 37),
661                    ),
662                    input_value_node(
663                        name_node("argTwo", (39, 45)),
664                        type_node("Int", (47, 50)),
665                        None,
666                        (39, 50),
667                    ),
668                ],
669                (16, 59),
670            )
671        ]
672        assert definition.loc == (1, 61)
673
674    def simple_union():
675        body = "union Hello = World"
676        definition = assert_definitions(body, (0, 19))
677        assert isinstance(definition, UnionTypeDefinitionNode)
678        assert definition.name == name_node("Hello", (6, 11))
679        assert definition.description is None
680        assert definition.directives == []
681        assert definition.types == [type_node("World", (14, 19))]
682        assert definition.loc == (0, 19)
683
684    def union_with_two_types():
685        body = "union Hello = Wo | Rld"
686        definition = assert_definitions(body, (0, 22))
687        assert isinstance(definition, UnionTypeDefinitionNode)
688        assert definition.name == name_node("Hello", (6, 11))
689        assert definition.description is None
690        assert definition.directives == []
691        assert definition.types == [
692            type_node("Wo", (14, 16)),
693            type_node("Rld", (19, 22)),
694        ]
695        assert definition.loc == (0, 22)
696
697    def union_with_two_types_and_leading_pipe():
698        body = "union Hello = | Wo | Rld"
699        definition = assert_definitions(body, (0, 24))
700        assert isinstance(definition, UnionTypeDefinitionNode)
701        assert definition.name == name_node("Hello", (6, 11))
702        assert definition.directives == []
703        assert definition.types == [
704            type_node("Wo", (16, 18)),
705            type_node("Rld", (21, 24)),
706        ]
707        assert definition.loc == (0, 24)
708
709    def union_fails_with_no_types():
710        assert_syntax_error("union Hello = |", "Expected Name, found <EOF>.", (1, 16))
711
712    def union_fails_with_leading_double_pipe():
713        assert_syntax_error(
714            "union Hello = || Wo | Rld", "Expected Name, found '|'.", (1, 16)
715        )
716
717    def union_fails_with_double_pipe():
718        assert_syntax_error(
719            "union Hello = Wo || Rld", "Expected Name, found '|'.", (1, 19)
720        )
721
722    def union_fails_with_trailing_pipe():
723        assert_syntax_error(
724            "union Hello = | Wo | Rld |", "Expected Name, found <EOF>.", (1, 27)
725        )
726
727    def scalar():
728        body = "scalar Hello"
729        definition = assert_definitions(body, (0, 12))
730        assert isinstance(definition, ScalarTypeDefinitionNode)
731        assert definition.name == name_node("Hello", (7, 12))
732        assert definition.description is None
733        assert definition.directives == []
734        assert definition.loc == (0, 12)
735
736    def simple_input_object():
737        body = "\ninput Hello {\n  world: String\n}"
738        definition = assert_definitions(body, (0, 32))
739        assert isinstance(definition, InputObjectTypeDefinitionNode)
740        assert definition.name == name_node("Hello", (7, 12))
741        assert definition.description is None
742        assert definition.directives == []
743        assert definition.fields == [
744            input_value_node(
745                name_node("world", (17, 22)),
746                type_node("String", (24, 30)),
747                None,
748                (17, 30),
749            )
750        ]
751        assert definition.loc == (1, 32)
752
753    def simple_input_object_with_args_should_fail():
754        assert_syntax_error(
755            "\ninput Hello {\n  world(foo : Int): String\n}",
756            "Expected ':', found '('.",
757            (3, 8),
758        )
759
760    def directive_definition():
761        body = "directive @foo on OBJECT | INTERFACE"
762        definition = assert_definitions(body, (0, 36))
763        assert isinstance(definition, DirectiveDefinitionNode)
764        assert definition.name == name_node("foo", (11, 14))
765        assert definition.description is None
766        assert definition.arguments == []
767        assert definition.repeatable is False
768        assert definition.locations == [
769            name_node("OBJECT", (18, 24)),
770            name_node("INTERFACE", (27, 36)),
771        ]
772
773    def repeatable_directive_definition():
774        body = "directive @foo repeatable on OBJECT | INTERFACE"
775        definition = assert_definitions(body, (0, 47))
776        assert isinstance(definition, DirectiveDefinitionNode)
777        assert definition.name == name_node("foo", (11, 14))
778        assert definition.description is None
779        assert definition.arguments == []
780        assert definition.repeatable is True
781        assert definition.locations == [
782            name_node("OBJECT", (29, 35)),
783            name_node("INTERFACE", (38, 47)),
784        ]
785
786    def directive_with_incorrect_locations():
787        assert_syntax_error(
788            "\ndirective @foo on FIELD | INCORRECT_LOCATION",
789            "Unexpected Name 'INCORRECT_LOCATION'.",
790            (2, 27),
791        )
792
793    def parses_kitchen_sink_schema(kitchen_sink_sdl):  # noqa: F811
794        assert parse(kitchen_sink_sdl)
795
796    def disallow_legacy_sdl_empty_fields_supports_type_with_empty_fields():
797        assert_syntax_error("type Hello { }", "Expected Name, found '}'.", (1, 14))
798
799    def disallow_legacy_sdl_implements_interfaces():
800        assert_syntax_error(
801            "type Hello implements Wo rld { field: String }",
802            "Unexpected Name 'rld'.",
803            (1, 26),
804        )
805