graphql 1.8.7 → 1.9.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 (368) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install_generator.rb +2 -1
  3. data/lib/generators/graphql/scalar_generator.rb +20 -0
  4. data/lib/generators/graphql/templates/base_scalar.erb +4 -0
  5. data/lib/generators/graphql/templates/scalar.erb +13 -0
  6. data/lib/graphql/analysis/ast/analyzer.rb +62 -0
  7. data/lib/graphql/analysis/ast/field_usage.rb +28 -0
  8. data/lib/graphql/analysis/ast/max_query_complexity.rb +23 -0
  9. data/lib/graphql/analysis/ast/max_query_depth.rb +18 -0
  10. data/lib/graphql/analysis/ast/query_complexity.rb +114 -0
  11. data/lib/graphql/analysis/ast/query_depth.rb +66 -0
  12. data/lib/graphql/analysis/ast/visitor.rb +255 -0
  13. data/lib/graphql/analysis/ast.rb +82 -0
  14. data/lib/graphql/analysis.rb +1 -0
  15. data/lib/graphql/argument.rb +5 -0
  16. data/lib/graphql/authorization.rb +1 -0
  17. data/lib/graphql/backwards_compatibility.rb +1 -1
  18. data/lib/graphql/base_type.rb +1 -1
  19. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +1 -2
  20. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -6
  21. data/lib/graphql/dig.rb +19 -0
  22. data/lib/graphql/directive/include_directive.rb +1 -7
  23. data/lib/graphql/directive/skip_directive.rb +1 -8
  24. data/lib/graphql/directive.rb +13 -1
  25. data/lib/graphql/enum_type.rb +8 -0
  26. data/lib/graphql/execution/execute.rb +36 -17
  27. data/lib/graphql/execution/instrumentation.rb +2 -0
  28. data/lib/graphql/execution/interpreter/execution_errors.rb +29 -0
  29. data/lib/graphql/execution/interpreter/hash_response.rb +46 -0
  30. data/lib/graphql/execution/interpreter/resolve.rb +58 -0
  31. data/lib/graphql/execution/interpreter/runtime.rb +597 -0
  32. data/lib/graphql/execution/interpreter.rb +99 -0
  33. data/lib/graphql/execution/lazy.rb +8 -1
  34. data/lib/graphql/execution/lookahead.rb +351 -0
  35. data/lib/graphql/execution/multiplex.rb +37 -29
  36. data/lib/graphql/execution.rb +2 -0
  37. data/lib/graphql/execution_error.rb +1 -1
  38. data/lib/graphql/field.rb +1 -7
  39. data/lib/graphql/integer_encoding_error.rb +12 -0
  40. data/lib/graphql/internal_representation/rewrite.rb +127 -142
  41. data/lib/graphql/introspection/dynamic_fields.rb +8 -2
  42. data/lib/graphql/introspection/entry_points.rb +11 -6
  43. data/lib/graphql/introspection/enum_value_type.rb +4 -0
  44. data/lib/graphql/introspection/schema_type.rb +7 -2
  45. data/lib/graphql/introspection/type_type.rb +9 -5
  46. data/lib/graphql/invalid_null_error.rb +1 -1
  47. data/lib/graphql/language/block_string.rb +37 -0
  48. data/lib/graphql/language/document_from_schema_definition.rb +10 -7
  49. data/lib/graphql/language/lexer.rb +55 -36
  50. data/lib/graphql/language/lexer.rl +8 -3
  51. data/lib/graphql/language/nodes.rb +440 -362
  52. data/lib/graphql/language/parser.rb +56 -56
  53. data/lib/graphql/language/parser.y +12 -12
  54. data/lib/graphql/language/printer.rb +2 -2
  55. data/lib/graphql/language/visitor.rb +158 -15
  56. data/lib/graphql/language.rb +0 -1
  57. data/lib/graphql/literal_validation_error.rb +6 -0
  58. data/lib/graphql/query/arguments.rb +3 -2
  59. data/lib/graphql/query/arguments_cache.rb +1 -1
  60. data/lib/graphql/query/context.rb +14 -5
  61. data/lib/graphql/query/executor.rb +1 -1
  62. data/lib/graphql/query/result.rb +1 -1
  63. data/lib/graphql/query/validation_pipeline.rb +35 -11
  64. data/lib/graphql/query/variable_validation_error.rb +10 -1
  65. data/lib/graphql/query.rb +16 -2
  66. data/lib/graphql/relay/base_connection.rb +2 -0
  67. data/lib/graphql/relay/connection_instrumentation.rb +3 -1
  68. data/lib/graphql/relay/connection_resolve.rb +1 -1
  69. data/lib/graphql/relay/node.rb +2 -28
  70. data/lib/graphql/relay/relation_connection.rb +1 -1
  71. data/lib/graphql/schema/argument.rb +13 -5
  72. data/lib/graphql/schema/base_64_encoder.rb +4 -4
  73. data/lib/graphql/schema/build_from_definition.rb +2 -4
  74. data/lib/graphql/schema/default_type_error.rb +1 -1
  75. data/lib/graphql/schema/directive/feature.rb +66 -0
  76. data/lib/graphql/schema/directive/include.rb +25 -0
  77. data/lib/graphql/schema/directive/skip.rb +25 -0
  78. data/lib/graphql/schema/directive/transform.rb +48 -0
  79. data/lib/graphql/schema/directive.rb +103 -0
  80. data/lib/graphql/schema/enum_value.rb +3 -2
  81. data/lib/graphql/schema/field/connection_extension.rb +50 -0
  82. data/lib/graphql/schema/field/scope_extension.rb +18 -0
  83. data/lib/graphql/schema/field.rb +273 -64
  84. data/lib/graphql/schema/field_extension.rb +69 -0
  85. data/lib/graphql/schema/input_object.rb +16 -8
  86. data/lib/graphql/schema/interface.rb +1 -0
  87. data/lib/graphql/schema/loader.rb +22 -16
  88. data/lib/graphql/schema/member/base_dsl_methods.rb +8 -2
  89. data/lib/graphql/schema/member/build_type.rb +33 -1
  90. data/lib/graphql/schema/member/has_arguments.rb +6 -2
  91. data/lib/graphql/schema/member/has_fields.rb +18 -70
  92. data/lib/graphql/schema/member/has_path.rb +25 -0
  93. data/lib/graphql/schema/member/instrumentation.rb +10 -7
  94. data/lib/graphql/schema/member.rb +2 -0
  95. data/lib/graphql/schema/mutation.rb +6 -48
  96. data/lib/graphql/schema/non_null.rb +5 -1
  97. data/lib/graphql/schema/object.rb +18 -4
  98. data/lib/graphql/schema/printer.rb +1 -1
  99. data/lib/graphql/schema/relay_classic_mutation.rb +42 -9
  100. data/lib/graphql/schema/resolver/has_payload_type.rb +65 -0
  101. data/lib/graphql/schema/resolver.rb +45 -20
  102. data/lib/graphql/schema/subscription.rb +97 -0
  103. data/lib/graphql/schema/traversal.rb +11 -7
  104. data/lib/graphql/schema.rb +186 -38
  105. data/lib/graphql/static_validation/all_rules.rb +3 -2
  106. data/lib/graphql/static_validation/base_visitor.rb +199 -0
  107. data/lib/graphql/static_validation/default_visitor.rb +15 -0
  108. data/lib/graphql/static_validation/definition_dependencies.rb +62 -68
  109. data/lib/graphql/static_validation/{message.rb → error.rb} +11 -11
  110. data/lib/graphql/static_validation/interpreter_visitor.rb +14 -0
  111. data/lib/graphql/static_validation/literal_validator.rb +54 -11
  112. data/lib/graphql/static_validation/no_validate_visitor.rb +10 -0
  113. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +87 -16
  114. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +31 -0
  115. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +11 -11
  116. data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +30 -0
  117. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +52 -8
  118. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +35 -0
  119. data/lib/graphql/static_validation/rules/directives_are_defined.rb +12 -15
  120. data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +29 -0
  121. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +19 -14
  122. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +31 -0
  123. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +17 -19
  124. data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +32 -0
  125. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +30 -14
  126. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +31 -0
  127. data/lib/graphql/static_validation/rules/fields_will_merge.rb +356 -29
  128. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +32 -0
  129. data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +20 -13
  130. data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +29 -0
  131. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +37 -29
  132. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +35 -0
  133. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +25 -17
  134. data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +29 -0
  135. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +12 -10
  136. data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +29 -0
  137. data/lib/graphql/static_validation/rules/fragments_are_named.rb +7 -11
  138. data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +26 -0
  139. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +16 -16
  140. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +30 -0
  141. data/lib/graphql/static_validation/rules/fragments_are_used.rb +21 -14
  142. data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +29 -0
  143. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +10 -14
  144. data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +26 -0
  145. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +30 -30
  146. data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +25 -0
  147. data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +25 -17
  148. data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +28 -0
  149. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +17 -18
  150. data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +35 -0
  151. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +47 -0
  152. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +35 -0
  153. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +10 -14
  154. data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +26 -0
  155. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +28 -17
  156. data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +29 -0
  157. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +35 -27
  158. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +39 -0
  159. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +15 -14
  160. data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +29 -0
  161. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +41 -30
  162. data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +38 -0
  163. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +18 -14
  164. data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +32 -0
  165. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +73 -65
  166. data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +37 -0
  167. data/lib/graphql/static_validation/validation_context.rb +8 -51
  168. data/lib/graphql/static_validation/validator.rb +23 -15
  169. data/lib/graphql/static_validation.rb +5 -3
  170. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -2
  171. data/lib/graphql/subscriptions/event.rb +28 -5
  172. data/lib/graphql/subscriptions/subscription_root.rb +66 -0
  173. data/lib/graphql/subscriptions.rb +16 -2
  174. data/lib/graphql/tracing/active_support_notifications_tracing.rb +0 -1
  175. data/lib/graphql/tracing/appsignal_tracing.rb +1 -1
  176. data/lib/graphql/tracing/data_dog_tracing.rb +1 -1
  177. data/lib/graphql/tracing/new_relic_tracing.rb +3 -3
  178. data/lib/graphql/tracing/platform_tracing.rb +17 -1
  179. data/lib/graphql/tracing/prometheus_tracing.rb +1 -1
  180. data/lib/graphql/tracing/scout_tracing.rb +1 -1
  181. data/lib/graphql/tracing/skylight_tracing.rb +3 -3
  182. data/lib/graphql/tracing.rb +8 -8
  183. data/lib/graphql/types/float.rb +1 -1
  184. data/lib/graphql/types/int.rb +11 -2
  185. data/lib/graphql/types/iso_8601_date_time.rb +15 -1
  186. data/lib/graphql/types/relay/base_connection.rb +15 -1
  187. data/lib/graphql/types/relay/node.rb +0 -1
  188. data/lib/graphql/types/relay/node_field.rb +43 -0
  189. data/lib/graphql/types/relay/nodes_field.rb +45 -0
  190. data/lib/graphql/types/relay.rb +2 -0
  191. data/lib/graphql/unauthorized_error.rb +4 -0
  192. data/lib/graphql/unauthorized_field_error.rb +23 -0
  193. data/lib/graphql/upgrader/member.rb +5 -0
  194. data/lib/graphql/version.rb +1 -1
  195. data/lib/graphql.rb +6 -1
  196. data/readme.md +7 -7
  197. data/spec/dummy/Gemfile +1 -1
  198. data/spec/dummy/Gemfile.lock +157 -0
  199. data/spec/dummy/app/channels/graphql_channel.rb +22 -11
  200. data/spec/dummy/config/locales/en.yml +1 -1
  201. data/spec/dummy/log/test.log +199 -0
  202. data/spec/dummy/test/test_helper.rb +1 -0
  203. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4w/4wzXRZrAkwKdgYaSE0pid5eB-fer8vSfSku_NPg4rMA.cache +0 -0
  204. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7I/7IHVBiJT06QSpgLpLoJIxboQ0B-D_tMTxsvoezBTV3Q.cache +1 -0
  205. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8w/8wY_SKagj8wHuwGNAAf6JnQ8joMbC6cEYpHrTAI8Urc.cache +1 -0
  206. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/AK/AKzz1u6bGb4auXcrObA_g5LL-oV0ejNGa448AgAi_WQ.cache +1 -0
  207. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ET/ETW4uxvaYpruL8y6_ZptUH82ZowMaHIqvg5WexBFdEM.cache +3 -0
  208. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F1/F1TWpjjyA56k9Z90n5B3xRn7DUdGjX73QCkYC6k07JQ.cache +0 -0
  209. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +2 -0
  210. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +2 -0
  211. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ms/MsKSimH_UCB-H1tLvDABDHuvGciuoW6kVqQWDrXU5FQ.cache +0 -0
  212. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Mt/Mtci-Kim50aPOmeClD4AIicKn1d1WJ0n454IjSd94sk.cache +0 -0
  213. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QH/QHt3Tc1Y6M66Oo_pDuMyWrQNs4Pp3SMeZR5K1wJj2Ts.cache +1 -0
  214. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/XU/XU4k1OXnfMils5SrirorPvDSyDSqiOWLZNtmAH1HH8k.cache +0 -0
  215. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ZI/ZIof7mZxWWCnraIFOCuV6a8QRWzKJXJnx2Xd7C0ZyX0.cache +1 -0
  216. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cG/cGc_puuPS5pZKgUcy1Y_i1L6jl5UtsiIrMH59rTzR6c.cache +3 -0
  217. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/df/dfro_B6bx3KP1Go-7jEOqqZ2j4hVRseXIc3es9PKQno.cache +1 -0
  218. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jO/jO1DfbqnG0mTULsjJJANc3fefrG2zt7DIMmcptMT628.cache +1 -0
  219. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pE/pE7gO6pQ-z187Swb4hT554wmqsq-cNzgPWLrCz-LQQQ.cache +0 -0
  220. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/r9/r9iU1l58a6rxkZSW5RSC52_tD-_UQuHxoMVnkfJ7Mhs.cache +1 -0
  221. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xi/xitPPFfPIyDMpaznV0sBBcw8eSCV8PJcLLWin78sCgE.cache +0 -0
  222. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  223. data/spec/graphql/analysis/analyze_query_spec.rb +1 -1
  224. data/spec/graphql/analysis/ast/field_usage_spec.rb +51 -0
  225. data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +120 -0
  226. data/spec/graphql/analysis/ast/max_query_depth_spec.rb +114 -0
  227. data/spec/graphql/analysis/ast/query_complexity_spec.rb +299 -0
  228. data/spec/graphql/analysis/ast/query_depth_spec.rb +108 -0
  229. data/spec/graphql/analysis/ast_spec.rb +269 -0
  230. data/spec/graphql/authorization_spec.rb +120 -23
  231. data/spec/graphql/base_type_spec.rb +6 -4
  232. data/spec/graphql/enum_type_spec.rb +6 -1
  233. data/spec/graphql/execution/execute_spec.rb +9 -9
  234. data/spec/graphql/execution/instrumentation_spec.rb +19 -0
  235. data/spec/graphql/execution/interpreter_spec.rb +485 -0
  236. data/spec/graphql/execution/lazy_spec.rb +67 -1
  237. data/spec/graphql/execution/lookahead_spec.rb +363 -0
  238. data/spec/graphql/execution/multiplex_spec.rb +31 -3
  239. data/spec/graphql/execution/typecast_spec.rb +20 -20
  240. data/spec/graphql/execution_error_spec.rb +110 -96
  241. data/spec/graphql/field_spec.rb +1 -1
  242. data/spec/graphql/input_object_type_spec.rb +13 -352
  243. data/spec/graphql/int_type_spec.rb +19 -0
  244. data/spec/graphql/interface_type_spec.rb +4 -4
  245. data/spec/graphql/internal_representation/rewrite_spec.rb +2 -0
  246. data/spec/graphql/introspection/input_value_type_spec.rb +1 -1
  247. data/spec/graphql/introspection/type_type_spec.rb +1 -2
  248. data/spec/graphql/language/document_from_schema_definition_spec.rb +2 -2
  249. data/spec/graphql/language/lexer_spec.rb +72 -3
  250. data/spec/graphql/language/nodes_spec.rb +20 -0
  251. data/spec/graphql/language/printer_spec.rb +18 -6
  252. data/spec/graphql/language/visitor_spec.rb +320 -14
  253. data/spec/graphql/non_null_type_spec.rb +1 -1
  254. data/spec/graphql/object_type_spec.rb +32 -27
  255. data/spec/graphql/query/arguments_spec.rb +21 -0
  256. data/spec/graphql/query/context_spec.rb +28 -0
  257. data/spec/graphql/query/executor_spec.rb +40 -36
  258. data/spec/graphql/query_spec.rb +12 -6
  259. data/spec/graphql/schema/argument_spec.rb +35 -1
  260. data/spec/graphql/schema/build_from_definition_spec.rb +144 -29
  261. data/spec/graphql/schema/catchall_middleware_spec.rb +16 -15
  262. data/spec/graphql/schema/directive/feature_spec.rb +81 -0
  263. data/spec/graphql/schema/directive/transform_spec.rb +39 -0
  264. data/spec/graphql/schema/enum_spec.rb +12 -3
  265. data/spec/graphql/schema/enum_value_spec.rb +11 -0
  266. data/spec/graphql/schema/field_extension_spec.rb +115 -0
  267. data/spec/graphql/schema/field_spec.rb +47 -7
  268. data/spec/graphql/schema/input_object_spec.rb +95 -0
  269. data/spec/graphql/schema/instrumentation_spec.rb +3 -0
  270. data/spec/graphql/schema/interface_spec.rb +8 -2
  271. data/spec/graphql/schema/introspection_system_spec.rb +9 -1
  272. data/spec/graphql/schema/loader_spec.rb +5 -0
  273. data/spec/graphql/schema/member/accepts_definition_spec.rb +4 -0
  274. data/spec/graphql/schema/member/build_type_spec.rb +46 -0
  275. data/spec/graphql/schema/member/scoped_spec.rb +19 -3
  276. data/spec/graphql/schema/mutation_spec.rb +5 -3
  277. data/spec/graphql/schema/object_spec.rb +9 -1
  278. data/spec/graphql/schema/printer_spec.rb +255 -93
  279. data/spec/graphql/schema/relay_classic_mutation_spec.rb +133 -0
  280. data/spec/graphql/schema/resolver_spec.rb +173 -9
  281. data/spec/graphql/schema/scalar_spec.rb +6 -0
  282. data/spec/graphql/schema/subscription_spec.rb +416 -0
  283. data/spec/graphql/schema/traversal_spec.rb +10 -10
  284. data/spec/graphql/schema/type_expression_spec.rb +2 -2
  285. data/spec/graphql/schema/union_spec.rb +7 -0
  286. data/spec/graphql/schema/validation_spec.rb +1 -1
  287. data/spec/graphql/schema/warden_spec.rb +145 -88
  288. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +213 -73
  289. data/spec/graphql/static_validation/rules/argument_names_are_unique_spec.rb +2 -2
  290. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +72 -29
  291. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +4 -2
  292. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +4 -2
  293. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +10 -5
  294. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +10 -5
  295. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +131 -5
  296. data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +2 -1
  297. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +6 -3
  298. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +4 -2
  299. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +4 -2
  300. data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +2 -1
  301. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +6 -3
  302. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +22 -2
  303. data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +2 -1
  304. data/spec/graphql/static_validation/rules/operation_names_are_valid_spec.rb +6 -3
  305. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +13 -4
  306. data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb +58 -0
  307. data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +2 -1
  308. data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +14 -7
  309. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +14 -7
  310. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +8 -4
  311. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +8 -4
  312. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +23 -3
  313. data/spec/graphql/static_validation/type_stack_spec.rb +10 -19
  314. data/spec/graphql/static_validation/validator_spec.rb +50 -2
  315. data/spec/graphql/subscriptions_spec.rb +27 -16
  316. data/spec/graphql/tracing/new_relic_tracing_spec.rb +16 -0
  317. data/spec/graphql/tracing/platform_tracing_spec.rb +59 -37
  318. data/spec/graphql/tracing/prometheus_tracing_spec.rb +3 -0
  319. data/spec/graphql/tracing/skylight_tracing_spec.rb +16 -0
  320. data/spec/graphql/types/iso_8601_date_time_spec.rb +29 -2
  321. data/spec/graphql/union_type_spec.rb +2 -2
  322. data/spec/graphql/upgrader/member_spec.rb +67 -0
  323. data/spec/{graphql → integration/mongoid/graphql}/relay/mongo_relation_connection_spec.rb +11 -22
  324. data/spec/integration/mongoid/spec_helper.rb +2 -0
  325. data/spec/{support → integration/mongoid}/star_trek/data.rb +0 -0
  326. data/spec/{support → integration/mongoid}/star_trek/schema.rb +56 -34
  327. data/spec/{support/star_wars → integration/rails}/data.rb +1 -0
  328. data/spec/{support → integration/rails/generators}/base_generator_test.rb +0 -0
  329. data/spec/{generators → integration/rails/generators}/graphql/enum_generator_spec.rb +0 -0
  330. data/spec/{generators → integration/rails/generators}/graphql/install_generator_spec.rb +1 -1
  331. data/spec/{generators → integration/rails/generators}/graphql/interface_generator_spec.rb +0 -0
  332. data/spec/{generators → integration/rails/generators}/graphql/loader_generator_spec.rb +0 -0
  333. data/spec/{generators → integration/rails/generators}/graphql/mutation_generator_spec.rb +0 -0
  334. data/spec/{generators → integration/rails/generators}/graphql/object_generator_spec.rb +0 -0
  335. data/spec/integration/rails/generators/graphql/scalar_generator_spec.rb +28 -0
  336. data/spec/{generators → integration/rails/generators}/graphql/union_generator_spec.rb +0 -0
  337. data/spec/integration/rails/graphql/input_object_type_spec.rb +364 -0
  338. data/spec/{graphql → integration/rails/graphql}/query/variables_spec.rb +7 -7
  339. data/spec/{graphql → integration/rails/graphql}/relay/array_connection_spec.rb +9 -9
  340. data/spec/{graphql → integration/rails/graphql}/relay/base_connection_spec.rb +11 -3
  341. data/spec/{graphql → integration/rails/graphql}/relay/connection_instrumentation_spec.rb +19 -22
  342. data/spec/{graphql → integration/rails/graphql}/relay/connection_resolve_spec.rb +16 -0
  343. data/spec/{graphql → integration/rails/graphql}/relay/connection_type_spec.rb +0 -0
  344. data/spec/{graphql → integration/rails/graphql}/relay/edge_spec.rb +0 -0
  345. data/spec/{graphql → integration/rails/graphql}/relay/mutation_spec.rb +48 -0
  346. data/spec/{graphql → integration/rails/graphql}/relay/node_spec.rb +0 -0
  347. data/spec/{graphql → integration/rails/graphql}/relay/page_info_spec.rb +22 -22
  348. data/spec/{graphql → integration/rails/graphql}/relay/range_add_spec.rb +4 -4
  349. data/spec/{graphql → integration/rails/graphql}/relay/relation_connection_spec.rb +56 -27
  350. data/spec/{graphql → integration/rails/graphql}/schema_spec.rb +15 -11
  351. data/spec/{graphql → integration/rails/graphql}/tracing/active_support_notifications_tracing_spec.rb +16 -9
  352. data/spec/integration/rails/spec_helper.rb +25 -0
  353. data/spec/integration/tmp/app/graphql/types/family_type.rb +9 -0
  354. data/spec/spec_helper.rb +23 -39
  355. data/spec/support/dummy/data.rb +20 -17
  356. data/spec/support/dummy/schema.rb +315 -305
  357. data/spec/support/error_bubbling_helpers.rb +23 -0
  358. data/spec/support/jazz.rb +213 -46
  359. data/spec/support/lazy_helpers.rb +69 -27
  360. data/spec/support/new_relic.rb +3 -0
  361. data/spec/support/skylight.rb +3 -0
  362. data/spec/support/star_wars/schema.rb +131 -81
  363. data/spec/support/static_validation_helpers.rb +9 -5
  364. metadata +418 -261
  365. data/lib/graphql/language/comments.rb +0 -45
  366. data/lib/graphql/static_validation/arguments_validator.rb +0 -50
  367. data/spec/graphql/schema/member/has_fields_spec.rb +0 -129
  368. data/spec/rails_dependency_sanity_spec.rb +0 -14
