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
@@ -29,17 +29,20 @@ describe GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped do
29
29
  {
30
30
  "message"=>"Default value for $badInt doesn't match type Int",
31
31
  "locations"=>[{"line"=>6, "column"=>7}],
32
- "fields"=>["query getCheese"],
32
+ "path"=>["query getCheese"],
33
+ "extensions"=>{"code"=>"defaultValueInvalidType", "variableName"=>"badInt", "typeName"=>"Int"}
33
34
  },
34
35
  {
35
36
  "message"=>"Default value for $badInput doesn't match type DairyProductInput",
36
37
  "locations"=>[{"line"=>8, "column"=>7}],
37
- "fields"=>["query getCheese"],
38
+ "path"=>["query getCheese"],
39
+ "extensions"=>{"code"=>"defaultValueInvalidType", "variableName"=>"badInput", "typeName"=>"DairyProductInput"}
38
40
  },
39
41
  {
40
42
  "message"=>"Non-null variable $nonNull can't have a default value",
41
43
  "locations"=>[{"line"=>9, "column"=>7}],
42
- "fields"=>["query getCheese"],
44
+ "path"=>["query getCheese"],
45
+ "extensions"=>{"code"=>"defaultValueInvalidOnNonNullVariable", "variableName"=>"nonNull"}
43
46
  }
44
47
  ]
45
48
  assert_equal(expected, errors)
@@ -116,17 +119,20 @@ describe GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped do
116
119
  {
117
120
  "message"=>"Non-null variable $a can't have a default value",
118
121
  "locations"=>[{"line"=>3, "column"=>11}],
119
- "fields"=>["query getCheese"]
122
+ "path"=>["query getCheese"],
123
+ "extensions"=>{"code"=>"defaultValueInvalidOnNonNullVariable", "variableName"=>"a"}
120
124
  },
121
125
  {
122
126
  "message"=>"Non-null variable $b can't have a default value",
123
127
  "locations"=>[{"line"=>4, "column"=>11}],
124
- "fields"=>["query getCheese"]
128
+ "path"=>["query getCheese"],
129
+ "extensions"=>{"code"=>"defaultValueInvalidOnNonNullVariable", "variableName"=>"b"}
125
130
  },
126
131
  {
127
132
  "message"=>"Default value for $c doesn't match type ComplexInput",
128
133
  "locations"=>[{"line"=>5, "column"=>11}],
129
- "fields"=>["query getCheese"]
134
+ "path"=>["query getCheese"],
135
+ "extensions"=>{"code"=>"defaultValueInvalidType", "variableName"=>"c", "typeName"=>"ComplexInput"}
130
136
  }
131
137
  ]
132
138
 
@@ -182,7 +188,8 @@ describe GraphQL::StaticValidation::VariableDefaultValuesAreCorrectlyTyped do
182
188
  assert_includes errors, {
183
189
  "message"=> "cannot coerce to Float",
184
190
  "locations"=>[{"line"=>3, "column"=>9}],
185
- "fields"=>["query"]
191
+ "path"=>["query"],
192
+ "extensions"=>{"code"=>"defaultValueInvalidType", "variableName"=>"value", "typeName"=>"Time"}
186
193
  }
187
194
  end
188
195
  end
@@ -43,22 +43,26 @@ describe GraphQL::StaticValidation::VariableUsagesAreAllowed do
43
43
  {
44
44
  "message"=>"Nullability mismatch on variable $badInt and argument id (Int / Int!)",
45
45
  "locations"=>[{"line"=>14, "column"=>28}],
46
- "fields"=>["query getCheese", "badCheese", "id"],
46
+ "path"=>["query getCheese", "badCheese", "id"],
47
+ "extensions"=>{"code"=>"variableMismatch", "variableName"=>"badInt", "typeName"=>"Int", "argumentName"=>"id", "errorMessage"=>"Nullability mismatch"}
47
48
  },
48
49
  {
49
50
  "message"=>"Type mismatch on variable $badStr and argument id (String! / Int!)",
50
51
  "locations"=>[{"line"=>15, "column"=>28}],
51
- "fields"=>["query getCheese", "badStrCheese", "id"],
52
+ "path"=>["query getCheese", "badStrCheese", "id"],
53
+ "extensions"=>{"code"=>"variableMismatch", "variableName"=>"badStr", "typeName"=>"String!", "argumentName"=>"id", "errorMessage"=>"Type mismatch"}
52
54
  },
