graphql 1.7.6 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (289) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/function_generator.rb +1 -1
  3. data/lib/generators/graphql/install_generator.rb +14 -8
  4. data/lib/generators/graphql/loader_generator.rb +1 -1
  5. data/lib/generators/graphql/mutation_generator.rb +6 -1
  6. data/lib/generators/graphql/templates/function.erb +2 -2
  7. data/lib/generators/graphql/templates/loader.erb +2 -2
  8. data/lib/generators/graphql/templates/schema.erb +1 -1
  9. data/lib/graphql/argument.rb +25 -19
  10. data/lib/graphql/backtrace/tracer.rb +16 -22
  11. data/lib/graphql/backtrace.rb +1 -1
  12. data/lib/graphql/backwards_compatibility.rb +2 -3
  13. data/lib/graphql/base_type.rb +31 -31
  14. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +14 -0
  15. data/lib/graphql/compatibility/query_parser_specification.rb +117 -0
  16. data/lib/graphql/define/assign_object_field.rb +5 -12
  17. data/lib/graphql/deprecated_dsl.rb +42 -0
  18. data/lib/graphql/directive.rb +1 -0
  19. data/lib/graphql/enum_type.rb +3 -1
  20. data/lib/graphql/execution/execute.rb +21 -13
  21. data/lib/graphql/execution/instrumentation.rb +82 -0
  22. data/lib/graphql/execution/lazy/lazy_method_map.rb +1 -1
  23. data/lib/graphql/execution/lazy/resolve.rb +1 -3
  24. data/lib/graphql/execution/multiplex.rb +12 -29
  25. data/lib/graphql/execution.rb +1 -0
  26. data/lib/graphql/field.rb +21 -4
  27. data/lib/graphql/function.rb +14 -0
  28. data/lib/graphql/input_object_type.rb +3 -1
  29. data/lib/graphql/interface_type.rb +5 -3
  30. data/lib/graphql/internal_representation/node.rb +26 -14
  31. data/lib/graphql/internal_representation/visit.rb +3 -6
  32. data/lib/graphql/introspection/base_object.rb +16 -0
  33. data/lib/graphql/introspection/directive_location_enum.rb +11 -7
  34. data/lib/graphql/introspection/directive_type.rb +23 -16
  35. data/lib/graphql/introspection/dynamic_fields.rb +11 -0
  36. data/lib/graphql/introspection/entry_points.rb +29 -0
  37. data/lib/graphql/introspection/enum_value_type.rb +16 -11
  38. data/lib/graphql/introspection/field_type.rb +21 -12
  39. data/lib/graphql/introspection/input_value_type.rb +26 -23
  40. data/lib/graphql/introspection/schema_field.rb +7 -2
  41. data/lib/graphql/introspection/schema_type.rb +36 -22
  42. data/lib/graphql/introspection/type_by_name_field.rb +10 -2
  43. data/lib/graphql/introspection/type_kind_enum.rb +10 -6
  44. data/lib/graphql/introspection/type_type.rb +85 -23
  45. data/lib/graphql/introspection/typename_field.rb +1 -0
  46. data/lib/graphql/introspection.rb +3 -10
  47. data/lib/graphql/language/block_string.rb +47 -0
  48. data/lib/graphql/language/document_from_schema_definition.rb +280 -0
  49. data/lib/graphql/language/generation.rb +3 -182
  50. data/lib/graphql/language/lexer.rb +144 -69
  51. data/lib/graphql/language/lexer.rl +15 -4
  52. data/lib/graphql/language/nodes.rb +141 -78
  53. data/lib/graphql/language/parser.rb +677 -630
  54. data/lib/graphql/language/parser.y +18 -12
  55. data/lib/graphql/language/printer.rb +361 -0
  56. data/lib/graphql/language/token.rb +10 -3
  57. data/lib/graphql/language.rb +3 -0
  58. data/lib/graphql/non_null_type.rb +1 -1
  59. data/lib/graphql/object_type.rb +1 -6
  60. data/lib/graphql/query/arguments.rb +63 -32
  61. data/lib/graphql/query/context.rb +32 -2
  62. data/lib/graphql/query/literal_input.rb +4 -1
  63. data/lib/graphql/query/null_context.rb +1 -1
  64. data/lib/graphql/query/result.rb +1 -1
  65. data/lib/graphql/query/variables.rb +21 -3
  66. data/lib/graphql/query.rb +19 -6
  67. data/lib/graphql/railtie.rb +109 -0
  68. data/lib/graphql/relay/connection_resolve.rb +3 -0
  69. data/lib/graphql/relay/connection_type.rb +5 -3
  70. data/lib/graphql/relay/edge_type.rb +2 -1
  71. data/lib/graphql/relay/global_id_resolve.rb +5 -1
  72. data/lib/graphql/relay/mongo_relation_connection.rb +40 -0
  73. data/lib/graphql/relay/mutation/instrumentation.rb +1 -1
  74. data/lib/graphql/relay/mutation/resolve.rb +5 -1
  75. data/lib/graphql/relay/relation_connection.rb +14 -19
  76. data/lib/graphql/relay/type_extensions.rb +30 -0
  77. data/lib/graphql/relay.rb +2 -0
  78. data/lib/graphql/scalar_type.rb +14 -2
  79. data/lib/graphql/schema/argument.rb +92 -0
  80. data/lib/graphql/schema/build_from_definition.rb +64 -18
  81. data/lib/graphql/schema/enum.rb +85 -0
  82. data/lib/graphql/schema/enum_value.rb +74 -0
  83. data/lib/graphql/schema/field.rb +372 -0
  84. data/lib/graphql/schema/finder.rb +153 -0
  85. data/lib/graphql/schema/input_object.rb +87 -0
  86. data/lib/graphql/schema/interface.rb +105 -0
  87. data/lib/graphql/schema/introspection_system.rb +93 -0
  88. data/lib/graphql/schema/late_bound_type.rb +32 -0
  89. data/lib/graphql/schema/list.rb +32 -0
  90. data/lib/graphql/schema/loader.rb +2 -2
  91. data/lib/graphql/schema/member/accepts_definition.rb +152 -0
  92. data/lib/graphql/schema/member/base_dsl_methods.rb +100 -0
  93. data/lib/graphql/schema/member/build_type.rb +137 -0
  94. data/lib/graphql/schema/member/cached_graphql_definition.rb +26 -0
  95. data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
  96. data/lib/graphql/schema/member/has_arguments.rb +50 -0
  97. data/lib/graphql/schema/member/has_fields.rb +130 -0
  98. data/lib/graphql/schema/member/instrumentation.rb +115 -0
  99. data/lib/graphql/schema/member/type_system_helpers.rb +34 -0
  100. data/lib/graphql/schema/member.rb +28 -0
  101. data/lib/graphql/schema/middleware_chain.rb +5 -1
  102. data/lib/graphql/schema/mutation.rb +138 -0
  103. data/lib/graphql/schema/non_null.rb +38 -0
  104. data/lib/graphql/schema/object.rb +81 -0
  105. data/lib/graphql/schema/printer.rb +33 -266
  106. data/lib/graphql/schema/relay_classic_mutation.rb +87 -0
  107. data/lib/graphql/schema/rescue_middleware.rb +8 -7
  108. data/lib/graphql/schema/resolver.rb +122 -0
  109. data/lib/graphql/schema/scalar.rb +35 -0
  110. data/lib/graphql/schema/traversal.rb +102 -22
  111. data/lib/graphql/schema/union.rb +36 -0
  112. data/lib/graphql/schema/validation.rb +3 -2
  113. data/lib/graphql/schema.rb +381 -12
  114. data/lib/graphql/static_validation/definition_dependencies.rb +1 -1
  115. data/lib/graphql/static_validation/literal_validator.rb +16 -4
  116. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +6 -6
  117. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -1
  118. data/lib/graphql/static_validation/rules/fields_will_merge.rb +15 -8
  119. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +11 -1
  120. data/lib/graphql/static_validation/validation_context.rb +1 -1
  121. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -5
  122. data/lib/graphql/subscriptions/instrumentation.rb +5 -1
  123. data/lib/graphql/subscriptions/serialize.rb +2 -0
  124. data/lib/graphql/subscriptions.rb +90 -16
  125. data/lib/graphql/tracing/data_dog_tracing.rb +49 -0
  126. data/lib/graphql/tracing/new_relic_tracing.rb +26 -0
  127. data/lib/graphql/tracing/platform_tracing.rb +20 -7
  128. data/lib/graphql/tracing/scout_tracing.rb +2 -2
  129. data/lib/graphql/tracing.rb +1 -0
  130. data/lib/graphql/unresolved_type_error.rb +3 -2
  131. data/lib/graphql/upgrader/member.rb +894 -0
  132. data/lib/graphql/upgrader/schema.rb +37 -0
  133. data/lib/graphql/version.rb +1 -1
  134. data/lib/graphql.rb +5 -25
  135. data/readme.md +2 -2
  136. data/spec/dummy/app/channels/graphql_channel.rb +23 -2
  137. data/spec/dummy/log/development.log +239 -0
  138. data/spec/dummy/log/test.log +410 -0
  139. data/spec/dummy/test/system/action_cable_subscription_test.rb +4 -0
  140. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-x/-xYZjAnuuzgR79fcznLTQtSdh6AARxu8FcQ_J6p7L3U.cache +0 -0
  141. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/13/13HiV12xyoQvT-1L39ZzLwMZxjyaGMiENmfw7f-QTIc.cache +0 -0
  142. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3W/3Wtf5pCWdqq0AB-iB0Y9uUNrTkruRxIEf1XFn_BETU0.cache +1 -0
  143. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/5i/5iguGafb4hOn8262Kn8Q37ogNN9MxxQKGKNzHAzUcvI.cache +1 -0
  144. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8m/8mj2T6yy847Mc2Z7k3Xzh8O91hhVJt3NrPe8ASNDlIA.cache +1 -0
  145. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/DT/DTQyMpr4ABZYQetsdRJ5A7S4jf1r3ie4FGOR7GZBNSs.cache +3 -0
  146. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Dq/DqJ5_yJPrP5iLlOQyTQsjAVI5FE5LCVDkED0f7GgsSo.cache +3 -0
  147. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -0
  148. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -0
  149. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Rw/RwDuCV-XpnCtjNkvhpJfBuxXMk0b5AD3L9eR6M-wcy0.cache +3 -0
  150. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/UL/ULdjhhb0bRuqmaG7XSZlFYzGYCXTDnqZuJBTWRlzqgw.cache +0 -0
  151. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Up/UpPNgh0yYoUsyMDh5zWqe_U6qJIyTC6-dxMMAs1vvlM.cache +1 -0
  152. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Wg/Wguh-szFGTI1gaL6npYwPekMXflugRei7F_mOyRucXg.cache +0 -0
  153. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/X-/X-khLYMA9mqFRPg3zAi86mREDxpKl4bdKYp3uF6WHos.cache +0 -0
  154. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/bi/BIkdhfxsezxM4q-HZ4oCNTq97WEJTigcq0tpX2cDvbY.cache +0 -0
  155. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ff/FfxmA4CMHQZT7exx0G7NS1Wpcnny0vzp-Jhc2H36bp8.cache +1 -0
  156. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gE/gEiiG4GZNy_djEjK2pHm_NgA-gyhLZhdQvo0Yt96GqE.cache +0 -0
  157. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gn/gnA9ZSqpjccNL2m8pe_jBvY6SinXlCzXDWyop83Od8s.cache +1 -0
  158. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/lO/lOAan3cMwCE_Hli6gsDML88xFNfn0nxPmvrSkW7eEOw.cache +1 -0
  159. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m1/M1pv8MJEPLXGLvS8QxVh3DSO9cI4mRt5FHFWdrvUj6o.cache +2 -0
  160. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m7/m77qH7ZqH0_0SmwJbiKGDd-aLau1Dav847DC6ge46zY.cache +1 -0
  161. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sj/sjRjnjRB37lH2vrgtkdJ8Cz84__IJ978IuKTM7HcztI.cache +0 -0
  162. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/um/um1JrirR4hJhK-1rE-HywlyCi5ibgxHVrReiujZBWJM.cache +1 -0
  163. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v4/v4fwVytD7ITcE0_GDbslZEYud8a5Okm85fV1o7SDl6g.cache +0 -0
  164. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v_/v_0PAQt0iipQjFP5zjgkkk9Stnpf4VzvnMv67d1Keuw.cache +1 -0
  165. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wd/wdT9U4MKxe1PyqNjVuCKMpCl3dxGCIRJIlwUTfh2DQU.cache +1 -0
  166. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xI/xIaxut_fEIhKBDqljTNwYaADK9kj3gG0ESrfHs-5_og.cache +3 -0
  167. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/y0/y0SJOqIx2fn1SKqOkAihsQow0trRJrSIyAswufVuoA8.cache +0 -0
  168. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zg/zgpzeaX-KZErHyGJ1aBH3ZusweNXMneVZule88XsIJI.cache +1 -0
  169. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zy/zYFltDy-8VC-uKq2BVEiJJyYXNFvVzAKuMlR3ZIYZsk.cache +0 -0
  170. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  171. data/spec/fixtures/upgrader/account.original.rb +19 -0
  172. data/spec/fixtures/upgrader/account.transformed.rb +20 -0
  173. data/spec/fixtures/upgrader/blame_range.original.rb +43 -0
  174. data/spec/fixtures/upgrader/blame_range.transformed.rb +30 -0
  175. data/spec/fixtures/upgrader/date_time.original.rb +24 -0
  176. data/spec/fixtures/upgrader/date_time.transformed.rb +23 -0
  177. data/spec/fixtures/upgrader/delete_project.original.rb +28 -0
  178. data/spec/fixtures/upgrader/delete_project.transformed.rb +27 -0
  179. data/spec/fixtures/upgrader/gist_order_field.original.rb +14 -0
  180. data/spec/fixtures/upgrader/gist_order_field.transformed.rb +13 -0
  181. data/spec/fixtures/upgrader/increment_count.original.rb +59 -0
  182. data/spec/fixtures/upgrader/increment_count.transformed.rb +50 -0
  183. data/spec/fixtures/upgrader/photo.original.rb +10 -0
  184. data/spec/fixtures/upgrader/photo.transformed.rb +12 -0
  185. data/spec/fixtures/upgrader/release_order.original.rb +15 -0
  186. data/spec/fixtures/upgrader/release_order.transformed.rb +14 -0
  187. data/spec/fixtures/upgrader/starrable.original.rb +49 -0
  188. data/spec/fixtures/upgrader/starrable.transformed.rb +46 -0
  189. data/spec/fixtures/upgrader/subscribable.original.rb +55 -0
  190. data/spec/fixtures/upgrader/subscribable.transformed.rb +51 -0
  191. data/spec/fixtures/upgrader/type_x.original.rb +65 -0
  192. data/spec/fixtures/upgrader/type_x.transformed.rb +56 -0
  193. data/spec/generators/graphql/function_generator_spec.rb +26 -0
  194. data/spec/generators/graphql/install_generator_spec.rb +1 -1
  195. data/spec/generators/graphql/loader_generator_spec.rb +24 -0
  196. data/spec/graphql/analysis/max_query_complexity_spec.rb +3 -3
  197. data/spec/graphql/analysis/max_query_depth_spec.rb +3 -3
  198. data/spec/graphql/argument_spec.rb +21 -0
  199. data/spec/graphql/backtrace_spec.rb +10 -0
  200. data/spec/graphql/base_type_spec.rb +42 -0
  201. data/spec/graphql/boolean_type_spec.rb +3 -3
  202. data/spec/graphql/directive_spec.rb +3 -1
  203. data/spec/graphql/enum_type_spec.rb +18 -5
  204. data/spec/graphql/execution/execute_spec.rb +4 -4
  205. data/spec/graphql/execution/instrumentation_spec.rb +165 -0
  206. data/spec/graphql/execution/multiplex_spec.rb +2 -2
  207. data/spec/graphql/execution_error_spec.rb +18 -0
  208. data/spec/graphql/float_type_spec.rb +2 -2
  209. data/spec/graphql/id_type_spec.rb +1 -1
  210. data/spec/graphql/input_object_type_spec.rb +15 -2
  211. data/spec/graphql/int_type_spec.rb +2 -2
  212. data/spec/graphql/interface_type_spec.rb +12 -0
  213. data/spec/graphql/internal_representation/rewrite_spec.rb +2 -2
  214. data/spec/graphql/introspection/schema_type_spec.rb +2 -0
  215. data/spec/graphql/language/block_string_spec.rb +70 -0
  216. data/spec/graphql/language/document_from_schema_definition_spec.rb +770 -0
  217. data/spec/graphql/language/generation_spec.rb +21 -186
  218. data/spec/graphql/language/lexer_spec.rb +21 -1
  219. data/spec/graphql/language/nodes_spec.rb +21 -12
  220. data/spec/graphql/language/parser_spec.rb +1 -1
  221. data/spec/graphql/language/printer_spec.rb +203 -0
  222. data/spec/graphql/object_type_spec.rb +22 -0
  223. data/spec/graphql/query/arguments_spec.rb +25 -15
  224. data/spec/graphql/query/context_spec.rb +18 -0
  225. data/spec/graphql/query/executor_spec.rb +2 -1
  226. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +2 -8
  227. data/spec/graphql/query/variables_spec.rb +42 -1
  228. data/spec/graphql/query_spec.rb +31 -5
  229. data/spec/graphql/rake_task_spec.rb +3 -1
  230. data/spec/graphql/relay/base_connection_spec.rb +1 -1
  231. data/spec/graphql/relay/connection_instrumentation_spec.rb +2 -2
  232. data/spec/graphql/relay/connection_resolve_spec.rb +1 -1
  233. data/spec/graphql/relay/connection_type_spec.rb +1 -1
  234. data/spec/graphql/relay/mongo_relation_connection_spec.rb +474 -0
  235. data/spec/graphql/relay/mutation_spec.rb +9 -7
  236. data/spec/graphql/relay/range_add_spec.rb +5 -1
  237. data/spec/graphql/relay/relation_connection_spec.rb +65 -1
  238. data/spec/graphql/schema/argument_spec.rb +87 -0
  239. data/spec/graphql/schema/build_from_definition_spec.rb +89 -5
  240. data/spec/graphql/schema/enum_spec.rb +74 -0
  241. data/spec/graphql/schema/field_spec.rb +225 -0
  242. data/spec/graphql/schema/finder_spec.rb +135 -0
  243. data/spec/graphql/schema/input_object_spec.rb +111 -0
  244. data/spec/graphql/schema/instrumentation_spec.rb +40 -0
  245. data/spec/graphql/schema/interface_spec.rb +185 -0
  246. data/spec/graphql/schema/introspection_system_spec.rb +39 -0
  247. data/spec/graphql/schema/member/accepts_definition_spec.rb +111 -0
  248. data/spec/graphql/schema/member/build_type_spec.rb +17 -0
  249. data/spec/graphql/schema/member/has_fields_spec.rb +129 -0
  250. data/spec/graphql/schema/member/type_system_helpers_spec.rb +63 -0
  251. data/spec/graphql/schema/mutation_spec.rb +148 -0
  252. data/spec/graphql/schema/object_spec.rb +175 -0
  253. data/spec/graphql/schema/printer_spec.rb +111 -15
  254. data/spec/graphql/schema/relay_classic_mutation_spec.rb +38 -0
  255. data/spec/graphql/schema/rescue_middleware_spec.rb +11 -0
  256. data/spec/graphql/schema/resolver_spec.rb +131 -0
  257. data/spec/graphql/schema/scalar_spec.rb +95 -0
  258. data/spec/graphql/schema/traversal_spec.rb +31 -0
  259. data/spec/graphql/schema/union_spec.rb +65 -0
  260. data/spec/graphql/schema/validation_spec.rb +1 -1
  261. data/spec/graphql/schema/warden_spec.rb +11 -11
  262. data/spec/graphql/schema_spec.rb +55 -12
  263. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +10 -2
  264. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +2 -2
  265. data/spec/graphql/string_type_spec.rb +3 -3
  266. data/spec/graphql/subscriptions_spec.rb +273 -184
  267. data/spec/graphql/tracing/active_support_notifications_tracing_spec.rb +1 -1
  268. data/spec/graphql/tracing/new_relic_tracing_spec.rb +47 -0
  269. data/spec/graphql/tracing/platform_tracing_spec.rb +60 -1
  270. data/spec/graphql/union_type_spec.rb +1 -1
  271. data/spec/graphql/upgrader/member_spec.rb +516 -0
  272. data/spec/graphql/upgrader/schema_spec.rb +82 -0
  273. data/spec/spec_helper.rb +8 -0
  274. data/spec/support/dummy/schema.rb +53 -24
  275. data/spec/support/jazz.rb +544 -0
  276. data/spec/support/lazy_helpers.rb +21 -23
  277. data/spec/support/new_relic.rb +24 -0
  278. data/spec/support/star_trek/data.rb +109 -0
  279. data/spec/support/star_trek/schema.rb +388 -0
  280. data/spec/support/star_wars/data.rb +6 -7
  281. data/spec/support/star_wars/schema.rb +127 -171
  282. metadata +233 -11
  283. data/lib/graphql/introspection/arguments_field.rb +0 -7
  284. data/lib/graphql/introspection/enum_values_field.rb +0 -18
  285. data/lib/graphql/introspection/fields_field.rb +0 -13
  286. data/lib/graphql/introspection/input_fields_field.rb +0 -12
  287. data/lib/graphql/introspection/interfaces_field.rb +0 -11
  288. data/lib/graphql/introspection/of_type_field.rb +0 -6
  289. data/lib/graphql/introspection/possible_types_field.rb +0 -11