@@ -48,7 +48,7 @@ describe GraphQL::Authorization do
48
48
  end
49
49
 
50
50
  def authorized?(object, context)
51
- super && object != :hide
51
+ super && object != :hide && object != :replace
52
52
  end
53
53
  end
54
54
 
@@ -159,7 +159,7 @@ describe GraphQL::Authorization do
159
159
  super && value != "a"
160
160
  end
161
161
 
162
- field :value, String, null: false, method: :object
162
+ field :value, String, null: false, method: :itself
163
163
  end
164
164
 
165
165
  module UnauthorizedInterface
@@ -186,7 +186,7 @@ describe GraphQL::Authorization do
186
186
  Box.new(value: Box.new(value: Box.new(value: Box.new(value: is_authed))))
187
187
  end
188
188
 
189
- field :value, String, null: false, method: :object
189
+ field :value, String, null: false, method: :itself
190
190
  end
191
191
 
192
192
  class IntegerObject < BaseObject
@@ -197,7 +197,7 @@ describe GraphQL::Authorization do
197
197
  is_allowed = !(ctx[:unauthorized_relay] || obj == ctx[:exclude_integer])
198
198
  Box.new(value: Box.new(value: is_allowed))
199
199
  end
200
- field :value, Integer, null: false, method: :object
200
+ field :value, Integer, null: false, method: :itself
201
201
  end