53
55
  {
54
56
  "message"=>"Nullability mismatch on variable $badAnimals and argument source ([DairyAnimal]! / [DairyAnimal!]!)",
55
57
  "locations"=>[{"line"=>18, "column"=>30}],
56
- "fields"=>["query getCheese", "cheese", "other", "source"],
58
+ "path"=>["query getCheese", "cheese", "other", "source"],
59
+ "extensions"=>{"code"=>"variableMismatch", "variableName"=>"badAnimals", "typeName"=>"[DairyAnimal]!", "argumentName"=>"source", "errorMessage"=>"Nullability mismatch"}
57
60
  },
58
61
  {
59
62
  "message"=>"List dimension mismatch on variable $deepAnimals and argument source ([[DairyAnimal!]!]! / [DairyAnimal!]!)",
60
63
  "locations"=>[{"line"=>19, "column"=>32}],
61
- "fields"=>["query getCheese", "cheese", "tooDeep", "source"],
64
+ "path"=>["query getCheese", "cheese", "tooDeep", "source"],
65
+ "extensions"=>{"code"=>"variableMismatch", "variableName"=>"deepAnimals", "typeName"=>"[[DairyAnimal!]!]!", "argumentName"=>"source", "errorMessage"=>"List dimension mismatch"}
62
66
  }
63
67
  ]
64
68
  assert_equal(expected, errors)
@@ -22,25 +22,29 @@ describe GraphQL::StaticValidation::VariablesAreInputTypes do
22
22
  assert_includes(errors, {
23
23
  "message"=>"AnimalProduct isn't a valid input type (on $interface)",
24
24
  "locations"=>[{"line"=>5, "column"=>7}],
25
- "fields"=>["query getCheese"],
25
+ "path"=>["query getCheese"],
26
+ "extensions"=> {"code"=>"variableRequiresValidType", "typeName"=>"AnimalProduct", "variableName"=>"interface"}
26
27
  })
27
28
 
28
29
  assert_includes(errors, {
29
30
  "message"=>"Milk isn't a valid input type (on $object)",
30
31
  "locations"=>[{"line"=>6, "column"=>7}],
31
- "fields"=>["query getCheese"],
32
+ "path"=>["query getCheese"],
33
+ "extensions"=>{"code"=>"variableRequiresValidType", "typeName"=>"Milk", "variableName"=>"object"}
32
34
  })
33
35
 
34
36
  assert_includes(errors, {
35
37
  "message"=>"Cheese isn't a valid input type (on $objects)",
36
38
  "locations"=>[{"line"=>7, "column"=>7}],
37
- "fields"=>["query getCheese"],
39
+ "path"=>["query getCheese"],
40
+ "extensions"=>{"code"=>"variableRequiresValidType", "typeName"=>"Cheese", "variableName"=>"objects"}
38
41
  })
39
42
 
40
43
  assert_includes(errors, {
41
44
  "message"=>"Nonsense isn't a defined input type (on $unknownType)",
42
45
  "locations"=>[{"line"=>8, "column"=>7}],
43
- "fields"=>["query getCheese"],
46
+ "path"=>["query getCheese"],
47
+ "extensions"=>{"code"=>"variableRequiresValidType", "typeName"=>"Nonsense", "variableName"=>"unknownType"}
44
48
  })
45
49
  end
46
50
 
@@ -42,20 +42,40 @@ describe GraphQL::StaticValidation::VariablesAreUsedAndDefined do
42
42
  {
43
43
  "message"=>"Variable $notUsedVar is declared by getCheese but not used",
44
44
  "locations"=>[{"line"=>2, "column"=>5}],
45
- "fields"=>["query getCheese"],
45
+ "path"=>["query getCheese"],
46
+ "extensions"=>{"code"=>"variableNotUsed", "variableName"=>"notUsedVar"}
46
47
  },
47
48
  {
48
49
  "message"=>"Variable $undefinedVar is used by getCheese but not declared",
49
50
  "locations"=>[{"line"=>19, "column"=>22}],
50
- "fields"=>["query getCheese", "c3", "id"],
51
+ "path"=>["query getCheese", "c3", "id"],
52
+ "extensions"=>{"code"=>"variableNotDefined", "variableName"=>"undefinedVar"}
51
53
  },