@@ -75,7 +75,7 @@ class InMemoryBackend
75
75
  end
76
76
  end
77
77
  # Just a random stateful object for tracking what happens:
78
- class Payload
78
+ class SubscriptionPayload
79
79
  attr_reader :str
80
80
 
81
81
  def initialize
@@ -87,7 +87,65 @@ class InMemoryBackend
87
87
  @counter += 1
88
88
  end
89
89
  end
90
+ end
91
+
92
+ class ClassBasedInMemoryBackend < InMemoryBackend
93
+ class Payload < GraphQL::Schema::Object
94
+ field :str, String, null: false
95
+ field :int, Integer, null: false
96
+ end
97
+
98
+ class PayloadType < GraphQL::Schema::Enum
99
+ graphql_name "PayloadType"
100
+ # Arbitrary "kinds" of payloads which may be
101
+ # subscribed to separately
102
+ value "ONE"
103
+ value "TWO"
104
+ end
105
+
106
+ class StreamInput < GraphQL::Schema::InputObject
107
+ argument :user_id, ID, required: true
108
+ argument :type, PayloadType, required: false, default_value: "ONE"
109
+ end
110
+
111
+ class Subscription < GraphQL::Schema::Object
112
+ field :payload, Payload, null: false do
113
+ argument :id, ID, required: true
114
+ end
115
+
116
+ def payload(id:)
117
+ object
118
+ end
119
+
120
+ field :event, Payload, null: true do
121
+ argument :stream, StreamInput, required: false
122
+ end
123
+
124
+ def event(stream: nil)
125
+ object
126
+ end
127
+
128
+ field :my_event, Payload, null: true, subscription_scope: :me do
129
+ argument :type, PayloadType, required: false
130
+ end
131
+
132
+ def my_event(type: nil)
133
+ object
134
+ end
135
+ end
136
+
137
+ class Query < GraphQL::Schema::Object
138
+ field :dummy, Integer, null: true
139
+ end
140
+
141
+ class Schema < GraphQL::Schema
142
+ query(Query)
143
+ subscription(Subscription)
144
+ use InMemoryBackend::Subscriptions, extra: 123
145
+ end
146
+ end
90
147
 