202
202
 
203
203
  class IntegerObjectEdge < GraphQL::Types::Relay::BaseEdge
@@ -237,7 +237,7 @@ describe GraphQL::Authorization do
237
237
 
238
238
  class Query < BaseObject
239
239
  field :hidden, Integer, null: false
240
- field :unauthorized, Integer, null: true, method: :object
240
+ field :unauthorized, Integer, null: true, method: :itself
241
241
  field :int2, Integer, null: true do
242
242
  argument :int, Integer, required: false
243
243
  argument :hidden, Integer, required: false
@@ -268,22 +268,22 @@ describe GraphQL::Authorization do
268
268
  end
269
269
 
270
270
  def empty_array; []; end
271
- field :hidden_object, HiddenObject, null: false, method: :itself
272
- field :hidden_interface, HiddenInterface, null: false, method: :itself
273
- field :hidden_default_interface, HiddenDefaultInterface, null: false, method: :itself
274
- field :hidden_connection, RelayObject.connection_type, null: :false, method: :empty_array
275
- field :hidden_edge, RelayObject.edge_type, null: :false, method: :edge_object
271
+ field :hidden_object, HiddenObject, null: false, resolver_method: :itself
272
+ field :hidden_interface, HiddenInterface, null: false, resolver_method: :itself
273
+ field :hidden_default_interface, HiddenDefaultInterface, null: false, resolver_method: :itself
274
+ field :hidden_connection, RelayObject.connection_type, null: :false, resolver_method: :empty_array
275
+ field :hidden_edge, RelayObject.edge_type, null: :false, resolver_method: :edge_object
276
276
 