52
54
  {
53
55
  "message"=>"Variable $undefinedFragmentVar is used by innerCheeseFields but not declared",
54
56
  "locations"=>[{"line"=>29, "column"=>22}],
55
- "fields"=>["fragment innerCheeseFields", "c4", "id"],
57
+ "path"=>["fragment innerCheeseFields", "c4", "id"],
58
+ "extensions"=>{"code"=>"variableNotDefined", "variableName"=>"undefinedFragmentVar"}
56
59
  },
57
60
  ]
58
61
 
59
62
  assert_equal(expected, errors)
60
63
  end
64
+
65
+ describe "usages in directives on fragment spreads" do
66
+ let(:query_string) {
67
+ <<-GRAPHQL
68
+ query($f: Boolean!){
69
+ ...F @include(if: $f)
70
+ }
71
+ fragment F on Query {
72
+ __typename
73
+ }
74
+ GRAPHQL
75
+ }
76
+
77
+ it "finds usages" do
78
+ assert_equal([], errors)
79
+ end
80
+ end
61
81
  end
@@ -1,19 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require "spec_helper"
3
3
 
4
- class TypeCheckValidator
5
- def self.checks
6
- @checks ||= []
7
- end
8
-
9
- def validate(context)
10
- self.class.checks.clear
11
- context.visitor[GraphQL::Language::Nodes::Field] << ->(node, parent) {
12
- self.class.checks << context.object_types.map {|t| t.name || t.kind.name }
13
- }
14
- end
15
- end
16
-
17
4
  describe GraphQL::StaticValidation::TypeStack do
18
5
  let(:query_string) {%|
19
6
  query getCheese {
@@ -22,17 +9,21 @@ describe GraphQL::StaticValidation::TypeStack do
22
9
  fragment edibleFields on Edible { fatContent @skip(if: false)}
23
10
  |}
24
11
 
25
- let(:validator) { GraphQL::StaticValidation::Validator.new(schema: Dummy::Schema, rules: [TypeCheckValidator]) }
26
- let(:query) { GraphQL::Query.new(Dummy::Schema, query_string) }
27
-
28
-
29
12
  it "stores up types" do
30
- validator.validate(query)
13
+ document = GraphQL.parse(query_string)
14
+ visitor = GraphQL::Language::Visitor.new(document)
15
+ type_stack = GraphQL::StaticValidation::TypeStack.new(Dummy::Schema, visitor)
16
+ checks = []
17
+ visitor[GraphQL::Language::Nodes::Field].enter << ->(node, parent) {
18
+ checks << type_stack.object_types.map {|t| t.name || t.kind.name }
19
+ }
20
+ visitor.visit
21
+
31
22
  expected = [
32
23
  ["Query", "Cheese"],
33
24
  ["Query", "Cheese", "NON_NULL"],
34
25
  ["Edible", "NON_NULL"]
35
26
  ]
36
- assert_equal(expected, TypeCheckValidator.checks)
27
+ assert_equal(expected, checks)
37
28
  end
38
29
  end
@@ -34,7 +34,8 @@ describe GraphQL::StaticValidation::Validator do
34
34
  expected_errors = [{
35
35
  "message" => "Variable $undefinedVar is used by but not declared",
36
36
  "locations" => [{"line" => 1, "column" => 14, "filename" => "not_a_real.graphql"}],
37
- "fields" => ["query", "cheese", "id"]
37
+ "path" => ["query", "cheese", "id"],
38
+ "extensions"=>{"code"=>"variableNotDefined", "variableName"=>"undefinedVar"}
38
39
  }]
39
40
  assert_equal expected_errors, errors
40
41
  end
@@ -115,7 +116,8 @@ describe GraphQL::StaticValidation::Validator do
115
116
  {
116
117
  "message"=>"Fragment cheeseFields contains an infinite loop",
117
118
  "locations"=>[{"line"=>10, "column"=>9}],
118
- "fields"=>["fragment cheeseFields"]
119
+ "path"=>["fragment cheeseFields"],
120
+ "extensions"=>{"code"=>"infiniteLoop", "fragmentName"=>"cheeseFields"}
119
121
  }
120
122
  ]