148
+ class FromDefinitionInMemoryBackend < InMemoryBackend
91
149
  SchemaDefinition = <<-GRAPHQL
92
150
  type Subscription {
93
151
  payload(id: ID!): Payload!
@@ -126,7 +184,7 @@ class InMemoryBackend
126
184
  }
127
185
  Schema = GraphQL::Schema.from_definition(SchemaDefinition, default_resolve: Resolvers).redefine do
128
186
  use InMemoryBackend::Subscriptions,
129
- extra: 123
187
+ extra: 123
130
188
  end
131
189
 
132
190
  # TODO don't hack this (no way to add metadata from IDL parser right now)
@@ -162,233 +220,264 @@ describe GraphQL::Subscriptions do
162
220
  schema.subscriptions.reset
163
221
  end
164
222
 
165
- let(:root_object) {
166
- OpenStruct.new(
167
- payload: InMemoryBackend::Payload.new,
168
- )
169
- }
223
+ [ClassBasedInMemoryBackend, FromDefinitionInMemoryBackend].each do |in_memory_backend_class|
224
+ describe "using #{in_memory_backend_class}" do
225
+ let(:root_object) {
226
+ OpenStruct.new(
227
+ payload: in_memory_backend_class::SubscriptionPayload.new,
228
+ )
229
+ }
170
230
 