277
277
  field :inaccessible, Integer, null: false, method: :object_id
278
- field :inaccessible_object, InaccessibleObject, null: false, method: :itself
279
- field :inaccessible_interface, InaccessibleInterface, null: false, method: :itself
280
- field :inaccessible_default_interface, InaccessibleDefaultInterface, null: false, method: :itself
281
- field :inaccessible_connection, RelayObject.connection_type, null: :false, method: :empty_array
282
- field :inaccessible_edge, RelayObject.edge_type, null: :false, method: :edge_object
278
+ field :inaccessible_object, InaccessibleObject, null: false, resolver_method: :itself
279
+ field :inaccessible_interface, InaccessibleInterface, null: false, resolver_method: :itself
280
+ field :inaccessible_default_interface, InaccessibleDefaultInterface, null: false, resolver_method: :itself
281
+ field :inaccessible_connection, RelayObject.connection_type, null: :false, resolver_method: :empty_array
282
+ field :inaccessible_edge, RelayObject.edge_type, null: :false, resolver_method: :edge_object
283
283
 
284
- field :unauthorized_object, UnauthorizedObject, null: true, method: :itself
285
- field :unauthorized_connection, RelayObject.connection_type, null: false, method: :array_with_item
286
- field :unauthorized_edge, RelayObject.edge_type, null: false, method: :edge_object
284
+ field :unauthorized_object, UnauthorizedObject, null: true, resolver_method: :itself
285
+ field :unauthorized_connection, RelayObject.connection_type, null: false, resolver_method: :array_with_item
286
+ field :unauthorized_edge, RelayObject.edge_type, null: false, resolver_method: :edge_object
287
287
 
