graphql 1.7.14 → 1.8.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +5 -5
  2. data/lib/generators/graphql/function_generator.rb +1 -1
  3. data/lib/generators/graphql/loader_generator.rb +1 -1
  4. data/lib/generators/graphql/mutation_generator.rb +1 -6
  5. data/lib/generators/graphql/templates/function.erb +2 -2
  6. data/lib/generators/graphql/templates/loader.erb +2 -2
  7. data/lib/graphql.rb +2 -0
  8. data/lib/graphql/argument.rb +0 -1
  9. data/lib/graphql/backwards_compatibility.rb +2 -3
  10. data/lib/graphql/base_type.rb +18 -16
  11. data/lib/graphql/compatibility/query_parser_specification.rb +0 -117
  12. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +0 -14
  13. data/lib/graphql/define/assign_object_field.rb +5 -12
  14. data/lib/graphql/deprecated_dsl.rb +28 -0
  15. data/lib/graphql/directive.rb +0 -1
  16. data/lib/graphql/enum_type.rb +1 -3
  17. data/lib/graphql/execution.rb +0 -1
  18. data/lib/graphql/execution/multiplex.rb +29 -12
  19. data/lib/graphql/field.rb +5 -20
  20. data/lib/graphql/function.rb +12 -0
  21. data/lib/graphql/input_object_type.rb +1 -3
  22. data/lib/graphql/internal_representation/node.rb +14 -26
  23. data/lib/graphql/internal_representation/visit.rb +6 -3
  24. data/lib/graphql/introspection/arguments_field.rb +0 -1
  25. data/lib/graphql/introspection/enum_values_field.rb +0 -1
  26. data/lib/graphql/introspection/fields_field.rb +0 -1
  27. data/lib/graphql/introspection/input_fields_field.rb +0 -1
  28. data/lib/graphql/introspection/interfaces_field.rb +0 -1
  29. data/lib/graphql/introspection/of_type_field.rb +0 -1
  30. data/lib/graphql/introspection/possible_types_field.rb +0 -1
  31. data/lib/graphql/introspection/schema_field.rb +0 -1
  32. data/lib/graphql/introspection/type_by_name_field.rb +0 -1
  33. data/lib/graphql/introspection/typename_field.rb +0 -1
  34. data/lib/graphql/language.rb +0 -3
  35. data/lib/graphql/language/generation.rb +182 -3
  36. data/lib/graphql/language/lexer.rb +69 -144
  37. data/lib/graphql/language/lexer.rl +4 -15
  38. data/lib/graphql/language/nodes.rb +76 -136
  39. data/lib/graphql/language/parser.rb +621 -668
  40. data/lib/graphql/language/parser.y +11 -17
  41. data/lib/graphql/language/token.rb +3 -10
  42. data/lib/graphql/object_type.rb +6 -1
  43. data/lib/graphql/query.rb +13 -8
  44. data/lib/graphql/query/arguments.rb +33 -48
  45. data/lib/graphql/query/context.rb +1 -0
  46. data/lib/graphql/query/literal_input.rb +1 -4
  47. data/lib/graphql/relay/connection_resolve.rb +3 -0
  48. data/lib/graphql/relay/global_id_resolve.rb +5 -1
  49. data/lib/graphql/relay/relation_connection.rb +19 -14
  50. data/lib/graphql/schema.rb +219 -12
  51. data/lib/graphql/schema/argument.rb +33 -0
  52. data/lib/graphql/schema/build_from_definition.rb +18 -64
  53. data/lib/graphql/schema/enum.rb +76 -0
  54. data/lib/graphql/schema/field.rb +127 -0
  55. data/lib/graphql/schema/field/dynamic_resolve.rb +63 -0
  56. data/lib/graphql/schema/field/unwrapped_resolve.rb +20 -0
  57. data/lib/graphql/schema/input_object.rb +61 -0
  58. data/lib/graphql/schema/interface.rb +32 -0
  59. data/lib/graphql/schema/loader.rb +2 -2
  60. data/lib/graphql/schema/member.rb +97 -0
  61. data/lib/graphql/schema/member/build_type.rb +106 -0
  62. data/lib/graphql/schema/member/has_fields.rb +56 -0
  63. data/lib/graphql/schema/member/instrumentation.rb +113 -0
  64. data/lib/graphql/schema/member/list_type_proxy.rb +21 -0
  65. data/lib/graphql/schema/member/non_null_type_proxy.rb +21 -0
  66. data/lib/graphql/schema/object.rb +65 -0
  67. data/lib/graphql/schema/printer.rb +266 -33
  68. data/lib/graphql/schema/scalar.rb +25 -0
  69. data/lib/graphql/schema/traversal.rb +26 -17
  70. data/lib/graphql/schema/union.rb +48 -0
  71. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +1 -5
  72. data/lib/graphql/static_validation/rules/fields_will_merge.rb +8 -15
  73. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +1 -11
  74. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +5 -7
  75. data/lib/graphql/tracing.rb +0 -1
  76. data/lib/graphql/tracing/platform_tracing.rb +7 -20
  77. data/lib/graphql/tracing/scout_tracing.rb +2 -2
  78. data/lib/graphql/unresolved_type_error.rb +2 -3
  79. data/lib/graphql/version.rb +1 -1
  80. data/readme.md +1 -1
  81. data/spec/dummy/app/channels/graphql_channel.rb +1 -22
  82. data/spec/dummy/log/development.log +0 -239
  83. data/spec/dummy/log/test.log +0 -204
  84. data/spec/dummy/test/system/action_cable_subscription_test.rb +0 -4
  85. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  86. data/spec/generators/graphql/function_generator_spec.rb +0 -26
  87. data/spec/generators/graphql/loader_generator_spec.rb +0 -24
  88. data/spec/graphql/analysis/max_query_complexity_spec.rb +3 -3
  89. data/spec/graphql/analysis/max_query_depth_spec.rb +3 -3
  90. data/spec/graphql/backtrace_spec.rb +0 -10
  91. data/spec/graphql/base_type_spec.rb +5 -19
  92. data/spec/graphql/boolean_type_spec.rb +3 -3
  93. data/spec/graphql/directive_spec.rb +1 -3
  94. data/spec/graphql/enum_type_spec.rb +5 -18
  95. data/spec/graphql/execution/execute_spec.rb +1 -1
  96. data/spec/graphql/execution/multiplex_spec.rb +2 -2
  97. data/spec/graphql/float_type_spec.rb +2 -2
  98. data/spec/graphql/id_type_spec.rb +1 -1
  99. data/spec/graphql/input_object_type_spec.rb +2 -15
  100. data/spec/graphql/int_type_spec.rb +2 -2
  101. data/spec/graphql/internal_representation/rewrite_spec.rb +2 -2
  102. data/spec/graphql/introspection/schema_type_spec.rb +0 -1
  103. data/spec/graphql/language/generation_spec.rb +186 -21
  104. data/spec/graphql/language/lexer_spec.rb +1 -21
  105. data/spec/graphql/language/nodes_spec.rb +12 -21
  106. data/spec/graphql/language/parser_spec.rb +1 -1
  107. data/spec/graphql/query/arguments_spec.rb +15 -37
  108. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +2 -2
  109. data/spec/graphql/query/variables_spec.rb +1 -1
  110. data/spec/graphql/query_spec.rb +5 -31
  111. data/spec/graphql/rake_task_spec.rb +1 -3
  112. data/spec/graphql/relay/base_connection_spec.rb +1 -1
  113. data/spec/graphql/relay/connection_instrumentation_spec.rb +2 -2
  114. data/spec/graphql/relay/connection_resolve_spec.rb +1 -1
  115. data/spec/graphql/relay/connection_type_spec.rb +1 -1
  116. data/spec/graphql/relay/mutation_spec.rb +3 -3
  117. data/spec/graphql/relay/relation_connection_spec.rb +1 -65
  118. data/spec/graphql/schema/build_from_definition_spec.rb +4 -86
  119. data/spec/graphql/schema/enum_spec.rb +60 -0
  120. data/spec/graphql/schema/field_spec.rb +14 -0
  121. data/spec/graphql/schema/input_object_spec.rb +43 -0
  122. data/spec/graphql/schema/interface_spec.rb +98 -0
  123. data/spec/graphql/schema/object_spec.rb +119 -0
  124. data/spec/graphql/schema/printer_spec.rb +15 -92
  125. data/spec/graphql/schema/scalar_spec.rb +40 -0
  126. data/spec/graphql/schema/union_spec.rb +35 -0
  127. data/spec/graphql/schema/validation_spec.rb +1 -1
  128. data/spec/graphql/schema/warden_spec.rb +11 -11
  129. data/spec/graphql/schema_spec.rb +25 -23
  130. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +2 -10
  131. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +2 -2
  132. data/spec/graphql/string_type_spec.rb +3 -3
  133. data/spec/graphql/subscriptions_spec.rb +1 -1
  134. data/spec/graphql/tracing/platform_tracing_spec.rb +1 -60
  135. data/spec/support/dummy/schema.rb +25 -39
  136. data/spec/support/jazz.rb +334 -0
  137. data/spec/support/lazy_helpers.rb +21 -23
  138. data/spec/support/star_wars/data.rb +7 -6
  139. data/spec/support/star_wars/schema.rb +109 -142
  140. metadata +39 -33
  141. data/lib/graphql/execution/instrumentation.rb +0 -82
  142. data/lib/graphql/language/block_string.rb +0 -47
  143. data/lib/graphql/language/document_from_schema_definition.rb +0 -277
  144. data/lib/graphql/language/printer.rb +0 -351
  145. data/lib/graphql/tracing/data_dog_tracing.rb +0 -49
  146. data/spec/graphql/execution/instrumentation_spec.rb +0 -165
  147. data/spec/graphql/language/block_string_spec.rb +0 -70
  148. data/spec/graphql/language/document_from_schema_definition_spec.rb +0 -770
  149. data/spec/graphql/language/printer_spec.rb +0 -203