121
123
  assert_equal(expected, errors)
@@ -153,4 +155,50 @@ describe GraphQL::StaticValidation::Validator do
153
155
  end
154
156
  end
155
157
  end
158
+
159
+ describe "Custom ruleset" do
160
+ let(:query_string) { "
161
+ fragment Thing on Cheese {
162
+ __typename
163
+ similarCheese(source: COW)
164
+ }
165
+ "
166
+ }
167
+
168
+ let(:rules) {
169
+ # This is from graphql-client, eg
170
+ # https://github.com/github/graphql-client/blob/c86fc05d7eba2370452592bb93572caced4123af/lib/graphql/client.rb#L168
171
+ GraphQL::StaticValidation::ALL_RULES - [
172
+ GraphQL::StaticValidation::FragmentsAreUsed,
173
+ GraphQL::StaticValidation::FieldsHaveAppropriateSelections
174
+ ]
175
+ }
176
+ let(:validator) { GraphQL::StaticValidation::Validator.new(schema: Dummy::Schema, rules: rules) }
177
+
178
+ it "runs the specified rules" do
179
+ assert_equal 0, errors.size
180
+ end
181
+
182
+ describe "With a legacy-style rule" do
183
+ # GraphQL-Pro's operation store uses this
184
+ class ValidatorSpecLegacyRule
185
+ include GraphQL::StaticValidation::Error::ErrorHelper
186
+ def validate(ctx)
187
+ ctx.visitor[GraphQL::Language::Nodes::OperationDefinition] << ->(n, _p) {
188
+ ctx.errors << error("Busted!", n, context: ctx)
189
+ }
190
+ end
191
+ end
192
+
193
+ let(:rules) {
194
+ GraphQL::StaticValidation::ALL_RULES + [ValidatorSpecLegacyRule]
195
+ }
196
+
197
+ let(:query_string) { "{ __typename }"}
198
+
199
+ it "runs the rule" do
200
+ assert_equal ["Busted!"], errors.map { |e| e["message"] }
201
+ end
202
+ end
203
+ end
156
204
  end
@@ -109,32 +109,32 @@ class ClassBasedInMemoryBackend < InMemoryBackend
109
109
  end
110
110
 
111
111
  class Subscription < GraphQL::Schema::Object
112
+ if TESTING_INTERPRETER
113
+ extend GraphQL::Subscriptions::SubscriptionRoot
114
+ else
115
+ # Stub methods are required
116
+ [:payload, :event, :my_event].each do |m|
117
+ define_method(m) { |*a| nil }
118
+ end
119
+ end
112
120
  field :payload, Payload, null: false do
113
121
  argument :id, ID, required: true
114
122
  end
115
123
 
116
- def payload(id:)
117
- object
118
- end
119
-
120
124
  field :event, Payload, null: true do
121
125
  argument :stream, StreamInput, required: false
122
126
  end
123
127
 
124
- def event(stream: nil)
125
- object
126
- end
127
-
128
128
  field :my_event, Payload, null: true, subscription_scope: :me do
129
129
  argument :type, PayloadType, required: false
130
130
  end
131
131
 
132
- def my_event(type: nil)
133
- object
132
+ field :failed_event, Payload, null: false do
133
+ argument :id, ID, required: true
134
134
  end
135
135
 
136
- field :failed_event, Payload, null: false, resolve: ->(o, a, c) { raise GraphQL::ExecutionError.new("unauthorized") } do
137
- argument :id, ID, required: true
136
+ def failed_event(id:)
137
+ raise GraphQL::ExecutionError.new("unauthorized")
138
138
  end
139
139
  end
140
140
 
@@ -146,6 +146,9 @@ class ClassBasedInMemoryBackend < InMemoryBackend
146
146
  query(Query)
147
147
  subscription(Subscription)
148
148
  use InMemoryBackend::Subscriptions, extra: 123
149
+ if TESTING_INTERPRETER
150
+ use GraphQL::Execution::Interpreter
151
+ end
149
152
  end
150
153
  end
151
154
 
@@ -236,9 +239,17 @@ describe GraphQL::Subscriptions do
236
239
  res_1 = schema.execute(query_str, context: { socket: "1" }, variables: { "id" => "100" }, root_value: root_object)