288
288
  def edge_object
289
289
  OpenStruct.new(node: 100)
@@ -305,11 +305,11 @@ describe GraphQL::Authorization do
305
305
  [self, self]
306
306
  end
307
307
 
308
- field :unauthorized_lazy_check_box, UnauthorizedCheckBox, null: true, method: :unauthorized_lazy_box do
308
+ field :unauthorized_lazy_check_box, UnauthorizedCheckBox, null: true, resolver_method: :unauthorized_lazy_box do
309
309
  argument :value, String, required: true
310
310
  end
311
311
 
312
- field :unauthorized_interface, UnauthorizedInterface, null: true, method: :unauthorized_lazy_box do
312
+ field :unauthorized_interface, UnauthorizedInterface, null: true, resolver_method: :unauthorized_lazy_box do
313
313
  argument :value, String, required: true
314
314
  end
315
315
 
@@ -369,14 +369,22 @@ describe GraphQL::Authorization do
369
369
  end
370
370
 
371
371
  class Schema < GraphQL::Schema
372
+ if TESTING_INTERPRETER
373
+ use GraphQL::Execution::Interpreter
374
+ end
372
375
  query(Query)
373
376
  mutation(Mutation)
374
377
 
378
+ # Opt in to accessible? checks
379
+ query_analyzer GraphQL::Authorization::Analyzer
380
+
375
381
  lazy_resolve(Box, :value)