171
- let(:schema) { InMemoryBackend::Schema }
172
- let(:implementation) { schema.subscriptions }
173
- let(:deliveries) { implementation.deliveries }
174
- describe "pushing updates" do
175
- it "sends updated data" do
176
- query_str = <<-GRAPHQL
231
+ let(:schema) { in_memory_backend_class::Schema }
232
+ let(:implementation) { schema.subscriptions }
233
+ let(:deliveries) { implementation.deliveries }
234
+ describe "pushing updates" do
235
+ it "sends updated data" do
236
+ query_str = <<-GRAPHQL
177
237
  subscription ($id: ID!){
178
238
  firstPayload: payload(id: $id) { str, int }
179
239
  otherPayload: payload(id: "900") { int }
180
240
  }
181
- GRAPHQL
182
-
183
- # Initial subscriptions
184
- res_1 = schema.execute(query_str, context: { socket: "1" }, variables: { "id" => "100" }, root_value: root_object)
185
- res_2 = schema.execute(query_str, context: { socket: "2" }, variables: { "id" => "200" }, root_value: root_object)
186
-
187
- # Initial response is nil, no broadcasts yet
188
- assert_equal(nil, res_1["data"])
189
- assert_equal(nil, res_2["data"])
190
- assert_equal [], deliveries["1"]
191
- assert_equal [], deliveries["2"]
192
-
193
- # Application stuff happens.
194
- # The application signals graphql via `subscriptions.trigger`:
195
- schema.subscriptions.trigger("payload", {"id" => "100"}, root_object.payload)
196
- schema.subscriptions.trigger("payload", {"id" => "200"}, root_object.payload)
197
- # Symobls are OK too
198
- schema.subscriptions.trigger("payload", {:id => "100"}, root_object.payload)
199
- schema.subscriptions.trigger("payload", {"id" => "300"}, nil)
200
-
201
- # Let's see what GraphQL sent over the wire:
202
- assert_equal({"str" => "Update", "int" => 1}, deliveries["1"][0]["data"]["firstPayload"])
203
- assert_equal({"str" => "Update", "int" => 2}, deliveries["2"][0]["data"]["firstPayload"])
204
- assert_equal({"str" => "Update", "int" => 3}, deliveries["1"][1]["data"]["firstPayload"])
205
- end
206
- end
241
+ GRAPHQL
242
+
243
+ # Initial subscriptions
244
+ res_1 = schema.execute(query_str, context: { socket: "1" }, variables: { "id" => "100" }, root_value: root_object)
245
+ res_2 = schema.execute(query_str, context: { socket: "2" }, variables: { "id" => "200" }, root_value: root_object)
246
+
247
+ # Initial response is nil, no broadcasts yet
248
+ assert_equal(nil, res_1["data"])
249
+ assert_equal(nil, res_2["data"])
250
+ assert_equal [], deliveries["1"]
251
+ assert_equal [], deliveries["2"]
252
+
253
+ # Application stuff happens.
254
+ # The application signals graphql via `subscriptions.trigger`:
255
+ schema.subscriptions.trigger(:payload, {"id" => "100"}, root_object.payload)
256
+ schema.subscriptions.trigger("payload", {"id" => "200"}, root_object.payload)
257
+ # Symobls are OK too
258
+ schema.subscriptions.trigger(:payload, {:id => "100"}, root_object.payload)
259
+ schema.subscriptions.trigger("payload", {"id" => "300"}, nil)
260
+
261
+ # Let's see what GraphQL sent over the wire:
262
+ assert_equal({"str" => "Update", "int" => 1}, deliveries["1"][0]["data"]["firstPayload"])
263
+ assert_equal({"str" => "Update", "int" => 2}, deliveries["2"][0]["data"]["firstPayload"])
264
+ assert_equal({"str" => "Update", "int" => 3}, deliveries["1"][1]["data"]["firstPayload"])
265
+ end
266
+ end
207
267
 