237
240
  res_2 = schema.execute(query_str, context: { socket: "2" }, variables: { "id" => "200" }, root_value: root_object)
238
241
 
242
+ # This difference is because of how `SKIP` is handled.
243
+ # Honestly the new way is probably better, since it puts a value there.
244
+ empty_response = if TESTING_INTERPRETER && schema == ClassBasedInMemoryBackend::Schema
245
+ {}
246
+ else
247
+ nil
248
+ end
249
+
239
250
  # Initial response is nil, no broadcasts yet
240
- assert_equal(nil, res_1["data"])
241
- assert_equal(nil, res_2["data"])
251
+ assert_equal(empty_response, res_1["data"])
252
+ assert_equal(empty_response, res_2["data"])
242
253
  assert_equal [], deliveries["1"]
243
254
  assert_equal [], deliveries["2"]
244
255
 
@@ -410,12 +421,12 @@ describe GraphQL::Subscriptions do
410
421
  failedEvent(id: $id) { str, int }
411
422
  }
412
423
  GRAPHQL
413
-
414
424
  assert_equal nil, res["data"]
415
425
  assert_equal "unauthorized", res["errors"][0]["message"]
416
426
 
417
427
  # this is to make sure nothing actually got subscribed.. but I don't have any idea better than checking its instance variable
418
- assert_equal 0, schema.subscriptions.instance_variable_get(:@subscriptions).size
428
+ subscriptions = schema.subscriptions.instance_variable_get(:@subscriptions)
429
+ assert_equal 0, subscriptions.size
419
430
  end
420
431
 
421
432
  it "lets unhandled errors crash" do
@@ -14,11 +14,22 @@ describe GraphQL::Tracing::NewRelicTracing do
14
14
  class SchemaWithoutTransactionName < GraphQL::Schema
15
15
  query(Query)
16
16
  use(GraphQL::Tracing::NewRelicTracing)
17
+ if TESTING_INTERPRETER
18
+ use GraphQL::Execution::Interpreter
19
+ end
17
20
  end
18
21
 
19
22
  class SchemaWithTransactionName < GraphQL::Schema
20
23
  query(Query)
21
24
  use(GraphQL::Tracing::NewRelicTracing, set_transaction_name: true)
25
+ if TESTING_INTERPRETER
26
+ use GraphQL::Execution::Interpreter
27
+ end
28
+ end
29
+
30
+ class SchemaWithScalarTrace < GraphQL::Schema
31
+ query(Query)
32
+ use(GraphQL::Tracing::NewRelicTracing, trace_scalars: true)
22
33
  end
23
34
  end
24
35
 
@@ -44,4 +55,9 @@ describe GraphQL::Tracing::NewRelicTracing do
44
55
  NewRelicTest::SchemaWithoutTransactionName.execute "{ int }", context: { set_new_relic_transaction_name: true }
45
56
  assert_equal ["GraphQL/query.anonymous"], NewRelic::TRANSACTION_NAMES
46
57
  end
58
+
59
+ it "traces scalars when trace_scalars is true" do
60
+ NewRelicTest::SchemaWithScalarTrace.execute "query X { int }"
61
+ assert_includes NewRelic::EXECUTION_SCOPES, "GraphQL/Query/int"
62
+ end
47
63
  end
@@ -17,7 +17,7 @@ describe GraphQL::Tracing::PlatformTracing do
17
17
  }
18
18
 
19
19
  def platform_field_key(type, field)
20
- "#{type.name[0]}.#{field.name[0]}"
20
+ "#{type.graphql_name[0]}.#{field.graphql_name[0]}"
21
21
  end
22
22
 
23
23
  def platform_trace(platform_key, key, data)
@@ -39,17 +39,25 @@ describe GraphQL::Tracing::PlatformTracing do
39
39
 
40
40
  it "calls the platform's own method with its own keys" do
41
41
  schema.execute(" { cheese(id: 1) { flavor } }")