376
382
 
377
383
  def self.unauthorized_object(err)
378
384
  if err.object.respond_to?(:replacement)
379
385
  err.object.replacement
386
+ elsif err.object == :replace
387
+ 33
380
388
  else
381
389
  raise GraphQL::ExecutionError, "Unauthorized #{err.type.graphql_name}: #{err.object}"
382
390
  end
@@ -384,6 +392,18 @@ describe GraphQL::Authorization do
384
392
 
385
393
  # use GraphQL::Backtrace
386
394
  end
395
+
396
+ class SchemaWithFieldHook < GraphQL::Schema
397
+ query(Query)
398
+
399
+ def self.unauthorized_field(err)
400
+ if err.object == :replace
401
+ 42
402
+ else
403
+ raise GraphQL::ExecutionError, "Unauthorized field #{err.field.graphql_name} on #{err.type.graphql_name}: #{err.object}"
404
+ end
405
+ end
406
+ end
387
407
  end
388
408
 
389
409
  def auth_execute(*args)
@@ -598,7 +618,7 @@ describe GraphQL::Authorization do
598
618
  end
599
619
 
600
620
  describe "applying the authorized? method" do
601
- it "halts on unauthorized objects" do
621
+ it "halts on unauthorized objects, replacing the object with nil" do
602
622
  query = "{ unauthorizedObject { __typename } }"
603
623
  hidden_response = auth_execute(query, context: { hide: true })
604
624
  assert_nil hidden_response["data"].fetch("unauthorizedObject")
@@ -615,6 +635,65 @@ describe GraphQL::Authorization do
615
635
  end
616
636
  end
617
637
 