208
- describe "subscribing" do
209
- it "doesn't call the subscriptions for invalid queries" do
210
- query_str = <<-GRAPHQL
268
+ describe "subscribing" do
269
+ it "doesn't call the subscriptions for invalid queries" do
270
+ query_str = <<-GRAPHQL
211
271
  subscription ($id: ID){
212
272
  payload(id: $id) { str, int }
213
273
  }
214
- GRAPHQL
274
+ GRAPHQL
215
275
 
216
- res = schema.execute(query_str, context: { socket: "1" }, variables: { "id" => "100" }, root_value: root_object)
217
- assert_equal true, res.key?("errors")
218
- assert_equal 0, implementation.size
219
- end
220
- end
276
+ res = schema.execute(query_str, context: { socket: "1" }, variables: { "id" => "100" }, root_value: root_object)
277
+ assert_equal true, res.key?("errors")
278
+ assert_equal 0, implementation.size
279
+ end
280
+ end
221
281
 
222
- describe "trigger" do
223
- it "uses the provided queue" do
224
- query_str = <<-GRAPHQL
282
+ describe "trigger" do
283
+ it "uses the provided queue" do
284
+ query_str = <<-GRAPHQL
225
285
  subscription ($id: ID!){
226
286
  payload(id: $id) { str, int }
227
287
  }
228
- GRAPHQL
288
+ GRAPHQL
229
289
 
230
- schema.execute(query_str, context: { socket: "1" }, variables: { "id" => "8" }, root_value: root_object)
231
- schema.subscriptions.trigger("payload", { "id" => "8"}, root_object.payload)
232
- assert_equal ["1"], implementation.pushes
233
- end
290
+ schema.execute(query_str, context: { socket: "1" }, variables: { "id" => "8" }, root_value: root_object)
291
+ schema.subscriptions.trigger("payload", { "id" => "8"}, root_object.payload)
292
+ assert_equal ["1"], implementation.pushes
293
+ end
234
294
 
235
- it "pushes errors" do
236
- query_str = <<-GRAPHQL
295
+ it "pushes errors" do
296
+ query_str = <<-GRAPHQL
237
297
  subscription ($id: ID!){
238
298
  payload(id: $id) { str, int }
239
299
  }
240
- GRAPHQL
300
+ GRAPHQL
241
301
 
242
- schema.execute(query_str, context: { socket: "1" }, variables: { "id" => "8" }, root_value: root_object)
243
- schema.subscriptions.trigger("payload", { "id" => "8"}, OpenStruct.new(str: nil, int: nil))
244
- delivery = deliveries["1"].first
245
- assert_equal nil, delivery.fetch("data")
246
- assert_equal 1, delivery["errors"].length
247
- end
302
+ schema.execute(query_str, context: { socket: "1" }, variables: { "id" => "8" }, root_value: root_object)
303
+ schema.subscriptions.trigger("payload", { "id" => "8"}, OpenStruct.new(str: nil, int: nil))
304
+ delivery = deliveries["1"].first
305
+ assert_nil delivery.fetch("data")
306
+ assert_equal 1, delivery["errors"].length
307
+ end
248
308
 