42
- expected_trace = [
43
- "em",
44
- "l",
45
- "p",
46
- "v",
47
- "am",
48
- "aq",
49
- "eq",
50
- "Q.c", # notice that the flavor is skipped
51
- "eql",
52
- ]
42
+ # This is different because schema/member/instrumentation
43
+ # calls `irep_selection` which causes the query to be parsed.
44
+ # But interpreter doesn't require parsing until later.
45
+ expected_trace = if TESTING_INTERPRETER
46
+ [
47
+ "em",
48
+ "am",
49
+ "l",
50
+ "p",
51
+ "v",
52
+ "aq",
53
+ "eq",
54
+ "Q.c", # notice that the flavor is skipped
55
+ "eql",
56
+ ]
57
+ else
58
+ ["em", "l", "p", "v", "am", "aq", "eq", "Q.c", "eql"]
59
+ end
60
+
53
61
  assert_equal expected_trace, CustomPlatformTracer::TRACE
54
62
  end
55
63
  end
@@ -67,18 +75,25 @@ describe GraphQL::Tracing::PlatformTracing do
67
75
 
68
76
  it "only traces traceTrue, not traceFalse or traceNil" do
69
77
  schema.execute(" { tracingScalar { traceNil traceFalse traceTrue } }")
70
- expected_trace = [
71
- "em",
72
- "l",
73
- "p",
74
- "v",
75
- "am",
76
- "aq",
77
- "eq",
78
- "Q.t",
79
- "T.t",
80
- "eql",
81
- ]
78
+ # This is different because schema/member/instrumentation
79
+ # calls `irep_selection` which causes the query to be parsed.
80
+ # But interpreter doesn't require parsing until later.
81
+ expected_trace = if TESTING_INTERPRETER
82
+ [
83
+ "em",
84
+ "am",
85
+ "l",
86
+ "p",
87
+ "v",
88
+ "aq",
89
+ "eq",
90
+ "Q.t",
91
+ "T.t",
92
+ "eql",
93
+ ]
94
+ else
95
+ ["em", "l", "p", "v", "am", "aq", "eq", "Q.t", "T.t", "eql"]
96
+ end
82
97
  assert_equal expected_trace, CustomPlatformTracer::TRACE
83
98
  end
84
99
  end
@@ -96,19 +111,26 @@ describe GraphQL::Tracing::PlatformTracing do
96
111
 
97
112
  it "traces traceTrue and traceNil but not traceFalse" do
98
113
  schema.execute(" { tracingScalar { traceNil traceFalse traceTrue } }")
99
- expected_trace = [
100
- "em",
101
- "l",
102
- "p",
103
- "v",
104
- "am",
105
- "aq",
106
- "eq",
107
- "Q.t",
108
- "T.t",
109
- "T.t",
110
- "eql",
111
- ]
114
+ # This is different because schema/member/instrumentation
115
+ # calls `irep_selection` which causes the query to be parsed.
116
+ # But interpreter doesn't require parsing until later.
117
+ expected_trace = if TESTING_INTERPRETER
118
+ [
119
+ "em",
120
+ "am",
121
+ "l",
122
+ "p",
123
+ "v",
124
+ "aq",
125
+ "eq",
126
+ "Q.t",
127
+ "T.t",
128
+ "T.t",
129
+ "eql",
130
+ ]
131
+ else
132
+ ["em", "l", "p", "v", "am", "aq", "eq", "Q.t", "T.t", "T.t", "eql"]
133
+ end
112
134
  assert_equal expected_trace, CustomPlatformTracer::TRACE
113
135
  end
114
136
  end
@@ -14,6 +14,9 @@ describe GraphQL::Tracing::PrometheusTracing do
14
14
 
15
15
  class Schema < GraphQL::Schema
16
16
  query Query
17
+ if TESTING_INTERPRETER
18
+ use GraphQL::Execution::Interpreter
19
+ end
17
20
  end
18
21
  end
19
22
 
@@ -14,11 +14,22 @@ describe GraphQL::Tracing::SkylightTracing do
14
14
  class SchemaWithoutTransactionName < GraphQL::Schema
15
15
  query(Query)
16
16
  use(GraphQL::Tracing::SkylightTracing)
17
+ if TESTING_INTERPRETER
18
+ use GraphQL::Execution::Interpreter
19
+ end
17
20
  end
18
21
 
19
22
  class SchemaWithTransactionName < GraphQL::Schema
20
23
  query(Query)
21
24
  use(GraphQL::Tracing::SkylightTracing, set_endpoint_name: true)