638
+ describe "field level authorization" do
639
+ describe "unauthorized field" do
640
+ describe "with an unauthorized field hook configured" do
641
+ describe "when the hook returns a value" do
642
+ it "replaces the response with the return value of the unauthorized field hook" do
643
+ query = "{ unauthorized }"
644
+ response = AuthTest::SchemaWithFieldHook.execute(query, root_value: :replace)
645
+ assert_equal 42, response["data"].fetch("unauthorized")
646
+ end
647
+ end
648
+
649
+ describe "when the field hook raises an error" do
650
+ it "returns nil" do
651
+ query = "{ unauthorized }"
652
+ response = AuthTest::SchemaWithFieldHook.execute(query, root_value: :hide)
653
+ assert_nil response["data"].fetch("unauthorized")
654
+ end
655
+
656
+ it "adds the error to the errors key" do
657
+ query = "{ unauthorized }"
658
+ response = AuthTest::SchemaWithFieldHook.execute(query, root_value: :hide)
659
+ assert_equal ["Unauthorized field unauthorized on Query: hide"], response["errors"].map { |e| e["message"] }
660
+ end
661
+ end
662
+ end
663
+
664
+ describe "with an unauthorized field hook not configured" do
665
+ describe "When the object hook replaces the field" do
666
+ it "delegates to the unauthorized object hook, which replaces the object" do
667
+ query = "{ unauthorized }"
668
+ response = AuthTest::Schema.execute(query, root_value: :replace)
669
+ assert_equal 33, response["data"].fetch("unauthorized")
670
+ end
671
+ end
672
+ describe "When the object hook raises an error" do
673
+ it "returns nil" do
674
+ query = "{ unauthorized }"
675
+ response = AuthTest::Schema.execute(query, root_value: :hide)
676
+ assert_nil response["data"].fetch("unauthorized")
677
+ end
678
+
679
+ it "adds the error to the errors key" do
680
+ query = "{ unauthorized }"
681
+ response = AuthTest::Schema.execute(query, root_value: :hide)
682
+ assert_equal ["Unauthorized Query: hide"], response["errors"].map { |e| e["message"] }
683
+ end
684
+ end
685
+ end
686
+ end
687
+
688
+ describe "authorized field" do
689
+ it "returns the field data" do
690
+ query = "{ unauthorized }"
691
+ response = AuthTest::SchemaWithFieldHook.execute(query, root_value: 1)
692
+ assert_equal 1, response["data"].fetch("unauthorized")
693
+ end
694
+ end
695
+ end
696
+
618
697
  it "halts on unauthorized fields, using the parent object" do
619
698
  query = "{ unauthorized }"
620
699
  hidden_response = auth_execute(query, root_value: :hide)
@@ -658,7 +737,25 @@ describe GraphQL::Authorization do
658
737
  unauthorized_res = auth_execute(query, context: { unauthorized_relay: true })
659
738
  conn = unauthorized_res["data"].fetch("unauthorizedConnection")
660
739
  assert_equal "RelayObjectConnection", conn.fetch("__typename")
661
- assert_equal nil, conn.fetch("nodes")
740
+ # This is tricky: the previous behavior was to replace the _whole_
741
+ # list with `nil`. This was due to an implementation detail:
742
+ # The list field's return value (an array of integers) was wrapped
743
+ # _before_ returning, and during this wrapping, a cascading error
744
+ # caused the entire field to be nilled out.
745
+ #
746
+ # In the interpreter, each list item is contained and the error doesn't propagate
747
+ # up to the whole list.
748
+ #
749
+ # Originally, I thought that this was a _feature_ that obscured list entries.
750
+ # But really, look at the test below: you don't get this "feature" if
751
+ # you use `edges { node }`, so it can't be relied on in any way.
752
+ #
753
+ # All that to say, in the interpreter, `nodes` and `edges { node }` behave
754
+ # the same.
755
+ #
756
+ # TODO revisit the docs for this.
757
+ failed_nodes_value = TESTING_INTERPRETER ? [nil] : nil
758
+ assert_equal failed_nodes_value, conn.fetch("nodes")
662
759
  assert_equal [{"node" => nil, "__typename" => "RelayObjectEdge"}], conn.fetch("edges")
663
760
 
664
761
  edge = unauthorized_res["data"].fetch("unauthorizedEdge")
@@ -667,7 +764,7 @@ describe GraphQL::Authorization do
667
764
 
668
765
  unauthorized_object_paths = [
669
766
  ["unauthorizedConnection", "edges", 0, "node"],
670
- ["unauthorizedConnection", "nodes"],
767
+ TESTING_INTERPRETER ? ["unauthorizedConnection", "nodes", 0] : ["unauthorizedConnection", "nodes"],
671
768
  ["unauthorizedEdge", "node"]
672
769
  ]
673
770
 
@@ -11,7 +11,7 @@ describe GraphQL::BaseType do
11
11
  end
12
12
 
13
13
  it "can be compared" do
14
- obj_type = Dummy::MilkType
14
+ obj_type = Dummy::Milk.graphql_definition
15
15
  assert_equal(!GraphQL::INT_TYPE, !GraphQL::INT_TYPE)
16
16
  refute_equal(!GraphQL::FLOAT_TYPE, GraphQL::FLOAT_TYPE)
