graphql 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,117 @@
1
+ require "graphql/compatibility/query_parser_specification/query_assertions"
2
+ require "graphql/compatibility/query_parser_specification/parse_error_specification"
3
+
4
+ module GraphQL
5
+ module Compatibility
6
+ # This asserts that a given parse function turns a string into
7
+ # the proper tree of {{GraphQL::Language::Nodes}}.
8
+ module QueryParserSpecification
9
+ # @yieldparam query_string [String] A query string to parse
10
+ # @yieldreturn [GraphQL::Language::Nodes::Document]
11
+ # @return [Class<Minitest::Test>] A test suite for this parse function
12
+ def self.build_suite(&block)
13
+ Class.new(Minitest::Test) do
14
+ include QueryAssertions
15
+ include ParseErrorSpecification
16
+
17
+ @@parse_fn = block
18
+
19
+ def parse(query_string)
20
+ @@parse_fn.call(query_string)
21
+ end
22
+
23
+ def test_it_parses_queries
24
+ document = parse(QUERY_STRING)
25
+ query = document.definitions.first
26
+ assert_valid_query(query)
27
+ assert_valid_fragment(document.definitions.last)
28
+ assert_valid_variable(query.variables.first)
29
+ field = query.selections.first
30
+ assert_valid_field(field)
31
+ assert_valid_variable_argument(field.arguments.first)
32
+ assert_valid_literal_argument(field.arguments.last)
33
+ assert_valid_directive(field.directives.first)
34
+ fragment_spread = query.selections[1].selections.last
35
+ assert_valid_fragment_spread(fragment_spread)
36
+ assert_valid_typed_inline_fragment(query.selections[2])
37
+ assert_valid_typeless_inline_fragment(query.selections[3])
38
+ end
39
+
40
+ def test_it_parses_unnamed_queries
41
+ document = parse("{ name, age, height }")
42
+ operation = document.definitions.first
43
+ assert_equal 1, document.definitions.length
44
+ assert_equal "query", operation.operation_type
45
+ assert_equal nil, operation.name
46
+ assert_equal 3, operation.selections.length
47
+ end
48
+
49
+ def test_it_parses_the_introspection_query
50
+ parse(GraphQL::Introspection::INTROSPECTION_QUERY)
51
+ end
52
+
53
+ def test_it_parses_inputs
54
+ query_string = %|
55
+ {
56
+ field(
57
+ int: 3,
58
+ float: 4.7e-24,
59
+ bool: false,
60
+ string: "☀︎🏆\\n \\" \u00b6 /",
61
+ enum: ENUM_NAME,
62
+ array: [7, 8, 9]
63
+ object: {a: [1,2,3], b: {c: "4"}}
64
+ unicode_bom: "\xef\xbb\xbfquery"
65
+ keywordEnum: on
66
+ )
67
+ }
68
+ |
69
+ document = parse(query_string)
70
+ inputs = document.definitions.first.selections.first.arguments
71
+ assert_equal 3, inputs[0].value, "Integers"
72
+ assert_equal 0.47e-23, inputs[1].value, "Floats"
73
+ assert_equal false, inputs[2].value, "Booleans"
74
+ assert_equal %|☀︎🏆\n " ¶ /|, inputs[3].value, "Strings"
75
+ assert_instance_of GraphQL::Language::Nodes::Enum, inputs[4].value
76
+ assert_equal "ENUM_NAME", inputs[4].value.name, "Enums"
77
+ assert_equal [7,8,9], inputs[5].value, "Lists"
78
+
79
+ obj = inputs[6].value
80
+ assert_equal "a", obj.arguments[0].name
81
+ assert_equal [1,2,3], obj.arguments[0].value
82
+ assert_equal "b", obj.arguments[1].name
83
+ assert_equal "c", obj.arguments[1].value.arguments[0].name
84
+ assert_equal "4", obj.arguments[1].value.arguments[0].value
85
+
86
+ assert_equal %|\xef\xbb\xbfquery|, inputs[7].value, "Unicode BOM"
87
+ assert_equal "on", inputs[8].value.name, "Enum value 'on'"
88
+ end
89
+ end
90
+ end
91
+
92
+ QUERY_STRING = %|
93
+ query getStuff($someVar: Int = 1, $anotherVar: [String!] ) @skip(if: false) {
94
+ myField: someField(someArg: $someVar, ok: 1.4) @skip(if: $anotherVar) @thing(or: "Whatever")
95
+
96
+ anotherField(someArg: [1,2,3]) {
97
+ nestedField
98
+ ... moreNestedFields @skip(if: true)
99
+ }
100
+
101
+ ... on OtherType @include(unless: false){
102
+ field(arg: [{key: "value", anotherKey: 0.9, anotherAnotherKey: WHATEVER}])
103
+ anotherField
104
+ }
105
+
106
+ ... {
107
+ id
108
+ }
109
+ }
110
+
111
+ fragment moreNestedFields on NestedType @or(something: "ok") {
112
+ anotherNestedField @enum(directive: true)
113
+ }
114
+ |
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,81 @@
1
+ module GraphQL
2
+ module Compatibility
3
+ module QueryParserSpecification
4
+ module ParseErrorSpecification
5
+ def assert_raises_parse_error(query_string)
6
+ assert_raises(GraphQL::ParseError) {
7
+ parse(query_string)
8
+ }
9
+ end
10
+
11
+ def test_it_includes_line_and_column
12
+ err = assert_raises_parse_error("
13
+ query getCoupons {
14
+ allCoupons: {data{id}}
15
+ }
16
+ ")
17
+
18
+ assert_includes(err.message, '{')
19
+ assert_equal(3, err.line)
20
+ assert_equal(27, err.col)
21
+ end
22
+
23
+ def test_it_rejects_unterminated_strings
24
+ assert_raises_parse_error('{ " }')
25
+ assert_raises_parse_error(%|{ "\n" }|)
26
+ end
27
+
28
+ def test_it_rejects_unexpected_ends
29
+ assert_raises_parse_error("query { stuff { thing }")
30
+ end
31
+
32
+ def assert_rejects_character(char)
33
+ err = assert_raises_parse_error("{ field#{char} }")
34
+ expected_char = char.inspect.gsub('"', '').downcase
35
+ msg_downcase = err.message.downcase
36
+ # Case-insensitive for UTF-8 printing
37
+ assert_includes(msg_downcase, expected_char, "The message includes the invalid character")
38
+ end
39
+
40
+ def test_it_rejects_invalid_characters
41
+ assert_rejects_character(";")
42
+ assert_rejects_character("\a")
43
+ assert_rejects_character("\xef")
44
+ assert_rejects_character("\v")
45
+ assert_rejects_character("\f")
46
+ assert_rejects_character("\xa0")
47
+ end
48
+
49
+ def test_it_rejects_bad_unicode
50
+ assert_raises_parse_error(%|{ field(arg:"\\x") }|)
51
+ assert_raises_parse_error(%|{ field(arg:"\\u1") }|)
52
+ assert_raises_parse_error(%|{ field(arg:"\\u0XX1") }|)
53
+ assert_raises_parse_error(%|{ field(arg:"\\uXXXX") }|)
54
+ assert_raises_parse_error(%|{ field(arg:"\\uFXXX") }|)
55
+ assert_raises_parse_error(%|{ field(arg:"\\uXXXF") }|)
56
+ end
57
+
58
+ def assert_empty_document(query_string)
59
+ doc = parse(query_string)
60
+ assert_equal 0, doc.definitions.length
61
+ end
62
+
63
+ def test_it_parses_blank_queries
64
+ assert_empty_document("")
65
+ assert_empty_document(" ")
66
+ assert_empty_document("\t \t")
67
+ end
68
+
69
+ def test_it_restricts_on
70
+ assert_raises_parse_error("{ ...on }")
71
+ assert_raises_parse_error("fragment on on Type { field }")
72
+ end
73
+
74
+ def test_it_rejects_null
75
+ err = assert_raises_parse_error("{ field(input: null) }")
76
+ assert_includes(err.message, "null")
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,78 @@
1
+ module GraphQL
2
+ module Compatibility
3
+ module QueryParserSpecification
4
+ module QueryAssertions
5
+ def assert_valid_query(query)
6
+ assert query.is_a?(GraphQL::Language::Nodes::OperationDefinition)
7
+ assert_equal "getStuff", query.name
8
+ assert_equal "query", query.operation_type
9
+ assert_equal 2, query.variables.length
10
+ assert_equal 4, query.selections.length
11
+ assert_equal 1, query.directives.length
12
+ assert_equal [2, 13], [query.line, query.col]
13
+ end
14
+
15
+ def assert_valid_fragment(fragment_def)
16
+ assert fragment_def.is_a?(GraphQL::Language::Nodes::FragmentDefinition)
17
+ assert_equal "moreNestedFields", fragment_def.name
18
+ assert_equal 1, fragment_def.selections.length
19
+ assert_equal "NestedType", fragment_def.type.name
20
+ assert_equal 1, fragment_def.directives.length
21
+ assert_equal [20, 13], fragment_def.position
22
+ end
23
+
24
+ def assert_valid_variable(variable)
25
+ assert_equal "someVar", variable.name
26
+ assert_equal "Int", variable.type.name
27
+ assert_equal 1, variable.default_value
28
+ assert_equal [2, 28], variable.position
29
+ end
30
+
31
+ def assert_valid_field(field)
32
+ assert_equal "someField", field.name
33
+ assert_equal "myField", field.alias
34
+ assert_equal 2, field.directives.length
35
+ assert_equal 2, field.arguments.length
36
+ assert_equal 0, field.selections.length
37
+ assert_equal [3, 15], field.position
38
+ end
39
+
40
+ def assert_valid_literal_argument(argument)
41
+ assert_equal "ok", argument.name
42
+ assert_equal 1.4, argument.value
43
+ end
44
+
45
+ def assert_valid_variable_argument(argument)
46
+ assert_equal "someArg", argument.name
47
+ assert_equal "someVar", argument.value.name
48
+ end
49
+
50
+ def assert_valid_fragment_spread(fragment_spread)
51
+ assert_equal "moreNestedFields", fragment_spread.name
52
+ assert_equal 1, fragment_spread.directives.length
53
+ assert_equal [7, 17], fragment_spread.position
54
+ end
55
+
56
+ def assert_valid_directive(directive)
57
+ assert_equal "skip", directive.name
58
+ assert_equal "if", directive.arguments.first.name
59
+ assert_equal 1, directive.arguments.length
60
+ assert_equal [3, 62], directive.position
61
+ end
62
+
63
+ def assert_valid_typed_inline_fragment(inline_fragment)
64
+ assert_equal "OtherType", inline_fragment.type.name
65
+ assert_equal 2, inline_fragment.selections.length
66
+ assert_equal 1, inline_fragment.directives.length
67
+ assert_equal [10, 15], inline_fragment.position
68
+ end
69
+
70
+ def assert_valid_typeless_inline_fragment(inline_fragment)
71
+ assert_equal nil, inline_fragment.type
72
+ assert_equal 1, inline_fragment.selections.length
73
+ assert_equal 0, inline_fragment.directives.length
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,239 @@
1
+ module GraphQL
2
+ module Compatibility
3
+ # This asserts that a given parse function turns a string into
4
+ # the proper tree of {{GraphQL::Language::Nodes}}.
5
+ module SchemaParserSpecification
6
+ # @yieldparam query_string [String] A query string to parse
7
+ # @yieldreturn [GraphQL::Language::Nodes::Document]
8
+ # @return [Class<Minitest::Test>] A test suite for this parse function
9
+ def self.build_suite(&block)
10
+ Class.new(Minitest::Test) do
11
+ @@parse_fn = block
12
+
13
+ def parse(query_string)
14
+ @@parse_fn.call(query_string)
15
+ end
16
+
17
+ def test_it_parses_object_types
18
+ document = parse('
19
+ # This is what
20
+ # somebody said about something
21
+ type Comment implements Node @deprecated(reason: "No longer supported") {
22
+ id: ID!
23
+ }
24
+ ')
25
+
26
+ type = document.definitions.first
27
+ assert_equal GraphQL::Language::Nodes::ObjectTypeDefinition, type.class
28
+ assert_equal 'Comment', type.name
29
+ assert_equal "This is what\nsomebody said about something", type.description
30
+ assert_equal ['Node'], type.interfaces.map(&:name)
31
+ assert_equal ['id'], type.fields.map(&:name)
32
+ assert_equal [], type.fields[0].arguments
33
+ assert_equal 'ID', type.fields[0].type.of_type.name
34
+ assert_equal 1, type.directives.length
35
+
36
+ deprecated_directive = type.directives[0]
37
+ assert_equal 'deprecated', deprecated_directive.name
38
+ assert_equal 'reason', deprecated_directive.arguments[0].name
39
+ assert_equal 'No longer supported', deprecated_directive.arguments[0].value
40
+ end
41
+
42
+ def test_it_parses_scalars
43
+ document = parse('scalar DateTime')
44
+
45
+ type = document.definitions.first
46
+ assert_equal GraphQL::Language::Nodes::ScalarTypeDefinition, type.class
47
+ assert_equal 'DateTime', type.name
48
+ end
49
+
50
+ def test_it_parses_enum_types
51
+ document = parse('
52
+ enum DogCommand {
53
+ # Good dog
54
+ SIT
55
+ DOWN @deprecated(reason: "No longer supported")
56
+ HEEL
57
+ }
58
+ ')
59
+
60
+ type = document.definitions.first
61
+ assert_equal GraphQL::Language::Nodes::EnumTypeDefinition, type.class
62
+ assert_equal 'DogCommand', type.name
63
+ assert_equal 3, type.values.length
64
+
65
+ assert_equal 'SIT', type.values[0].name
66
+ assert_equal [], type.values[0].directives
67
+ assert_equal "Good dog", type.values[0].description
68
+
69
+ assert_equal 'DOWN', type.values[1].name
70
+ assert_equal 1, type.values[1].directives.length
71
+ deprecated_directive = type.values[1].directives[0]
72
+ assert_equal 'deprecated', deprecated_directive.name
73
+ assert_equal 'reason', deprecated_directive.arguments[0].name
74
+ assert_equal 'No longer supported', deprecated_directive.arguments[0].value
75
+
76
+ assert_equal 'HEEL', type.values[2].name
77
+ assert_equal [], type.values[2].directives
78
+ end
79
+
80
+ def test_it_parses_input_types
81
+ document = parse('
82
+ input EmptyMutationInput {
83
+ clientMutationId: String
84
+ }
85
+ ')
86
+
87
+ type = document.definitions.first
88
+ assert_equal GraphQL::Language::Nodes::InputObjectTypeDefinition, type.class
89
+ assert_equal 'EmptyMutationInput', type.name
90
+ assert_equal ['clientMutationId'], type.fields.map(&:name)
91
+ assert_equal 'String', type.fields[0].type.name
92
+ assert_equal nil, type.fields[0].default_value
93
+ end
94
+
95
+ def test_it_parses_directives
96
+ document = parse('
97
+ directive @include(if: Boolean!)
98
+ on FIELD
99
+ | FRAGMENT_SPREAD
100
+ | INLINE_FRAGMENT
101
+ ')
102
+
103
+ type = document.definitions.first
104
+ assert_equal GraphQL::Language::Nodes::DirectiveDefinition, type.class
105
+ assert_equal 'include', type.name
106
+
107
+ assert_equal 1, type.arguments.length
108
+ assert_equal 'if', type.arguments[0].name
109
+ assert_equal 'Boolean', type.arguments[0].type.of_type.name
110
+
111
+ assert_equal ['FIELD', 'FRAGMENT_SPREAD', 'INLINE_FRAGMENT'], type.locations
112
+ end
113
+
114
+ def test_it_parses_field_arguments
115
+ document = parse('
116
+ type Mutation {
117
+ post(
118
+ id: ID! @deprecated(reason: "Not used"),
119
+ # This is what goes in the post
120
+ data: String
121
+ ): Post
122
+ }
123
+ ')
124
+
125
+ field = document.definitions.first.fields.first
126
+ assert_equal ['id', 'data'], field.arguments.map(&:name)
127
+ id_arg = field.arguments[0]
128
+
129
+ deprecated_directive = id_arg.directives[0]
130
+ assert_equal 'deprecated', deprecated_directive.name
131
+ assert_equal 'reason', deprecated_directive.arguments[0].name
132
+ assert_equal 'Not used', deprecated_directive.arguments[0].value
133
+
134
+ data_arg = field.arguments[1]
135
+ assert_equal "data", data_arg.name
136
+ assert_equal "This is what goes in the post", data_arg.description
137
+ end
138
+
139
+ def test_it_parses_schema_definition
140
+ document = parse('
141
+ schema {
142
+ query: QueryRoot
143
+ mutation: MutationRoot
144
+ subscription: SubscriptionRoot
145
+ }
146
+ ')
147
+
148
+ schema = document.definitions.first
149
+ assert_equal 'QueryRoot', schema.query
150
+ assert_equal 'MutationRoot', schema.mutation
151
+ assert_equal 'SubscriptionRoot', schema.subscription
152
+ end
153
+
154
+ def test_it_parses_whole_definition_with_descriptions
155
+ document = parse(SCHEMA_DEFINITION_STRING)
156
+
157
+ assert_equal 6, document.definitions.size
158
+
159
+ schema_definition = document.definitions.shift
160
+ assert_equal GraphQL::Language::Nodes::SchemaDefinition, schema_definition.class
161
+
162
+ directive_definition = document.definitions.shift
163
+ assert_equal GraphQL::Language::Nodes::DirectiveDefinition, directive_definition.class
164
+ assert_equal 'This is a directive', directive_definition.description
165
+
166
+ enum_type_definition = document.definitions.shift
167
+ assert_equal GraphQL::Language::Nodes::EnumTypeDefinition, enum_type_definition.class
168
+ assert_equal "Multiline comment\n\nWith an enum", enum_type_definition.description
169
+
170
+ assert_nil enum_type_definition.values[0].description
171
+ assert_equal 'Not a creative color', enum_type_definition.values[1].description
172
+
173
+ object_type_definition = document.definitions.shift
174
+ assert_equal GraphQL::Language::Nodes::ObjectTypeDefinition, object_type_definition.class
175
+ assert_equal 'Comment without preceding space', object_type_definition.description
176
+ assert_equal 'And a field to boot', object_type_definition.fields[0].description
177
+
178
+ input_object_type_definition = document.definitions.shift
179
+ assert_equal GraphQL::Language::Nodes::InputObjectTypeDefinition, input_object_type_definition.class
180
+ assert_equal 'Comment for input object types', input_object_type_definition.description
181
+ assert_equal 'Color of the car', input_object_type_definition.fields[0].description
182
+
183
+ interface_type_definition = document.definitions.shift
184
+ assert_equal GraphQL::Language::Nodes::InterfaceTypeDefinition, interface_type_definition.class
185
+ assert_equal 'Comment for interface definitions', interface_type_definition.description
186
+ assert_equal 'Amount of wheels', interface_type_definition.fields[0].description
187
+ end
188
+ end
189
+ end
190
+
191
+ SCHEMA_DEFINITION_STRING = %|
192
+ # Schema at beginning of file
193
+
194
+ schema {
195
+ query: Hello
196
+ }
197
+
198
+ # Comment between two definitions are omitted
199
+
200
+ # This is a directive
201
+ directive @foo(
202
+ # It has an argument
203
+ arg: Int
204
+ ) on FIELD
205
+
206
+ # Multiline comment
207
+ #
208
+ # With an enum
209
+ enum Color {
210
+ RED
211
+
212
+ # Not a creative color
213
+ GREEN
214
+ BLUE
215
+ }
216
+
217
+ #Comment without preceding space
218
+ type Hello {
219
+ # And a field to boot
220
+ str: String
221
+ }
222
+
223
+ # Comment for input object types
224
+ input Car {
225
+ # Color of the car
226
+ color: String!
227
+ }
228
+
229
+ # Comment for interface definitions
230
+ interface Vehicle {
231
+ # Amount of wheels
232
+ wheels: Int!
233
+ }
234
+
235
+ # Comment at the end of schema
236
+ |
237
+ end
238
+ end
239
+ end