249
- it "coerces args" do
250
- query_str = <<-GRAPHQL
309
+ it "coerces args" do
310
+ query_str = <<-GRAPHQL
251
311
  subscription($type: PayloadType) {
252
312
  e1: event(stream: { userId: "3", type: $type }) { int }
253
313
  }
254
- GRAPHQL
255
-
256
- # Subscribe with explicit `TYPE`
257
- schema.execute(query_str, context: { socket: "1" }, variables: { "type" => "ONE" }, root_value: root_object)
258
- # Subscribe with default `TYPE`
259
- schema.execute(query_str, context: { socket: "2" }, root_value: root_object)
260
- # Subscribe with non-matching `TYPE`
261
- schema.execute(query_str, context: { socket: "3" }, variables: { "type" => "TWO" }, root_value: root_object)
262
- # Subscribe with explicit null
263
- schema.execute(query_str, context: { socket: "4" }, variables: { "type" => nil }, root_value: root_object)
264
-
265
- # Trigger the subscription with coerceable args, different orders:
266
- schema.subscriptions.trigger("event", { "stream" => {"userId" => 3, "type" => "ONE"} }, OpenStruct.new(str: "", int: 1))
267
- schema.subscriptions.trigger("event", { "stream" => {"type" => "ONE", "userId" => "3"} }, OpenStruct.new(str: "", int: 2))
268
- # This is a non-trigger
269
- schema.subscriptions.trigger("event", { "stream" => {"userId" => "3", "type" => "TWO"} }, OpenStruct.new(str: "", int: 3))
270
- # These get default value of ONE
271
- schema.subscriptions.trigger("event", { "stream" => {"userId" => "3"} }, OpenStruct.new(str: "", int: 4))
272
- # Trigger with null updates subscriptionss to null
273
- schema.subscriptions.trigger("event", { "stream" => {"userId" => 3, "type" => nil} }, OpenStruct.new(str: "", int: 5))
274
-
275
- assert_equal [1,2,4], deliveries["1"].map { |d| d["data"]["e1"]["int"] }
276
-
277
- # Same as socket_1
278
- assert_equal [1,2,4], deliveries["2"].map { |d| d["data"]["e1"]["int"] }
279
-
280
- # Received the "non-trigger"
281
- assert_equal [3], deliveries["3"].map { |d| d["data"]["e1"]["int"] }
282
-
283
- # Received the trigger with null
284
- assert_equal [5], deliveries["4"].map { |d| d["data"]["e1"]["int"] }
285
- end
314
+ GRAPHQL
315
+
316
+ # Subscribe with explicit `TYPE`
317
+ schema.execute(query_str, context: { socket: "1" }, variables: { "type" => "ONE" }, root_value: root_object)
318
+ # Subscribe with default `TYPE`
319
+ schema.execute(query_str, context: { socket: "2" }, root_value: root_object)
320
+ # Subscribe with non-matching `TYPE`
321
+ schema.execute(query_str, context: { socket: "3" }, variables: { "type" => "TWO" }, root_value: root_object)
322
+ # Subscribe with explicit null
323
+ schema.execute(query_str, context: { socket: "4" }, variables: { "type" => nil }, root_value: root_object)
324
+
325
+ # Trigger the subscription with coerceable args, different orders:
326
+ schema.subscriptions.trigger("event", { "stream" => {"userId" => 3, "type" => "ONE"} }, OpenStruct.new(str: "", int: 1))
327
+ schema.subscriptions.trigger("event", { "stream" => {"type" => "ONE", "userId" => "3"} }, OpenStruct.new(str: "", int: 2))
328
+ # This is a non-trigger
329
+ schema.subscriptions.trigger("event", { "stream" => {"userId" => "3", "type" => "TWO"} }, OpenStruct.new(str: "", int: 3))
330
+ # These get default value of ONE (underscored / symbols are ok)
331
+ schema.subscriptions.trigger("event", { stream: { user_id: "3"} }, OpenStruct.new(str: "", int: 4))
332
+ # Trigger with null updates subscriptionss to null
333
+ schema.subscriptions.trigger("event", { "stream" => {"userId" => 3, "type" => nil} }, OpenStruct.new(str: "", int: 5))
334
+
335
+ assert_equal [1,2,4], deliveries["1"].map { |d| d["data"]["e1"]["int"] }
336
+
337
+ # Same as socket_1
338
+ assert_equal [1,2,4], deliveries["2"].map { |d| d["data"]["e1"]["int"] }
339
+
340
+ # Received the "non-trigger"
341
+ assert_equal [3], deliveries["3"].map { |d| d["data"]["e1"]["int"] }
342
+
343
+ # Received the trigger with null
344
+ assert_equal [5], deliveries["4"].map { |d| d["data"]["e1"]["int"] }
345
+ end
286
346
 
287
- it "allows context-scoped subscriptions" do
288
- query_str = <<-GRAPHQL
347
+ it "allows context-scoped subscriptions" do
348
+ query_str = <<-GRAPHQL
289
349
  subscription($type: PayloadType) {
290
350
  myEvent(type: $type) { int }
291
351
  }