17
17
  assert_equal(
@@ -25,7 +25,7 @@ describe GraphQL::BaseType do
25
25
  end
26
26
 
27
27
  it "Accepts arbitrary metadata" do
28
- assert_equal ["Cheese"], Dummy::CheeseType.metadata[:class_names]
28
+ assert_equal ["Cheese"], Dummy::Cheese.graphql_definition.metadata[:class_names]
29
29
  end
30
30
 
31
31
  describe "#name" do
@@ -63,7 +63,7 @@ describe GraphQL::BaseType do
63
63
  end
64
64
 
65
65
  describe "forwards-compat with new api" do
66
- let(:type_defn) { Dummy::CheeseType }
66
+ let(:type_defn) { Dummy::Cheese.graphql_definition }
67
67
  it "responds to new methods" do
68
68
  assert_equal "Cheese", type_defn.graphql_name
69
69
  assert_equal type_defn, type_defn.graphql_definition
@@ -112,7 +112,9 @@ describe GraphQL::BaseType do
112
112
  schema = GraphQL::Schema.define(query: query_root)
113
113
 
114
114
  expected = <<TYPE
115
- # A blog post
115
+ """
116
+ A blog post
117
+ """
116
118
  type Post {
117
119
  body: String!
118
120
  id: ID!
@@ -2,7 +2,7 @@
2
2
  require "spec_helper"
3
3
 
4
4
  describe GraphQL::EnumType do
5
- let(:enum) { Dummy::DairyAnimalEnum }
5
+ let(:enum) { Dummy::DairyAnimal.graphql_definition }
6
6
 
7
7
  it "coerces names to underlying values" do
8
8
  assert_equal("YAK", enum.coerce_isolated_input("YAK"))
@@ -130,6 +130,11 @@ describe GraphQL::EnumType do
130
130
  assert_equal({ "COW" => cow, "GOAT" => goat }, enum.values)
131
131
  end
132
132
 
133
+ it "values respond to graphql_name" do
134
+ cow = GraphQL::EnumType::EnumValue.define(name: "COW")
135
+ assert_equal("COW", cow.graphql_name)
136
+ end
137
+
133
138
  describe "#dup" do
134
139
  it "copies the values map without altering the original" do
135
140
  enum_2 = enum.dup
@@ -236,7 +236,7 @@ describe GraphQL::Execution::Execute do
236
236
  end
237
237
 
238
238
  describe "tracing" do
239
- if rails_should_be_installed?
239
+ if defined?(Rails)
240
240
  it "emits traces" do
241
241
  query_string = <<-GRAPHQL
242
242
  query Bases($id1: ID!, $id2: ID!){
@@ -280,20 +280,20 @@ describe GraphQL::Execution::Execute do
280
280
  field_3_lazy, field_4_lazy,
281
281
  query_lazy, multiplex = exec_traces
282
282
 
283
- assert_equal ["b1"], field_1_eager[:context].path
284
- assert_equal ["b2"], field_2_eager[:context].path
283
+ assert_equal ["b1"], field_1_eager[:path]
284
+ assert_equal ["b2"], field_2_eager[:path]
285
285
  assert_instance_of GraphQL::Query, query_eager[:query]
286
286
 
287
287
  assert_equal [first_id.to_s, last_id.to_s], lazy_loader[:ids]
288
288
  assert_equal StarWars::Base, lazy_loader[:model]
289
289
 
290
- assert_equal ["b1", "name"], field_3_eager[:context].path
291
- assert_equal ["b1"], field_1_lazy[:context].path
292
- assert_equal ["b2", "name"], field_4_eager[:context].path
293
- assert_equal ["b2"], field_2_lazy[:context].path
290
+ assert_equal ["b1", "name"], field_3_eager[:path]
291
+ assert_equal ["b1"], field_1_lazy[:path]
292
+ assert_equal ["b2", "name"], field_4_eager[:path]
293
+ assert_equal ["b2"], field_2_lazy[:path]
294
294
 
295
- assert_equal ["b1", "name"], field_3_lazy[:context].path
296
- assert_equal ["b2", "name"], field_4_lazy[:context].path
295
+ assert_equal ["b1", "name"], field_3_lazy[:path]
296
+ assert_equal ["b2", "name"], field_4_lazy[:path]
297
297
  assert_instance_of GraphQL::Query, query_lazy[:query]
298
298
 
299
299
  assert_instance_of GraphQL::Execution::Multiplex, multiplex[:multiplex]
@@ -51,6 +51,17 @@ describe GraphQL::Schema do
51
51
  class FirstInstrumenter < LogInstrumenter; end
52
52
  class SecondInstrumenter < LogInstrumenter; end
53
53
 
54
+ class ExecutionErrorInstrumenter
55
+ def before_query(query)
56
+ if query.context[:raise_execution_error]
57
+ raise GraphQL::ExecutionError, "Raised from instrumenter before_query"
58
+ end
59
+ end
60
+
61
+ def after_query(query)
62
+ end
63
+ end
64
+
54
65
  let(:query_type) {
55
66
  GraphQL::ObjectType.define do
56
67
  name "Query"
@@ -67,6 +78,7 @@ describe GraphQL::Schema do
67
78
  query(spec.query_type)
68
79
  instrument(:query, FirstInstrumenter.new)
69
80
  instrument(:query, SecondInstrumenter.new)
81
+ instrument(:query, ExecutionErrorInstrumenter.new)
70
82
  end
71
83
  }
72
84
 
@@ -95,6 +107,13 @@ describe GraphQL::Schema do
95
107
  assert context[:second_instrumenter_did_begin]
96
108
  assert context[:second_instrumenter_did_end]
97
109
  end
110
+
111
+ it "rescues execution errors from before_query" do
112
+ context = {raise_execution_error: true}
113
+ res = schema.execute(" { int(value: 2) } ", context: context)
114
+ assert_equal "Raised from instrumenter before_query", res["errors"].first["message"]
115
+ refute res.key?("data"), "The query doesn't run"
116
+ end
98
117
  end
99
118
 
100
119
  describe "within a multiplex" do