@@ -1,351 +0,0 @@
1
- # frozen_string_literal: true
2
- module GraphQL
3
- module Language
4
- class Printer
5
- # Turn an arbitrary AST node back into a string.
6
- #
7
- # @example Turning a document into a query string
8
- # document = GraphQL.parse(query_string)
9
- # GraphQL::Language::Printer.new.print(document)
10
- # # => "{ ... }"
11
- #
12
- #
13
- # @example Building a custom printer
14
- #
15
- # class MyPrinter < GraphQL::Language::Printer
16
- # def print_argument(arg)
17
- # "#{arg.name}: <HIDDEN>"
18
- # end
19
- # end
20
- #
21
- # MyPrinter.new.print(document)
22
- # # => "mutation { pay(creditCard: <HIDDEN>) { success } }"
23
- #
24
- #
25
- # @param indent [String] Whitespace to add to the printed node
26
- # @return [String] Valid GraphQL for `node`
27
- def print(node, indent: "")
28
- print_node(node, indent: indent)
29
- end
30
-
31
- protected
32
-
33
- def print_document(document)
34
- document.definitions.map { |d| print_node(d) }.join("\n\n")
35
- end
36
-
37
- def print_argument(argument)
38
- "#{argument.name}: #{print_node(argument.value)}".dup
39
- end
40
-
41
- def print_directive(directive)
42
- out = "@#{directive.name}".dup
43
-
44
- if directive.arguments.any?
45
- out << "(#{directive.arguments.map { |a| print_argument(a) }.join(", ")})"
46
- end
47
-
48
- out
49
- end
50
-
51
- def print_enum(enum)
52
- "#{enum.name}".dup
53
- end
54
-
55
- def print_null_value
56
- "null".dup
57
- end
58
-
59
- def print_field(field, indent: "")
60
- out = "#{indent}".dup
61
- out << "#{field.alias}: " if field.alias
62
- out << "#{field.name}"
63
- out << "(#{field.arguments.map { |a| print_argument(a) }.join(", ")})" if field.arguments.any?
64
- out << print_directives(field.directives)
65
- out << print_selections(field.selections, indent: indent)
66
- out
67
- end
68
-
69
- def print_fragment_definition(fragment_def, indent: "")
70
- out = "#{indent}fragment #{fragment_def.name}".dup
71
- if fragment_def.type
72
- out << " on #{print_node(fragment_def.type)}"
73
- end
74
- out << print_directives(fragment_def.directives)
75
- out << print_selections(fragment_def.selections, indent: indent)
76
- out
77
- end
78
-
79
- def print_fragment_spread(fragment_spread, indent: "")
80
- out = "#{indent}...#{fragment_spread.name}".dup
81
- out << print_directives(fragment_spread.directives)
82
- out
83
- end
84
-
85
- def print_inline_fragment(inline_fragment, indent: "")
86
- out = "#{indent}...".dup
87
- if inline_fragment.type
88
- out << " on #{print_node(inline_fragment.type)}"
89
- end
90
- out << print_directives(inline_fragment.directives)
91
- out << print_selections(inline_fragment.selections, indent: indent)
92
- out
93
- end
94
-
95
- def print_input_object(input_object)
96
- "{#{input_object.arguments.map { |a| "#{a.name}: #{print(a.value)}" }.join(", ")}}"
97
- end
98
-
99
- def print_list_type(list_type)
100
- "[#{print_node(list_type.of_type)}]".dup
101
- end
102
-
103
- def print_non_null_type(non_null_type)
104
- "#{print_node(non_null_type.of_type)}!".dup
105
- end
106
-
107
- def print_operation_definition(operation_definition, indent: "")
108
- out = "#{indent}#{operation_definition.operation_type}".dup
109
- out << " #{operation_definition.name}" if operation_definition.name
110
-
111
- if operation_definition.variables.any?
112
- out << "(#{operation_definition.variables.map { |v| print_variable_definition(v) }.join(", ")})"
113
- end
114
-
115
- out << print_directives(operation_definition.directives)
116
- out << print_selections(operation_definition.selections, indent: indent)
117
- out
118
- end
119
-
120
- def print_type_name(type_name)
121
- "#{type_name.name}".dup
122
- end
123
-
124
- def print_variable_definition(variable_definition)
125
- out = "$#{variable_definition.name}: #{print_node(variable_definition.type)}".dup
126
- out << " = #{print_node(variable_definition.default_value)}" unless variable_definition.default_value.nil?
127
- out
128
- end
129
-
130
- def print_variable_identifier(variable_identifier)
131
- "$#{variable_identifier.name}".dup
132
- end
133
-
134
- def print_schema_definition(schema)
135
- if (schema.query.nil? || schema.query == 'Query') &&
136
- (schema.mutation.nil? || schema.mutation == 'Mutation') &&
137
- (schema.subscription.nil? || schema.subscription == 'Subscription')
138
- return
139
- end
140
-
141
- out = "schema {\n".dup
142
- out << " query: #{schema.query}\n" if schema.query
143
- out << " mutation: #{schema.mutation}\n" if schema.mutation
144
- out << " subscription: #{schema.subscription}\n" if schema.subscription
145
- out << "}"
146
- end
147
-
148
- def print_scalar_type_definition(scalar_type)
149
- out = print_description(scalar_type)
150
- out << "scalar #{scalar_type.name}"
151
- out << print_directives(scalar_type.directives)
152
- end
153
-
154
- def print_object_type_definition(object_type)
155
- out = print_description(object_type)
156
- out << "type #{object_type.name}"
157
- out << " implements " << object_type.interfaces.map(&:name).join(" & ") unless object_type.interfaces.empty?
158
- out << print_directives(object_type.directives)
159
- out << print_field_definitions(object_type.fields)
160
- end
161
-
162
- def print_input_value_definition(input_value)
163
- out = "#{input_value.name}: #{print_node(input_value.type)}".dup
164
- out << " = #{print_node(input_value.default_value)}" unless input_value.default_value.nil?
165
- out << print_directives(input_value.directives)
166
- end
167
-
168
- def print_arguments(arguments, indent: "")
169
- if arguments.all?{ |arg| !arg.description }
170
- return "(#{arguments.map{ |arg| print_input_value_definition(arg) }.join(", ")})"
171
- end
172
-
173
- out = "(\n".dup
174
- out << arguments.map.with_index{ |arg, i|
175
- "#{print_description(arg, indent: " " + indent, first_in_block: i == 0)} #{indent}"\
176
- "#{print_input_value_definition(arg)}"
177
- }.join("\n")
178
- out << "\n#{indent})"
179
- end
180
-
181
- def print_field_definition(field)
182
- out = field.name.dup
183
- unless field.arguments.empty?
184
- out << print_arguments(field.arguments, indent: " ")
185
- end
186
- out << ": #{print_node(field.type)}"
187
- out << print_directives(field.directives)
188
- end
189
-
190
- def print_interface_type_definition(interface_type)
191
- out = print_description(interface_type)
192
- out << "interface #{interface_type.name}"
193
- out << print_directives(interface_type.directives)
194
- out << print_field_definitions(interface_type.fields)
195
- end
196
-
197
- def print_union_type_definition(union_type)
198
- out = print_description(union_type)
199
- out << "union #{union_type.name}"
200
- out << print_directives(union_type.directives)
201
- out << " = " + union_type.types.map(&:name).join(" | ")
202
- end
203
-
204
- def print_enum_type_definition(enum_type)
205
- out = print_description(enum_type)
206
- out << "enum #{enum_type.name}#{print_directives(enum_type.directives)} {\n"
207
- enum_type.values.each.with_index do |value, i|
208
- out << print_description(value, indent: ' ', first_in_block: i == 0)
209
- out << print_enum_value_definition(value)
210
- end
211
- out << "}"
212
- end
213
-
214
- def print_enum_value_definition(enum_value)
215
- out = " #{enum_value.name}".dup
216
- out << print_directives(enum_value.directives)
217
- out << "\n"
218
- end
219
-
220
- def print_input_object_type_definition(input_object_type)
221
- out = print_description(input_object_type)
222
- out << "input #{input_object_type.name}"
223
- out << print_directives(input_object_type.directives)
224
- out << " {\n"
225
- input_object_type.fields.each.with_index do |field, i|
226
- out << print_description(field, indent: ' ', first_in_block: i == 0)
227
- out << " #{print_input_value_definition(field)}\n"
228
- end
229
- out << "}"
230
- end
231
-
232
- def print_directive_definition(directive)
233
- out = print_description(directive)
234
- out << "directive @#{directive.name}"
235
-
236
- if directive.arguments.any?
237
- out << print_arguments(directive.arguments)
238
- end
239
-
240
- out << " on #{directive.locations.join(' | ')}"
241
- end
242
-
243
- def print_description(node, indent: "", first_in_block: true)
244
- return ''.dup unless node.description
245
-
246
- description = indent != '' && !first_in_block ? "\n".dup : "".dup
247
- description << GraphQL::Language::Comments.commentize(node.description, indent: indent)
248
- end
249
-
250
- def print_field_definitions(fields)
251
- out = " {\n".dup
252
- fields.each.with_index do |field, i|
253
- out << print_description(field, indent: ' ', first_in_block: i == 0)
254
- out << " #{print_field_definition(field)}\n"
255
- end
256
- out << "}"
257
- end
258
-
259
- def print_directives(directives)
260
- if directives.any?
261
- directives.map { |d| " #{print_directive(d)}" }.join
262
- else
263
- ""
264
- end
265
- end
266
-
267
- def print_selections(selections, indent: "")
268
- if selections.any?
269
- out = " {\n".dup
270
- selections.each do |selection|
271
- out << print_node(selection, indent: indent + " ") << "\n"
272
- end
273
- out << "#{indent}}"
274
- else
275
- ""
276
- end
277
- end
278
-
279
- def print_node(node, indent: "")
280
- case node
281
- when Nodes::Document
282
- print_document(node)
283
- when Nodes::Argument
284
- print_argument(node)
285
- when Nodes::Directive
286
- print_directive(node)
287
- when Nodes::Enum
288
- print_enum(node)
289
- when Nodes::NullValue
290
- print_null_value
291
- when Nodes::Field
292
- print_field(node, indent: indent)
293
- when Nodes::FragmentDefinition
294
- print_fragment_definition(node, indent: indent)
295
- when Nodes::FragmentSpread
296
- print_fragment_spread(node, indent: indent)
297
- when Nodes::InlineFragment
298
- print_inline_fragment(node, indent: indent)
299
- when Nodes::InputObject
300
- print_input_object(node)
301
- when Nodes::ListType
302
- print_list_type(node)
303
- when Nodes::NonNullType
304
- print_non_null_type(node)
305
- when Nodes::OperationDefinition
306
- print_operation_definition(node, indent: indent)
307
- when Nodes::TypeName
308
- print_type_name(node)
309
- when Nodes::VariableDefinition
310
- print_variable_definition(node)
311
- when Nodes::VariableIdentifier
312
- print_variable_identifier(node)
313
- when Nodes::SchemaDefinition
314
- print_schema_definition(node)
315
- when Nodes::ScalarTypeDefinition
316
- print_scalar_type_definition(node)
317
- when Nodes::ObjectTypeDefinition
318
- print_object_type_definition(node)
319
- when Nodes::InputValueDefinition
320
- print_input_value_definition(node)
321
- when Nodes::FieldDefinition
322
- print_field_definition(node)
323
- when Nodes::InterfaceTypeDefinition
324
- print_interface_type_definition(node)
325
- when Nodes::UnionTypeDefinition
326
- print_union_type_definition(node)
327
- when Nodes::EnumTypeDefinition
328
- print_enum_type_definition(node)
329
- when Nodes::EnumValueDefinition
330
- print_enum_value_definition(node)
331
- when Nodes::InputObjectTypeDefinition
332
- print_input_object_type_definition(node)
333
- when Nodes::DirectiveDefinition
334
- print_directive_definition(node)
335
- when FalseClass, Float, Integer, NilClass, String, TrueClass, Symbol
336
- GraphQL::Language.serialize(node)
337
- when Array
338
- "[#{node.map { |v| print_node(v) }.join(", ")}]".dup
339
- when Hash
340
- "{#{node.map { |k, v| "#{k}: #{print_node(v)}" }.join(", ")}}".dup
341
- else
342
- GraphQL::Language.serialize(node.to_s)
343
- end
344
- end
345
-
346
- private
347
-
348
- attr_reader :node
349
- end
350
- end
351
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module GraphQL
4
- module Tracing
5
- class DataDogTracing < PlatformTracing
6
- self.platform_keys = {
7
- 'lex' => 'lex.graphql',
8
- 'parse' => 'parse.graphql',
9
- 'validate' => 'validate.graphql',
10
- 'analyze_query' => 'analyze.graphql',
11
- 'analyze_multiplex' => 'analyze.graphql',
12
- 'execute_multiplex' => 'execute.graphql',
13
- 'execute_query' => 'execute.graphql',
14
- 'execute_query_lazy' => 'execute.graphql',
15
- }
16
-
17
- def platform_trace(platform_key, key, data)
18
- tracer.trace(platform_key, service: service_name) do |span|
19
- span.span_type = 'custom'
20
-
21
- if key == 'execute_multiplex'
22
- operations = data[:multiplex].queries.map(&:selected_operation_name).join(', ')
23
- span.resource = operations unless operations.empty?
24
- end
25
-
26
- if key == 'execute_query'
27
- span.set_tag(:selected_operation_name, data[:query].selected_operation_name)
28
- span.set_tag(:selected_operation_type, data[:query].selected_operation.operation_type)
29
- span.set_tag(:query_string, data[:query].query_string)
30
- end
31
-
32
- yield
33
- end
34
- end
35
-
36
- def service_name
37
- options.fetch(:service, 'ruby-graphql')
38
- end
39
-
40
- def tracer
41
- options.fetch(:tracer, Datadog.tracer)
42
- end
43
-
44
- def platform_field_key(type, field)
45
- "#{type.name}.#{field.name}"
46
- end
47
- end
48
- end
49
- end
@@ -1,165 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
-
4
- describe GraphQL::Schema do
5
- describe "instrumentation teardown bug" do
6
- # This instrumenter records that it ran,
7
- # or raises an error if instructed to do so
8
- class InstrumenterError < StandardError
9
- attr_reader :key
10
- def initialize(key)
11
- @key = key
12
- super()
13
- end
14
- end
15
-
16
- class LogInstrumenter
17
- def before_query(unit_of_work)
18
- run_hook(unit_of_work, "begin")
19
- end
20
-
21
- def after_query(unit_of_work)
22
- run_hook(unit_of_work, "end")
23
- end
24
-
25
- alias :before_multiplex :before_query
26
- alias :after_multiplex :after_query
27
-
28
- private
29
-
30
- def run_hook(unit_of_work, event_name)
31
- unit_of_work.context[log_key(event_name)] = true
32
- if unit_of_work.context[raise_key(event_name)]
33
- raise InstrumenterError.new(log_key(event_name))
34
- end
35
- end
36
-
37
- def log_key(event_name)
38
- context_key("did_#{event_name}")
39
- end
40
-
41
- def raise_key(event_name)
42
- context_key("should_raise_#{event_name}")
43
- end
44
-
45
- def context_key(suffix)
46
- prefix = self.class.name.sub("Instrumenter", "").downcase
47
- :"#{prefix}_instrumenter_#{suffix}"
48
- end
49
- end
50
-
51
- class FirstInstrumenter < LogInstrumenter; end
52
- class SecondInstrumenter < LogInstrumenter; end
53
-
54
- let(:query_type) {
55
- GraphQL::ObjectType.define do
56
- name "Query"
57
- field :int, types.Int do
58
- argument :value, types.Int
59
- resolve ->(obj, args, ctx) { args.value }
60
- end
61
- end
62
- }
63
-
64
- let(:schema) {
65
- spec = self
66
- GraphQL::Schema.define do
67
- query(spec.query_type)
68
- instrument(:query, FirstInstrumenter.new)
69
- instrument(:query, SecondInstrumenter.new)
70
- end
71
- }
72
-
73
- describe "query instrumenters" do
74
- it "before_query of the 2nd instrumenter does not run but after_query does" do
75
- context = {second_instrumenter_should_raise_begin: true}
76
- assert_raises InstrumenterError do
77
- schema.execute(" { int(value: 2) } ", context: context)
78
- end
79
- assert context[:first_instrumenter_did_begin]
80
- assert context[:first_instrumenter_did_end]
81
- assert context[:second_instrumenter_did_begin]
82
- refute context[:second_instrumenter_did_end]
83
- end
84
-
85
- it "runs after_query even if a previous after_query raised an error" do
86
- context = {second_instrumenter_should_raise_end: true}
87
- err = assert_raises InstrumenterError do
88
- schema.execute(" { int(value: 2) } ", context: context)
89
- end
90
- # The error came from the second instrumenter:
91
- assert_equal :second_instrumenter_did_end, err.key
92
- # But the first instrumenter still got a chance to teardown
93
- assert context[:first_instrumenter_did_begin]
94
- assert context[:first_instrumenter_did_end]
95
- assert context[:second_instrumenter_did_begin]
96
- assert context[:second_instrumenter_did_end]
97
- end
98
- end
99
-
100
- describe "within a multiplex" do
101
- let(:multiplex_schema) {
102
- schema.redefine {
103
- instrument(:multiplex, FirstInstrumenter.new)
104
- instrument(:multiplex, SecondInstrumenter.new)
105
- }
106
- }
107
-
108
- it "only runs after_multiplex if before_multiplex finished" do
109
- multiplex_ctx = {second_instrumenter_should_raise_begin: true}
110
- query_1_ctx = {}
111
- query_2_ctx = {}
112
- assert_raises InstrumenterError do
113
- multiplex_schema.multiplex(
114
- [
115
- {query: "{int(value: 1)}", context: query_1_ctx},
116
- {query: "{int(value: 2)}", context: query_2_ctx},
117
- ],
118
- context: multiplex_ctx
119
- )
120
- end
121
-
122
- assert multiplex_ctx[:first_instrumenter_did_begin]
123
- assert multiplex_ctx[:first_instrumenter_did_end]
124
- assert multiplex_ctx[:second_instrumenter_did_begin]
125
- refute multiplex_ctx[:second_instrumenter_did_end]
126
- # No query instrumentation was run at all
127
- assert_equal 0, query_1_ctx.size
128
- assert_equal 0, query_2_ctx.size
129
- end
130
-
131
- it "does full and partial query runs" do
132
- multiplex_ctx = {}
133
- query_1_ctx = {}
134
- query_2_ctx = {second_instrumenter_should_raise_begin: true}
135
- assert_raises InstrumenterError do
136
- multiplex_schema.multiplex(
137
- [
138
- { query: " { int(value: 2) } ", context: query_1_ctx },
139
- { query: " { int(value: 2) } ", context: query_2_ctx },
140
- ],
141
- context: multiplex_ctx
142
- )
143
- end
144
-
145
- # multiplex got a full run
146
- assert multiplex_ctx[:first_instrumenter_did_begin]
147
- assert multiplex_ctx[:first_instrumenter_did_end]
148
- assert multiplex_ctx[:second_instrumenter_did_begin]
149
- assert multiplex_ctx[:second_instrumenter_did_end]
150
-
151
- # query 1 got a full run
152
- assert query_1_ctx[:first_instrumenter_did_begin]
153
- assert query_1_ctx[:first_instrumenter_did_end]
154
- assert query_1_ctx[:second_instrumenter_did_begin]
155
- assert query_1_ctx[:second_instrumenter_did_end]
156
-
157
- # query 2 got a partial run
158
- assert query_2_ctx[:first_instrumenter_did_begin]
159
- assert query_2_ctx[:first_instrumenter_did_end]
160
- assert query_2_ctx[:second_instrumenter_did_begin]
161
- refute query_2_ctx[:second_instrumenter_did_end]
162
- end
163
- end
164
- end
165
- end