292
- GRAPHQL
293
-
294
- # Subscriptions for user 1
295
- schema.execute(query_str, context: { socket: "1", me: "1" }, variables: { "type" => "ONE" }, root_value: root_object)
296
- schema.execute(query_str, context: { socket: "2", me: "1" }, variables: { "type" => "TWO" }, root_value: root_object)
297
- # Subscription for user 2
298
- schema.execute(query_str, context: { socket: "3", me: "2" }, variables: { "type" => "ONE" }, root_value: root_object)
299
-
300
- schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, OpenStruct.new(str: "", int: 1), scope: "1")
301
- schema.subscriptions.trigger("myEvent", { "type" => "TWO" }, OpenStruct.new(str: "", int: 2), scope: "1")
302
- schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, OpenStruct.new(str: "", int: 3), scope: "2")
303
-
304
- # Delivered to user 1
305
- assert_equal [1], deliveries["1"].map { |d| d["data"]["myEvent"]["int"] }
306
- assert_equal [2], deliveries["2"].map { |d| d["data"]["myEvent"]["int"] }
307
- # Delivered to user 2
308
- assert_equal [3], deliveries["3"].map { |d| d["data"]["myEvent"]["int"] }
309
- end
352
+ GRAPHQL
353
+
354
+ # Subscriptions for user 1
355
+ schema.execute(query_str, context: { socket: "1", me: "1" }, variables: { "type" => "ONE" }, root_value: root_object)
356
+ schema.execute(query_str, context: { socket: "2", me: "1" }, variables: { "type" => "TWO" }, root_value: root_object)
357
+ # Subscription for user 2
358
+ schema.execute(query_str, context: { socket: "3", me: "2" }, variables: { "type" => "ONE" }, root_value: root_object)
359
+
360
+ schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, OpenStruct.new(str: "", int: 1), scope: "1")
361
+ schema.subscriptions.trigger("myEvent", { "type" => "TWO" }, OpenStruct.new(str: "", int: 2), scope: "1")
362
+ schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, OpenStruct.new(str: "", int: 3), scope: "2")
363
+
364
+ # Delivered to user 1
365
+ assert_equal [1], deliveries["1"].map { |d| d["data"]["myEvent"]["int"] }
366
+ assert_equal [2], deliveries["2"].map { |d| d["data"]["myEvent"]["int"] }
367
+ # Delivered to user 2
368
+ assert_equal [3], deliveries["3"].map { |d| d["data"]["myEvent"]["int"] }
369
+ end
310
370
 
311
- if defined?(GlobalID)
312
- it "allows complex object subscription scopes" do
313
- query_str = <<-GRAPHQL
371
+ if defined?(GlobalID)
372
+ it "allows complex object subscription scopes" do
373
+ query_str = <<-GRAPHQL
314
374
  subscription($type: PayloadType) {
315
375
  myEvent(type: $type) { int }
316
376
  }
317
- GRAPHQL
318
-
319
- # Global ID Backed User
320
- schema.execute(query_str, context: { socket: "1", me: GlobalIDUser.new(1) }, variables: { "type" => "ONE" }, root_value: root_object)
321
- schema.execute(query_str, context: { socket: "2", me: GlobalIDUser.new(1) }, variables: { "type" => "TWO" }, root_value: root_object)
322
- # ToParam Backed User
323
- schema.execute(query_str, context: { socket: "3", me: ToParamUser.new(2) }, variables: { "type" => "ONE" }, root_value: root_object)
324
- # Array of Objects
325
- schema.execute(query_str, context: { socket: "4", me: [GlobalIDUser.new(4), ToParamUser.new(5)] }, variables: { "type" => "ONE" }, root_value: root_object)
326
-
327
- schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, OpenStruct.new(str: "", int: 1), scope: GlobalIDUser.new(1))
328
- schema.subscriptions.trigger("myEvent", { "type" => "TWO" }, OpenStruct.new(str: "", int: 2), scope: GlobalIDUser.new(1))
329
- schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, OpenStruct.new(str: "", int: 3), scope: ToParamUser.new(2))
330
- schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, OpenStruct.new(str: "", int: 4), scope: [GlobalIDUser.new(4), ToParamUser.new(5)])
331
-
332
- # Delivered to GlobalIDUser
333
- assert_equal [1], deliveries["1"].map { |d| d["data"]["myEvent"]["int"] }
334
- assert_equal [2], deliveries["2"].map { |d| d["data"]["myEvent"]["int"] }
335
- # Delivered to ToParamUser
336
- assert_equal [3], deliveries["3"].map { |d| d["data"]["myEvent"]["int"] }
337
- # Delivered to Array of GlobalIDUser and ToParamUser
338
- assert_equal [4], deliveries["4"].map { |d| d["data"]["myEvent"]["int"] }
339
- end
340
- end
341
-
342
- describe "errors" do
343
- class ErrorPayload
344
- def int
345
- raise "Boom!"
377
+ GRAPHQL
378
+
379
+ # Global ID Backed User
380
+ schema.execute(query_str, context: { socket: "1", me: GlobalIDUser.new(1) }, variables: { "type" => "ONE" }, root_value: root_object)
381
+ schema.execute(query_str, context: { socket: "2", me: GlobalIDUser.new(1) }, variables: { "type" => "TWO" }, root_value: root_object)
382
+ # ToParam Backed User
383
+ schema.execute(query_str, context: { socket: "3", me: ToParamUser.new(2) }, variables: { "type" => "ONE" }, root_value: root_object)
384
+ # Array of Objects
385
+ schema.execute(query_str, context: { socket: "4", me: [GlobalIDUser.new(4), ToParamUser.new(5)] }, variables: { "type" => "ONE" }, root_value: root_object)
386
+
387
+ schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, OpenStruct.new(str: "", int: 1), scope: GlobalIDUser.new(1))
388
+ schema.subscriptions.trigger("myEvent", { "type" => "TWO" }, OpenStruct.new(str: "", int: 2), scope: GlobalIDUser.new(1))
389
+ schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, OpenStruct.new(str: "", int: 3), scope: ToParamUser.new(2))
390
+ schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, OpenStruct.new(str: "", int: 4), scope: [GlobalIDUser.new(4), ToParamUser.new(5)])
391
+
392
+ # Delivered to GlobalIDUser
393
+ assert_equal [1], deliveries["1"].map { |d| d["data"]["myEvent"]["int"] }
394
+ assert_equal [2], deliveries["2"].map { |d| d["data"]["myEvent"]["int"] }
395
+ # Delivered to ToParamUser
396
+ assert_equal [3], deliveries["3"].map { |d| d["data"]["myEvent"]["int"] }
397
+ # Delivered to Array of GlobalIDUser and ToParamUser
398
+ assert_equal [4], deliveries["4"].map { |d| d["data"]["myEvent"]["int"] }
399
+ end
346
400
  end
347
401
 
348
- def str
349
- raise GraphQL::ExecutionError.new("This is handled")
350
- end
351
- end
402
+ describe "errors" do
403
+ class ErrorPayload
404
+ def int
405
+ raise "Boom!"
406
+ end
352
407
 
353
- it "lets unhandled errors crash "do
354
- query_str = <<-GRAPHQL
408
+ def str
409
+ raise GraphQL::ExecutionError.new("This is handled")
410
+ end
411
+ end
412
+
413
+ it "lets unhandled errors crash "do
414
+ query_str = <<-GRAPHQL
355
415
  subscription($type: PayloadType) {
356
416
  myEvent(type: $type) { int }
357
417
  }