25
+ if TESTING_INTERPRETER
26
+ use GraphQL::Execution::Interpreter
27
+ end
28
+ end
29
+
30
+ class SchemaWithScalarTrace < GraphQL::Schema
31
+ query(Query)
32
+ use(GraphQL::Tracing::SkylightTracing, trace_scalars: true)
22
33
  end
23
34
  end
24
35
 
@@ -44,4 +55,9 @@ describe GraphQL::Tracing::SkylightTracing do
44
55
  SkylightTest::SchemaWithoutTransactionName.execute "{ int }", context: { set_skylight_endpoint_name: true }
45
56
  assert_equal ["GraphQL/query.<anonymous>"], Skylight::ENDPOINT_NAMES
46
57
  end
58
+
59
+ it "traces scalars when trace_scalars is true" do
60
+ SkylightTest::SchemaWithScalarTrace.execute "query X { int }"
61
+ assert_includes Skylight::TITLE_NAMES, "graphql.Query.int"
62
+ end
47
63
  end
@@ -11,8 +11,7 @@ describe GraphQL::Types::ISO8601DateTime do
11
11
  field :minute, Integer, null: false
12
12
  field :second, Integer, null: false
13
13
  field :zone, String, null: false
14
- # Use method: :object so that the DateTime instance is passed to the scalar
15
- field :iso8601, GraphQL::Types::ISO8601DateTime, null: false, method: :object
14
+ field :iso8601, GraphQL::Types::ISO8601DateTime, null: false, method: :itself
16
15
  end
17
16
 
18
17
  class Query < GraphQL::Schema::Object
@@ -29,6 +28,9 @@ describe GraphQL::Types::ISO8601DateTime do
29
28
 
30
29
  class Schema < GraphQL::Schema
31
30
  query(Query)
31
+ if TESTING_INTERPRETER
32
+ use GraphQL::Execution::Interpreter
33
+ end
32
34
  end
33
35
  end
34
36
 
@@ -90,6 +92,31 @@ describe GraphQL::Types::ISO8601DateTime do
90
92
  full_res = DateTimeTest::Schema.execute(query_str, variables: { date: date_str })
91
93
  assert_equal date_str, full_res["data"]["parseDate"]["iso8601"]
92
94
  end
95
+
96
+ describe "with time_precision = 3 (i.e. 'with milliseconds')" do
97
+ before do
98
+ @tp = GraphQL::Types::ISO8601DateTime.time_precision
99
+ GraphQL::Types::ISO8601DateTime.time_precision = 3
100
+ end
101
+
102
+ after do
103
+ GraphQL::Types::ISO8601DateTime.time_precision = @tp
104
+ end
105
+
106
+ it "returns a string" do
107
+ query_str = <<-GRAPHQL
108
+ query($date: ISO8601DateTime!){
109
+ parseDate(date: $date) {
110
+ iso8601
111
+ }
112
+ }
113
+ GRAPHQL
114
+
115
+ date_str = "2010-02-02T22:30:30.123-06:00"
116
+ full_res = DateTimeTest::Schema.execute(query_str, variables: { date: date_str })
117
+ assert_equal date_str, full_res["data"]["parseDate"]["iso8601"]
118
+ end
119
+ end
93
120
  end
94
121
 
95
122
  describe "structure" do
@@ -169,7 +169,7 @@ describe GraphQL::UnionType do
169
169
  |}
170
170
 
171
171
  let(:query) { GraphQL::Query.new(Dummy::Schema, query_string) }
172
- let(:union) { Dummy::BeverageUnion }
172
+ let(:union) { Dummy::Beverage.graphql_definition }
173
173
 
174
174
  it "returns the type definition if the type exists and is a possible type of the union" do
175
175
  assert union.get_possible_type("Milk", query.context)
@@ -194,7 +194,7 @@ describe GraphQL::UnionType do
194
194
  |}
195
195
 
196
196
  let(:query) { GraphQL::Query.new(Dummy::Schema, query_string) }
197
- let(:union) { Dummy::BeverageUnion }
197
+ let(:union) { Dummy::Beverage.graphql_definition }
198
198
 
199
199
  it "returns true if the type exists and is a possible type of the union" do
200
200
  assert union.possible_type?("Milk", query.context)