358
- GRAPHQL
359
-
360
- schema.execute(query_str, context: { socket: "1", me: "1" }, variables: { "type" => "ONE" }, root_value: root_object)
361
- err = assert_raises(RuntimeError) {
362
- schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, ErrorPayload.new, scope: "1")
363
- }
364
- assert_equal "Boom!", err.message
365
- end
366
- end
418
+ GRAPHQL
419
+
420
+ schema.execute(query_str, context: { socket: "1", me: "1" }, variables: { "type" => "ONE" }, root_value: root_object)
421
+ err = assert_raises(RuntimeError) {
422
+ schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, ErrorPayload.new, scope: "1")
423
+ }
424
+ assert_equal "Boom!", err.message
425
+ end
426
+ end
367
427
 
368
- it "sends query errors to the subscriptions" do
369
- query_str = <<-GRAPHQL
428
+ it "sends query errors to the subscriptions" do
429
+ query_str = <<-GRAPHQL
370
430
  subscription($type: PayloadType) {
371
431
  myEvent(type: $type) { str }
372
432
  }
373
- GRAPHQL
433
+ GRAPHQL
374
434
 
375
- schema.execute(query_str, context: { socket: "1", me: "1" }, variables: { "type" => "ONE" }, root_value: root_object)
376
- schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, ErrorPayload.new, scope: "1")
377
- res = deliveries["1"].first
378
- assert_equal "This is handled", res["errors"][0]["message"]
379
- end
380
- end
435
+ schema.execute(query_str, context: { socket: "1", me: "1" }, variables: { "type" => "ONE" }, root_value: root_object)
436
+ schema.subscriptions.trigger("myEvent", { "type" => "ONE" }, ErrorPayload.new, scope: "1")
437
+ res = deliveries["1"].first
438
+ assert_equal "This is handled", res["errors"][0]["message"]
439
+ end
440
+ end
381
441
 
382
- describe "implementation" do
383
- it "is initialized with keywords" do
384
- assert_equal 123, schema.subscriptions.extra
385
- end
386
- end
442
+ describe "implementation" do
443
+ it "is initialized with keywords" do
444
+ assert_equal 123, schema.subscriptions.extra
445
+ end
446
+ end
447
+
448
+ describe "#build_id" do
449
+ it "returns a unique ID string" do
450
+ assert_instance_of String, schema.subscriptions.build_id
451
+ refute_equal schema.subscriptions.build_id, schema.subscriptions.build_id
452
+ end
453
+ end
454
+
455
+ describe ".trigger" do
456
+ it "raises when event name is not found" do
457
+ err = assert_raises(GraphQL::Subscriptions::InvalidTriggerError) do
458
+ schema.subscriptions.trigger(:nonsense_field, {}, nil)
459
+ end
460
+
461
+ assert_includes err.message, "trigger: nonsense_field"
462
+ assert_includes err.message, "Subscription.nonsenseField"
463
+ end
464
+
465
+ it "raises when argument is not found" do
466
+ err = assert_raises(GraphQL::Subscriptions::InvalidTriggerError) do
467
+ schema.subscriptions.trigger(:event, { scream: {"userId" => "😱"} }, nil)
468
+ end
387
469
 
388
- describe "#build_id" do
389
- it "returns a unique ID string" do
390
- assert_instance_of String, schema.subscriptions.build_id
391
- refute_equal schema.subscriptions.build_id, schema.subscriptions.build_id
470
+ assert_includes err.message, "arguments: scream"
471
+ assert_includes err.message, "arguments of Subscription.event"
472
+
473
+ err = assert_raises(GraphQL::Subscriptions::InvalidTriggerError) do
474
+ schema.subscriptions.trigger(:event, { stream: { user_id_number: "😱"} }, nil)
475
+ end
476
+
477
+ assert_includes err.message, "arguments: user_id_number"
478
+ assert_includes err.message, "arguments of StreamInput"
479
+ end
480
+ end
392
481
  end
393
482
  end
394
483
  end
@@ -41,10 +41,10 @@ describe GraphQL::Tracing::ActiveSupportNotificationsTracing do
41
41
  "graphql.execute_field",
42
42
  "graphql.execute_query",
43
43
  "graphql.lazy_loader",
44
- "graphql.execute_field",
45
44
  "graphql.execute_field_lazy",
46
45
  "graphql.execute_field",
47
46
  "graphql.execute_field_lazy",
47
+ "graphql.execute_field",
48
48
  "graphql.execute_field_lazy",
49
49
  "graphql.execute_field_lazy",
50
50
  "graphql.execute_query_lazy",
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
3
+
4
+ describe GraphQL::Tracing::NewRelicTracing do
5
+ module NewRelicTest
6
+ class Query < GraphQL::Schema::Object
7
+ field :int, Integer, null: false
8
+
9
+ def int
10
+ 1
11
+ end
12
+ end
13
+
14
+ class SchemaWithoutTransactionName < GraphQL::Schema
15
+ query(Query)
16
+ use(GraphQL::Tracing::NewRelicTracing)
17
+ end
18
+
19
+ class SchemaWithTransactionName < GraphQL::Schema
20
+ query(Query)
21
+ use(GraphQL::Tracing::NewRelicTracing, set_transaction_name: true)
22
+ end
23
+ end
24
+
25
+ before do
26
+ NewRelic.clear_all
27
+ end
28
+
29
+ it "can leave the transaction name in place" do
30
+ NewRelicTest::SchemaWithoutTransactionName.execute "query X { int }"
31
+ assert_equal [], NewRelic::TRANSACTION_NAMES
32
+ end
33
+
34
+ it "can override the transaction name" do
35
+ NewRelicTest::SchemaWithTransactionName.execute "query X { int }"
36
+ assert_equal ["GraphQL/query.X"], NewRelic::TRANSACTION_NAMES
37
+ end
38
+
39
+ it "can override the transaction name per query" do
40
+ # Override with `false`
41
+ NewRelicTest::SchemaWithTransactionName.execute "{ int }", context: { set_new_relic_transaction_name: false }
42
+ assert_equal [], NewRelic::TRANSACTION_NAMES
43
+ # Override with `true`
44
+ NewRelicTest::SchemaWithoutTransactionName.execute "{ int }", context: { set_new_relic_transaction_name: true }
45
+ assert_equal ["GraphQL/query.anonymous"], NewRelic::TRANSACTION_NAMES
46
+ end
47
+ end