graphql 1.9.5 → 1.13.19

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.

Potentially problematic release.


This version of graphql might be problematic. Click here for more details.

Files changed (659) hide show
  1. checksums.yaml +5 -5
  2. data/lib/generators/graphql/core.rb +21 -9
  3. data/lib/generators/graphql/enum_generator.rb +4 -10
  4. data/lib/generators/graphql/field_extractor.rb +31 -0
  5. data/lib/generators/graphql/input_generator.rb +50 -0
  6. data/lib/generators/graphql/install/mutation_root_generator.rb +34 -0
  7. data/lib/generators/graphql/install/templates/base_mutation.erb +10 -0
  8. data/lib/generators/graphql/{templates → install/templates}/mutation_type.erb +2 -0
  9. data/lib/generators/graphql/install_generator.rb +48 -8
  10. data/lib/generators/graphql/interface_generator.rb +7 -7
  11. data/lib/generators/graphql/loader_generator.rb +1 -0
  12. data/lib/generators/graphql/mutation_create_generator.rb +22 -0
  13. data/lib/generators/graphql/mutation_delete_generator.rb +22 -0
  14. data/lib/generators/graphql/mutation_generator.rb +6 -30
  15. data/lib/generators/graphql/mutation_update_generator.rb +22 -0
  16. data/lib/generators/graphql/object_generator.rb +28 -12
  17. data/lib/generators/graphql/orm_mutations_base.rb +40 -0
  18. data/lib/generators/graphql/relay.rb +63 -0
  19. data/lib/generators/graphql/relay_generator.rb +21 -0
  20. data/lib/generators/graphql/scalar_generator.rb +4 -2
  21. data/lib/generators/graphql/templates/base_argument.erb +6 -0
  22. data/lib/generators/graphql/templates/base_connection.erb +8 -0
  23. data/lib/generators/graphql/templates/base_edge.erb +8 -0
  24. data/lib/generators/graphql/templates/base_enum.erb +2 -0
  25. data/lib/generators/graphql/templates/base_field.erb +7 -0
  26. data/lib/generators/graphql/templates/base_input_object.erb +3 -0
  27. data/lib/generators/graphql/templates/base_interface.erb +4 -0
  28. data/lib/generators/graphql/templates/base_object.erb +3 -0
  29. data/lib/generators/graphql/templates/base_scalar.erb +2 -0
  30. data/lib/generators/graphql/templates/base_union.erb +2 -0
  31. data/lib/generators/graphql/templates/enum.erb +7 -1
  32. data/lib/generators/graphql/templates/graphql_controller.erb +21 -12
  33. data/lib/generators/graphql/templates/input.erb +9 -0
  34. data/lib/generators/graphql/templates/interface.erb +6 -2
  35. data/lib/generators/graphql/templates/loader.erb +2 -0
  36. data/lib/generators/graphql/templates/mutation.erb +3 -1
  37. data/lib/generators/graphql/templates/mutation_create.erb +20 -0
  38. data/lib/generators/graphql/templates/mutation_delete.erb +20 -0
  39. data/lib/generators/graphql/templates/mutation_update.erb +21 -0
  40. data/lib/generators/graphql/templates/node_type.erb +9 -0
  41. data/lib/generators/graphql/templates/object.erb +7 -3
  42. data/lib/generators/graphql/templates/query_type.erb +3 -3
  43. data/lib/generators/graphql/templates/scalar.erb +5 -1
  44. data/lib/generators/graphql/templates/schema.erb +23 -28
  45. data/lib/generators/graphql/templates/union.erb +6 -2
  46. data/lib/generators/graphql/type_generator.rb +47 -10
  47. data/lib/generators/graphql/union_generator.rb +5 -5
  48. data/lib/graphql/analysis/analyze_query.rb +7 -0
  49. data/lib/graphql/analysis/ast/analyzer.rb +34 -12
  50. data/lib/graphql/analysis/ast/field_usage.rb +29 -2
  51. data/lib/graphql/analysis/ast/max_query_complexity.rb +3 -3
  52. data/lib/graphql/analysis/ast/max_query_depth.rb +7 -3
  53. data/lib/graphql/analysis/ast/query_complexity.rb +179 -64
  54. data/lib/graphql/analysis/ast/query_depth.rb +16 -26
  55. data/lib/graphql/analysis/ast/visitor.rb +46 -32
  56. data/lib/graphql/analysis/ast.rb +23 -14
  57. data/lib/graphql/analysis/query_depth.rb +4 -17
  58. data/lib/graphql/argument.rb +16 -38
  59. data/lib/graphql/backtrace/inspect_result.rb +0 -1
  60. data/lib/graphql/backtrace/legacy_tracer.rb +56 -0
  61. data/lib/graphql/backtrace/table.rb +44 -5
  62. data/lib/graphql/backtrace/traced_error.rb +0 -1
  63. data/lib/graphql/backtrace/tracer.rb +40 -9
  64. data/lib/graphql/backtrace.rb +28 -19
  65. data/lib/graphql/backwards_compatibility.rb +2 -1
  66. data/lib/graphql/base_type.rb +11 -5
  67. data/lib/graphql/boolean_type.rb +1 -1
  68. data/lib/graphql/coercion_error.rb +8 -0
  69. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +2 -2
  70. data/lib/graphql/compatibility/execution_specification.rb +1 -0
  71. data/lib/graphql/compatibility/lazy_execution_specification/lazy_schema.rb +1 -1
  72. data/lib/graphql/compatibility/lazy_execution_specification.rb +2 -0
  73. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +5 -9
  74. data/lib/graphql/compatibility/query_parser_specification.rb +2 -0
  75. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -0
  76. data/lib/graphql/dataloader/null_dataloader.rb +22 -0
  77. data/lib/graphql/dataloader/request.rb +19 -0
  78. data/lib/graphql/dataloader/request_all.rb +19 -0
  79. data/lib/graphql/dataloader/source.rb +155 -0
  80. data/lib/graphql/dataloader.rb +308 -0
  81. data/lib/graphql/date_encoding_error.rb +16 -0
  82. data/lib/graphql/define/assign_enum_value.rb +1 -1
  83. data/lib/graphql/define/assign_global_id_field.rb +2 -2
  84. data/lib/graphql/define/assign_object_field.rb +3 -3
  85. data/lib/graphql/define/defined_object_proxy.rb +3 -0
  86. data/lib/graphql/define/instance_definable.rb +65 -110
  87. data/lib/graphql/define/type_definer.rb +5 -5
  88. data/lib/graphql/deprecated_dsl.rb +18 -5
  89. data/lib/graphql/deprecation.rb +9 -0
  90. data/lib/graphql/directive/deprecated_directive.rb +1 -12
  91. data/lib/graphql/directive/include_directive.rb +1 -1
  92. data/lib/graphql/directive/skip_directive.rb +1 -1
  93. data/lib/graphql/directive.rb +9 -6
  94. data/lib/graphql/enum_type.rb +14 -74
  95. data/lib/graphql/execution/directive_checks.rb +2 -2
  96. data/lib/graphql/execution/errors.rb +163 -0
  97. data/lib/graphql/execution/execute.rb +10 -3
  98. data/lib/graphql/execution/instrumentation.rb +1 -1
  99. data/lib/graphql/execution/interpreter/argument_value.rb +28 -0
  100. data/lib/graphql/execution/interpreter/arguments.rb +88 -0
  101. data/lib/graphql/execution/interpreter/arguments_cache.rb +105 -0
  102. data/lib/graphql/execution/interpreter/handles_raw_value.rb +18 -0
  103. data/lib/graphql/execution/interpreter/resolve.rb +37 -25
  104. data/lib/graphql/execution/interpreter/runtime.rb +737 -376
  105. data/lib/graphql/execution/interpreter.rb +42 -19
  106. data/lib/graphql/execution/lazy/lazy_method_map.rb +4 -0
  107. data/lib/graphql/execution/lazy.rb +5 -1
  108. data/lib/graphql/execution/lookahead.rb +39 -114
  109. data/lib/graphql/execution/multiplex.rb +58 -29
  110. data/lib/graphql/execution.rb +1 -0
  111. data/lib/graphql/execution_error.rb +3 -2
  112. data/lib/graphql/field.rb +15 -119
  113. data/lib/graphql/filter.rb +1 -1
  114. data/lib/graphql/float_type.rb +1 -1
  115. data/lib/graphql/function.rb +6 -31
  116. data/lib/graphql/id_type.rb +1 -1
  117. data/lib/graphql/input_object_type.rb +11 -26
  118. data/lib/graphql/int_type.rb +1 -1
  119. data/lib/graphql/integer_decoding_error.rb +17 -0
  120. data/lib/graphql/integer_encoding_error.rb +18 -2
  121. data/lib/graphql/interface_type.rb +10 -24
  122. data/lib/graphql/internal_representation/document.rb +2 -2
  123. data/lib/graphql/internal_representation/rewrite.rb +1 -1
  124. data/lib/graphql/internal_representation/scope.rb +2 -2
  125. data/lib/graphql/internal_representation/visit.rb +2 -2
  126. data/lib/graphql/introspection/base_object.rb +2 -5
  127. data/lib/graphql/introspection/directive_location_enum.rb +2 -2
  128. data/lib/graphql/introspection/directive_type.rb +12 -6
  129. data/lib/graphql/introspection/entry_points.rb +9 -8
  130. data/lib/graphql/introspection/enum_value_type.rb +2 -2
  131. data/lib/graphql/introspection/field_type.rb +9 -5
  132. data/lib/graphql/introspection/input_value_type.rb +41 -11
  133. data/lib/graphql/introspection/introspection_query.rb +6 -92
  134. data/lib/graphql/introspection/schema_type.rb +13 -12
  135. data/lib/graphql/introspection/type_type.rb +27 -17
  136. data/lib/graphql/introspection.rb +99 -0
  137. data/lib/graphql/invalid_null_error.rb +18 -0
  138. data/lib/graphql/language/block_string.rb +22 -7
  139. data/lib/graphql/language/cache.rb +37 -0
  140. data/lib/graphql/language/definition_slice.rb +21 -10
  141. data/lib/graphql/language/document_from_schema_definition.rb +126 -67
  142. data/lib/graphql/language/lexer.rb +180 -141
  143. data/lib/graphql/language/lexer.rl +75 -51
  144. data/lib/graphql/language/nodes.rb +92 -108
  145. data/lib/graphql/language/parser.rb +933 -897
  146. data/lib/graphql/language/parser.y +129 -103
  147. data/lib/graphql/language/printer.rb +11 -2
  148. data/lib/graphql/language/sanitized_printer.rb +222 -0
  149. data/lib/graphql/language/token.rb +1 -1
  150. data/lib/graphql/language/visitor.rb +11 -8
  151. data/lib/graphql/language.rb +3 -1
  152. data/lib/graphql/name_validator.rb +2 -7
  153. data/lib/graphql/non_null_type.rb +0 -10
  154. data/lib/graphql/object_type.rb +47 -58
  155. data/lib/graphql/pagination/active_record_relation_connection.rb +85 -0
  156. data/lib/graphql/pagination/array_connection.rb +77 -0
  157. data/lib/graphql/pagination/connection.rb +226 -0
  158. data/lib/graphql/pagination/connections.rb +160 -0
  159. data/lib/graphql/pagination/mongoid_relation_connection.rb +25 -0
  160. data/lib/graphql/pagination/relation_connection.rb +226 -0
  161. data/lib/graphql/pagination/sequel_dataset_connection.rb +28 -0
  162. data/lib/graphql/pagination.rb +6 -0
  163. data/lib/graphql/parse_error.rb +0 -1
  164. data/lib/graphql/query/arguments.rb +29 -19
  165. data/lib/graphql/query/arguments_cache.rb +1 -2
  166. data/lib/graphql/query/context.rb +81 -14
  167. data/lib/graphql/query/executor.rb +0 -1
  168. data/lib/graphql/query/fingerprint.rb +26 -0
  169. data/lib/graphql/query/input_validation_result.rb +32 -6
  170. data/lib/graphql/query/literal_input.rb +31 -10
  171. data/lib/graphql/query/null_context.rb +28 -8
  172. data/lib/graphql/query/serial_execution/field_resolution.rb +1 -1
  173. data/lib/graphql/query/serial_execution.rb +1 -0
  174. data/lib/graphql/query/validation_pipeline.rb +6 -4
  175. data/lib/graphql/query/variable_validation_error.rb +3 -3
  176. data/lib/graphql/query/variables.rb +51 -9
  177. data/lib/graphql/query.rb +97 -23
  178. data/lib/graphql/railtie.rb +9 -1
  179. data/lib/graphql/rake_task/validate.rb +3 -0
  180. data/lib/graphql/rake_task.rb +12 -9
  181. data/lib/graphql/relay/array_connection.rb +11 -13
  182. data/lib/graphql/relay/base_connection.rb +33 -16
  183. data/lib/graphql/relay/connection_instrumentation.rb +4 -4
  184. data/lib/graphql/relay/connection_type.rb +18 -4
  185. data/lib/graphql/relay/edge_type.rb +1 -0
  186. data/lib/graphql/relay/edges_instrumentation.rb +1 -2
  187. data/lib/graphql/relay/global_id_resolve.rb +1 -2
  188. data/lib/graphql/relay/mutation.rb +3 -87
  189. data/lib/graphql/relay/node.rb +5 -2
  190. data/lib/graphql/relay/page_info.rb +1 -1
  191. data/lib/graphql/relay/range_add.rb +27 -9
  192. data/lib/graphql/relay/relation_connection.rb +17 -15
  193. data/lib/graphql/relay/type_extensions.rb +2 -0
  194. data/lib/graphql/rubocop/graphql/base_cop.rb +36 -0
  195. data/lib/graphql/rubocop/graphql/default_null_true.rb +43 -0
  196. data/lib/graphql/rubocop/graphql/default_required_true.rb +43 -0
  197. data/lib/graphql/rubocop.rb +4 -0
  198. data/lib/graphql/scalar_type.rb +18 -62
  199. data/lib/graphql/schema/addition.rb +247 -0
  200. data/lib/graphql/schema/argument.rb +289 -11
  201. data/lib/graphql/schema/base_64_bp.rb +3 -2
  202. data/lib/graphql/schema/base_64_encoder.rb +2 -0
  203. data/lib/graphql/schema/build_from_definition/resolve_map/default_resolve.rb +1 -1
  204. data/lib/graphql/schema/build_from_definition/resolve_map.rb +13 -5
  205. data/lib/graphql/schema/build_from_definition.rb +323 -203
  206. data/lib/graphql/schema/built_in_types.rb +5 -5
  207. data/lib/graphql/schema/default_type_error.rb +2 -0
  208. data/lib/graphql/schema/directive/deprecated.rb +18 -0
  209. data/lib/graphql/schema/directive/feature.rb +2 -2
  210. data/lib/graphql/schema/directive/flagged.rb +57 -0
  211. data/lib/graphql/schema/directive/include.rb +2 -2
  212. data/lib/graphql/schema/directive/skip.rb +2 -2
  213. data/lib/graphql/schema/directive/transform.rb +14 -2
  214. data/lib/graphql/schema/directive.rb +136 -6
  215. data/lib/graphql/schema/enum.rb +121 -12
  216. data/lib/graphql/schema/enum_value.rb +23 -6
  217. data/lib/graphql/schema/field/connection_extension.rb +46 -20
  218. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  219. data/lib/graphql/schema/field.rb +515 -191
  220. data/lib/graphql/schema/field_extension.rb +89 -2
  221. data/lib/graphql/schema/find_inherited_value.rb +36 -0
  222. data/lib/graphql/schema/finder.rb +16 -14
  223. data/lib/graphql/schema/input_object.rb +178 -34
  224. data/lib/graphql/schema/interface.rb +35 -25
  225. data/lib/graphql/schema/introspection_system.rb +111 -35
  226. data/lib/graphql/schema/late_bound_type.rb +3 -2
  227. data/lib/graphql/schema/list.rb +65 -1
  228. data/lib/graphql/schema/loader.rb +147 -97
  229. data/lib/graphql/schema/member/accepts_definition.rb +15 -3
  230. data/lib/graphql/schema/member/base_dsl_methods.rb +40 -45
  231. data/lib/graphql/schema/member/build_type.rb +19 -8
  232. data/lib/graphql/schema/member/cached_graphql_definition.rb +34 -2
  233. data/lib/graphql/schema/member/has_arguments.rb +212 -22
  234. data/lib/graphql/schema/member/has_ast_node.rb +20 -0
  235. data/lib/graphql/schema/member/has_deprecation_reason.rb +25 -0
  236. data/lib/graphql/schema/member/has_directives.rb +98 -0
  237. data/lib/graphql/schema/member/has_fields.rb +113 -28
  238. data/lib/graphql/schema/member/has_interfaces.rb +100 -0
  239. data/lib/graphql/schema/member/has_unresolved_type_error.rb +15 -0
  240. data/lib/graphql/schema/member/has_validators.rb +31 -0
  241. data/lib/graphql/schema/member/instrumentation.rb +6 -2
  242. data/lib/graphql/schema/member/relay_shortcuts.rb +2 -2
  243. data/lib/graphql/schema/member/type_system_helpers.rb +3 -3
  244. data/lib/graphql/schema/member/validates_input.rb +33 -0
  245. data/lib/graphql/schema/member.rb +11 -0
  246. data/lib/graphql/schema/middleware_chain.rb +1 -1
  247. data/lib/graphql/schema/mutation.rb +5 -1
  248. data/lib/graphql/schema/non_null.rb +37 -1
  249. data/lib/graphql/schema/object.rb +52 -37
  250. data/lib/graphql/schema/possible_types.rb +12 -7
  251. data/lib/graphql/schema/printer.rb +17 -34
  252. data/lib/graphql/schema/relay_classic_mutation.rb +51 -7
  253. data/lib/graphql/schema/resolver/has_payload_type.rb +36 -5
  254. data/lib/graphql/schema/resolver.rb +159 -59
  255. data/lib/graphql/schema/scalar.rb +43 -3
  256. data/lib/graphql/schema/subscription.rb +83 -25
  257. data/lib/graphql/schema/timeout.rb +123 -0
  258. data/lib/graphql/schema/timeout_middleware.rb +6 -3
  259. data/lib/graphql/schema/traversal.rb +2 -2
  260. data/lib/graphql/schema/type_expression.rb +21 -13
  261. data/lib/graphql/schema/type_membership.rb +48 -0
  262. data/lib/graphql/schema/union.rb +67 -6
  263. data/lib/graphql/schema/unique_within_type.rb +1 -2
  264. data/lib/graphql/schema/validation.rb +30 -8
  265. data/lib/graphql/schema/validator/allow_blank_validator.rb +29 -0
  266. data/lib/graphql/schema/validator/allow_null_validator.rb +26 -0
  267. data/lib/graphql/schema/validator/exclusion_validator.rb +33 -0
  268. data/lib/graphql/schema/validator/format_validator.rb +48 -0
  269. data/lib/graphql/schema/validator/inclusion_validator.rb +35 -0
  270. data/lib/graphql/schema/validator/length_validator.rb +59 -0
  271. data/lib/graphql/schema/validator/numericality_validator.rb +82 -0
  272. data/lib/graphql/schema/validator/required_validator.rb +82 -0
  273. data/lib/graphql/schema/validator.rb +171 -0
  274. data/lib/graphql/schema/warden.rb +263 -30
  275. data/lib/graphql/schema/wrapper.rb +1 -1
  276. data/lib/graphql/schema.rb +1016 -256
  277. data/lib/graphql/static_validation/all_rules.rb +2 -0
  278. data/lib/graphql/static_validation/base_visitor.rb +17 -10
  279. data/lib/graphql/static_validation/definition_dependencies.rb +21 -13
  280. data/lib/graphql/static_validation/error.rb +3 -1
  281. data/lib/graphql/static_validation/literal_validator.rb +52 -27
  282. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +46 -79
  283. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +23 -6
  284. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +35 -26
  285. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +4 -2
  286. data/lib/graphql/static_validation/rules/directives_are_defined.rb +1 -1
  287. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -2
  288. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -4
  289. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -5
  290. data/lib/graphql/static_validation/rules/fields_will_merge.rb +105 -55
  291. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +25 -4
  292. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  293. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +2 -2
  294. data/lib/graphql/static_validation/rules/input_object_names_are_unique.rb +30 -0
  295. data/lib/graphql/static_validation/rules/input_object_names_are_unique_error.rb +30 -0
  296. data/lib/graphql/static_validation/rules/query_root_exists.rb +17 -0
  297. data/lib/graphql/static_validation/rules/query_root_exists_error.rb +26 -0
  298. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +5 -3
  299. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +9 -10
  300. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
  301. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +12 -13
  302. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +19 -14
  303. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +1 -1
  304. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +5 -3
  305. data/lib/graphql/static_validation/type_stack.rb +2 -2
  306. data/lib/graphql/static_validation/validation_context.rb +13 -3
  307. data/lib/graphql/static_validation/validation_timeout_error.rb +25 -0
  308. data/lib/graphql/static_validation/validator.rb +43 -9
  309. data/lib/graphql/static_validation.rb +1 -0
  310. data/lib/graphql/string_encoding_error.rb +13 -3
  311. data/lib/graphql/string_type.rb +1 -1
  312. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +123 -22
  313. data/lib/graphql/subscriptions/broadcast_analyzer.rb +81 -0
  314. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +21 -0
  315. data/lib/graphql/subscriptions/event.rb +94 -26
  316. data/lib/graphql/subscriptions/instrumentation.rb +10 -6
  317. data/lib/graphql/subscriptions/serialize.rb +53 -6
  318. data/lib/graphql/subscriptions/subscription_root.rb +15 -5
  319. data/lib/graphql/subscriptions.rb +122 -54
  320. data/lib/graphql/tracing/active_support_notifications_tracing.rb +8 -17
  321. data/lib/graphql/tracing/appoptics_tracing.rb +173 -0
  322. data/lib/graphql/tracing/appsignal_tracing.rb +23 -0
  323. data/lib/graphql/tracing/data_dog_tracing.rb +32 -2
  324. data/lib/graphql/tracing/new_relic_tracing.rb +9 -12
  325. data/lib/graphql/tracing/notifications_tracing.rb +59 -0
  326. data/lib/graphql/tracing/platform_tracing.rb +66 -7
  327. data/lib/graphql/tracing/prometheus_tracing/graphql_collector.rb +4 -1
  328. data/lib/graphql/tracing/prometheus_tracing.rb +8 -0
  329. data/lib/graphql/tracing/scout_tracing.rb +19 -0
  330. data/lib/graphql/tracing/skylight_tracing.rb +9 -0
  331. data/lib/graphql/tracing/statsd_tracing.rb +42 -0
  332. data/lib/graphql/tracing.rb +15 -35
  333. data/lib/graphql/types/big_int.rb +5 -1
  334. data/lib/graphql/types/int.rb +10 -3
  335. data/lib/graphql/types/iso_8601_date.rb +42 -0
  336. data/lib/graphql/types/iso_8601_date_time.rb +32 -8
  337. data/lib/graphql/types/relay/base_connection.rb +6 -88
  338. data/lib/graphql/types/relay/base_edge.rb +2 -37
  339. data/lib/graphql/types/relay/connection_behaviors.rb +174 -0
  340. data/lib/graphql/types/relay/default_relay.rb +31 -0
  341. data/lib/graphql/types/relay/edge_behaviors.rb +64 -0
  342. data/lib/graphql/types/relay/has_node_field.rb +41 -0
  343. data/lib/graphql/types/relay/has_nodes_field.rb +41 -0
  344. data/lib/graphql/types/relay/node.rb +2 -4
  345. data/lib/graphql/types/relay/node_behaviors.rb +15 -0
  346. data/lib/graphql/types/relay/node_field.rb +4 -23
  347. data/lib/graphql/types/relay/nodes_field.rb +16 -18
  348. data/lib/graphql/types/relay/page_info.rb +2 -14
  349. data/lib/graphql/types/relay/page_info_behaviors.rb +25 -0
  350. data/lib/graphql/types/relay.rb +11 -3
  351. data/lib/graphql/types/string.rb +8 -2
  352. data/lib/graphql/types.rb +1 -0
  353. data/lib/graphql/unauthorized_error.rb +2 -2
  354. data/lib/graphql/union_type.rb +61 -46
  355. data/lib/graphql/unresolved_type_error.rb +2 -2
  356. data/lib/graphql/upgrader/member.rb +150 -112
  357. data/lib/graphql/upgrader/schema.rb +1 -0
  358. data/lib/graphql/version.rb +1 -1
  359. data/lib/graphql.rb +89 -18
  360. data/readme.md +4 -7
  361. metadata +115 -703
  362. data/lib/graphql/execution/interpreter/hash_response.rb +0 -46
  363. data/lib/graphql/literal_validation_error.rb +0 -6
  364. data/lib/graphql/types/relay/base_field.rb +0 -22
  365. data/lib/graphql/types/relay/base_interface.rb +0 -29
  366. data/lib/graphql/types/relay/base_object.rb +0 -26
  367. data/spec/dummy/Gemfile +0 -12
  368. data/spec/dummy/Gemfile.lock +0 -157
  369. data/spec/dummy/README.md +0 -24
  370. data/spec/dummy/Rakefile +0 -7
  371. data/spec/dummy/app/assets/config/manifest.js +0 -1
  372. data/spec/dummy/app/assets/javascripts/application.js +0 -66
  373. data/spec/dummy/app/channels/application_cable/channel.rb +0 -5
  374. data/spec/dummy/app/channels/application_cable/connection.rb +0 -5
  375. data/spec/dummy/app/channels/graphql_channel.rb +0 -116
  376. data/spec/dummy/app/controllers/application_controller.rb +0 -4
  377. data/spec/dummy/app/controllers/pages_controller.rb +0 -5
  378. data/spec/dummy/app/helpers/application_helper.rb +0 -3
  379. data/spec/dummy/app/jobs/application_job.rb +0 -3
  380. data/spec/dummy/app/views/layouts/application.html.erb +0 -12
  381. data/spec/dummy/app/views/pages/show.html +0 -16
  382. data/spec/dummy/bin/bundle +0 -4
  383. data/spec/dummy/bin/rails +0 -5
  384. data/spec/dummy/bin/rake +0 -5
  385. data/spec/dummy/bin/setup +0 -31
  386. data/spec/dummy/bin/update +0 -27
  387. data/spec/dummy/bin/yarn +0 -12
  388. data/spec/dummy/config/application.rb +0 -30
  389. data/spec/dummy/config/boot.rb +0 -4
  390. data/spec/dummy/config/cable.yml +0 -10
  391. data/spec/dummy/config/environment.rb +0 -6
  392. data/spec/dummy/config/environments/development.rb +0 -40
  393. data/spec/dummy/config/environments/production.rb +0 -76
  394. data/spec/dummy/config/environments/test.rb +0 -37
  395. data/spec/dummy/config/initializers/application_controller_renderer.rb +0 -9
  396. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -8
  397. data/spec/dummy/config/initializers/cookies_serializer.rb +0 -6
  398. data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -5
  399. data/spec/dummy/config/initializers/inflections.rb +0 -17
  400. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  401. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -10
  402. data/spec/dummy/config/locales/en.yml +0 -33
  403. data/spec/dummy/config/puma.rb +0 -57
  404. data/spec/dummy/config/routes.rb +0 -4
  405. data/spec/dummy/config/secrets.yml +0 -32
  406. data/spec/dummy/config.ru +0 -6
  407. data/spec/dummy/log/test.log +0 -199
  408. data/spec/dummy/package.json +0 -5
  409. data/spec/dummy/public/404.html +0 -67
  410. data/spec/dummy/public/422.html +0 -67
  411. data/spec/dummy/public/500.html +0 -66
  412. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  413. data/spec/dummy/public/apple-touch-icon.png +0 -0
  414. data/spec/dummy/public/favicon.ico +0 -0
  415. data/spec/dummy/public/robots.txt +0 -1
  416. data/spec/dummy/test/application_system_test_case.rb +0 -6
  417. data/spec/dummy/test/system/action_cable_subscription_test.rb +0 -45
  418. data/spec/dummy/test/test_helper.rb +0 -4
  419. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4w/4wzXRZrAkwKdgYaSE0pid5eB-fer8vSfSku_NPg4rMA.cache +0 -0
  420. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7I/7IHVBiJT06QSpgLpLoJIxboQ0B-D_tMTxsvoezBTV3Q.cache +0 -1
  421. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8w/8wY_SKagj8wHuwGNAAf6JnQ8joMbC6cEYpHrTAI8Urc.cache +0 -1
  422. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/AK/AKzz1u6bGb4auXcrObA_g5LL-oV0ejNGa448AgAi_WQ.cache +0 -1
  423. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ET/ETW4uxvaYpruL8y6_ZptUH82ZowMaHIqvg5WexBFdEM.cache +0 -3
  424. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F1/F1TWpjjyA56k9Z90n5B3xRn7DUdGjX73QCkYC6k07JQ.cache +0 -0
  425. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -2
  426. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -2
  427. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ms/MsKSimH_UCB-H1tLvDABDHuvGciuoW6kVqQWDrXU5FQ.cache +0 -0
  428. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Mt/Mtci-Kim50aPOmeClD4AIicKn1d1WJ0n454IjSd94sk.cache +0 -0
  429. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QH/QHt3Tc1Y6M66Oo_pDuMyWrQNs4Pp3SMeZR5K1wJj2Ts.cache +0 -1
  430. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/XU/XU4k1OXnfMils5SrirorPvDSyDSqiOWLZNtmAH1HH8k.cache +0 -0
  431. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ZI/ZIof7mZxWWCnraIFOCuV6a8QRWzKJXJnx2Xd7C0ZyX0.cache +0 -1
  432. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cG/cGc_puuPS5pZKgUcy1Y_i1L6jl5UtsiIrMH59rTzR6c.cache +0 -3
  433. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/df/dfro_B6bx3KP1Go-7jEOqqZ2j4hVRseXIc3es9PKQno.cache +0 -1
  434. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jO/jO1DfbqnG0mTULsjJJANc3fefrG2zt7DIMmcptMT628.cache +0 -1
  435. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pE/pE7gO6pQ-z187Swb4hT554wmqsq-cNzgPWLrCz-LQQQ.cache +0 -0
  436. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/r9/r9iU1l58a6rxkZSW5RSC52_tD-_UQuHxoMVnkfJ7Mhs.cache +0 -1
  437. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xi/xitPPFfPIyDMpaznV0sBBcw8eSCV8PJcLLWin78sCgE.cache +0 -0
  438. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  439. data/spec/fixtures/upgrader/account.original.rb +0 -19
  440. data/spec/fixtures/upgrader/account.transformed.rb +0 -20
  441. data/spec/fixtures/upgrader/blame_range.original.rb +0 -43
  442. data/spec/fixtures/upgrader/blame_range.transformed.rb +0 -30
  443. data/spec/fixtures/upgrader/date_time.original.rb +0 -24
  444. data/spec/fixtures/upgrader/date_time.transformed.rb +0 -23
  445. data/spec/fixtures/upgrader/delete_project.original.rb +0 -28
  446. data/spec/fixtures/upgrader/delete_project.transformed.rb +0 -27
  447. data/spec/fixtures/upgrader/gist_order_field.original.rb +0 -14
  448. data/spec/fixtures/upgrader/gist_order_field.transformed.rb +0 -13
  449. data/spec/fixtures/upgrader/increment_count.original.rb +0 -59
  450. data/spec/fixtures/upgrader/increment_count.transformed.rb +0 -50
  451. data/spec/fixtures/upgrader/photo.original.rb +0 -10
  452. data/spec/fixtures/upgrader/photo.transformed.rb +0 -12
  453. data/spec/fixtures/upgrader/release_order.original.rb +0 -15
  454. data/spec/fixtures/upgrader/release_order.transformed.rb +0 -14
  455. data/spec/fixtures/upgrader/starrable.original.rb +0 -49
  456. data/spec/fixtures/upgrader/starrable.transformed.rb +0 -46
  457. data/spec/fixtures/upgrader/subscribable.original.rb +0 -55
  458. data/spec/fixtures/upgrader/subscribable.transformed.rb +0 -51
  459. data/spec/fixtures/upgrader/type_x.original.rb +0 -65
  460. data/spec/fixtures/upgrader/type_x.transformed.rb +0 -56
  461. data/spec/graphql/analysis/analyze_query_spec.rb +0 -272
  462. data/spec/graphql/analysis/ast/field_usage_spec.rb +0 -51
  463. data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +0 -120
  464. data/spec/graphql/analysis/ast/max_query_depth_spec.rb +0 -114
  465. data/spec/graphql/analysis/ast/query_complexity_spec.rb +0 -299
  466. data/spec/graphql/analysis/ast/query_depth_spec.rb +0 -108
  467. data/spec/graphql/analysis/ast_spec.rb +0 -269
  468. data/spec/graphql/analysis/field_usage_spec.rb +0 -62
  469. data/spec/graphql/analysis/max_query_complexity_spec.rb +0 -102
  470. data/spec/graphql/analysis/max_query_depth_spec.rb +0 -101
  471. data/spec/graphql/analysis/query_complexity_spec.rb +0 -301
  472. data/spec/graphql/analysis/query_depth_spec.rb +0 -81
  473. data/spec/graphql/argument_spec.rb +0 -159
  474. data/spec/graphql/authorization_spec.rb +0 -974
  475. data/spec/graphql/backtrace_spec.rb +0 -206
  476. data/spec/graphql/base_type_spec.rb +0 -171
  477. data/spec/graphql/boolean_type_spec.rb +0 -21
  478. data/spec/graphql/compatibility/execution_specification_spec.rb +0 -4
  479. data/spec/graphql/compatibility/lazy_execution_specification_spec.rb +0 -4
  480. data/spec/graphql/compatibility/query_parser_specification_spec.rb +0 -6
  481. data/spec/graphql/compatibility/schema_parser_specification_spec.rb +0 -6
  482. data/spec/graphql/define/assign_argument_spec.rb +0 -61
  483. data/spec/graphql/define/instance_definable_spec.rb +0 -203
  484. data/spec/graphql/directive/skip_directive_spec.rb +0 -9
  485. data/spec/graphql/directive_spec.rb +0 -295
  486. data/spec/graphql/enum_type_spec.rb +0 -158
  487. data/spec/graphql/execution/execute_spec.rb +0 -303
  488. data/spec/graphql/execution/instrumentation_spec.rb +0 -184
  489. data/spec/graphql/execution/interpreter_spec.rb +0 -485
  490. data/spec/graphql/execution/lazy/lazy_method_map_spec.rb +0 -57
  491. data/spec/graphql/execution/lazy_spec.rb +0 -247
  492. data/spec/graphql/execution/lookahead_spec.rb +0 -390
  493. data/spec/graphql/execution/multiplex_spec.rb +0 -211
  494. data/spec/graphql/execution/typecast_spec.rb +0 -47
  495. data/spec/graphql/execution_error_spec.rb +0 -325
  496. data/spec/graphql/field_spec.rb +0 -246
  497. data/spec/graphql/float_type_spec.rb +0 -16
  498. data/spec/graphql/function_spec.rb +0 -152
  499. data/spec/graphql/id_type_spec.rb +0 -33
  500. data/spec/graphql/input_object_type_spec.rb +0 -25
  501. data/spec/graphql/int_type_spec.rb +0 -35
  502. data/spec/graphql/interface_type_spec.rb +0 -196
  503. data/spec/graphql/internal_representation/print_spec.rb +0 -41
  504. data/spec/graphql/internal_representation/rewrite_spec.rb +0 -376
  505. data/spec/graphql/introspection/directive_type_spec.rb +0 -61
  506. data/spec/graphql/introspection/input_value_type_spec.rb +0 -144
  507. data/spec/graphql/introspection/introspection_query_spec.rb +0 -59
  508. data/spec/graphql/introspection/schema_type_spec.rb +0 -56
  509. data/spec/graphql/introspection/type_type_spec.rb +0 -155
  510. data/spec/graphql/language/block_string_spec.rb +0 -70
  511. data/spec/graphql/language/definition_slice_spec.rb +0 -226
  512. data/spec/graphql/language/document_from_schema_definition_spec.rb +0 -770
  513. data/spec/graphql/language/equality_spec.rb +0 -84
  514. data/spec/graphql/language/generation_spec.rb +0 -38
  515. data/spec/graphql/language/lexer_spec.rb +0 -135
  516. data/spec/graphql/language/nodes_spec.rb +0 -67
  517. data/spec/graphql/language/parser_spec.rb +0 -183
  518. data/spec/graphql/language/printer_spec.rb +0 -215
  519. data/spec/graphql/language/visitor_spec.rb +0 -419
  520. data/spec/graphql/list_type_spec.rb +0 -57
  521. data/spec/graphql/non_null_type_spec.rb +0 -48
  522. data/spec/graphql/object_type_spec.rb +0 -197
  523. data/spec/graphql/query/arguments_spec.rb +0 -346
  524. data/spec/graphql/query/context_spec.rb +0 -292
  525. data/spec/graphql/query/executor_spec.rb +0 -341
  526. data/spec/graphql/query/literal_input_spec.rb +0 -91
  527. data/spec/graphql/query/result_spec.rb +0 -29
  528. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +0 -109
  529. data/spec/graphql/query_spec.rb +0 -800
  530. data/spec/graphql/rake_task_spec.rb +0 -59
  531. data/spec/graphql/scalar_type_spec.rb +0 -66
  532. data/spec/graphql/schema/argument_spec.rb +0 -152
  533. data/spec/graphql/schema/build_from_definition_spec.rb +0 -1187
  534. data/spec/graphql/schema/catchall_middleware_spec.rb +0 -35
  535. data/spec/graphql/schema/directive/feature_spec.rb +0 -81
  536. data/spec/graphql/schema/directive/transform_spec.rb +0 -39
  537. data/spec/graphql/schema/enum_spec.rb +0 -83
  538. data/spec/graphql/schema/enum_value_spec.rb +0 -24
  539. data/spec/graphql/schema/field_extension_spec.rb +0 -137
  540. data/spec/graphql/schema/field_spec.rb +0 -301
  541. data/spec/graphql/schema/finder_spec.rb +0 -135
  542. data/spec/graphql/schema/input_object_spec.rb +0 -347
  543. data/spec/graphql/schema/instrumentation_spec.rb +0 -43
  544. data/spec/graphql/schema/interface_spec.rb +0 -215
  545. data/spec/graphql/schema/introspection_system_spec.rb +0 -56
  546. data/spec/graphql/schema/list_spec.rb +0 -46
  547. data/spec/graphql/schema/loader_spec.rb +0 -286
  548. data/spec/graphql/schema/member/accepts_definition_spec.rb +0 -115
  549. data/spec/graphql/schema/member/build_type_spec.rb +0 -63
  550. data/spec/graphql/schema/member/scoped_spec.rb +0 -217
  551. data/spec/graphql/schema/member/type_system_helpers_spec.rb +0 -63
  552. data/spec/graphql/schema/middleware_chain_spec.rb +0 -57
  553. data/spec/graphql/schema/mutation_spec.rb +0 -150
  554. data/spec/graphql/schema/non_null_spec.rb +0 -46
  555. data/spec/graphql/schema/object_spec.rb +0 -315
  556. data/spec/graphql/schema/printer_spec.rb +0 -869
  557. data/spec/graphql/schema/relay_classic_mutation_spec.rb +0 -252
  558. data/spec/graphql/schema/rescue_middleware_spec.rb +0 -88
  559. data/spec/graphql/schema/resolver_spec.rb +0 -714
  560. data/spec/graphql/schema/scalar_spec.rb +0 -101
  561. data/spec/graphql/schema/subscription_spec.rb +0 -440
  562. data/spec/graphql/schema/timeout_middleware_spec.rb +0 -188
  563. data/spec/graphql/schema/traversal_spec.rb +0 -222
  564. data/spec/graphql/schema/type_expression_spec.rb +0 -39
  565. data/spec/graphql/schema/union_spec.rb +0 -72
  566. data/spec/graphql/schema/unique_within_type_spec.rb +0 -44
  567. data/spec/graphql/schema/validation_spec.rb +0 -355
  568. data/spec/graphql/schema/warden_spec.rb +0 -926
  569. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +0 -413
  570. data/spec/graphql/static_validation/rules/argument_names_are_unique_spec.rb +0 -44
  571. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +0 -112
  572. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +0 -35
  573. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +0 -42
  574. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +0 -167
  575. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +0 -66
  576. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +0 -740
  577. data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +0 -28
  578. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +0 -52
  579. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +0 -42
  580. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +0 -123
  581. data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +0 -24
  582. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +0 -56
  583. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +0 -61
  584. data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +0 -39
  585. data/spec/graphql/static_validation/rules/no_definitions_are_present_spec.rb +0 -62
  586. data/spec/graphql/static_validation/rules/operation_names_are_valid_spec.rb +0 -82
  587. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +0 -73
  588. data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb +0 -86
  589. data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +0 -34
  590. data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +0 -188
  591. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +0 -196
  592. data/spec/graphql/static_validation/rules/variable_names_are_unique_spec.rb +0 -23
  593. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +0 -236
  594. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +0 -78
  595. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +0 -81
  596. data/spec/graphql/static_validation/type_stack_spec.rb +0 -29
  597. data/spec/graphql/static_validation/validator_spec.rb +0 -204
  598. data/spec/graphql/string_type_spec.rb +0 -80
  599. data/spec/graphql/subscriptions/serialize_spec.rb +0 -49
  600. data/spec/graphql/subscriptions_spec.rb +0 -540
  601. data/spec/graphql/tracing/new_relic_tracing_spec.rb +0 -84
  602. data/spec/graphql/tracing/platform_tracing_spec.rb +0 -141
  603. data/spec/graphql/tracing/prometheus_tracing_spec.rb +0 -42
  604. data/spec/graphql/tracing/scout_tracing_spec.rb +0 -17
  605. data/spec/graphql/tracing/skylight_tracing_spec.rb +0 -63
  606. data/spec/graphql/tracing_spec.rb +0 -52
  607. data/spec/graphql/types/big_int_spec.rb +0 -24
  608. data/spec/graphql/types/iso_8601_date_time_spec.rb +0 -137
  609. data/spec/graphql/types/relay/base_edge_spec.rb +0 -33
  610. data/spec/graphql/union_type_spec.rb +0 -211
  611. data/spec/graphql/upgrader/member_spec.rb +0 -583
  612. data/spec/graphql/upgrader/schema_spec.rb +0 -82
  613. data/spec/integration/mongoid/graphql/relay/mongo_relation_connection_spec.rb +0 -528
  614. data/spec/integration/mongoid/spec_helper.rb +0 -2
  615. data/spec/integration/mongoid/star_trek/data.rb +0 -126
  616. data/spec/integration/mongoid/star_trek/schema.rb +0 -425
  617. data/spec/integration/rails/data.rb +0 -110
  618. data/spec/integration/rails/generators/base_generator_test.rb +0 -7
  619. data/spec/integration/rails/generators/graphql/enum_generator_spec.rb +0 -30
  620. data/spec/integration/rails/generators/graphql/install_generator_spec.rb +0 -218
  621. data/spec/integration/rails/generators/graphql/interface_generator_spec.rb +0 -34
  622. data/spec/integration/rails/generators/graphql/loader_generator_spec.rb +0 -59
  623. data/spec/integration/rails/generators/graphql/mutation_generator_spec.rb +0 -71
  624. data/spec/integration/rails/generators/graphql/object_generator_spec.rb +0 -54
  625. data/spec/integration/rails/generators/graphql/scalar_generator_spec.rb +0 -28
  626. data/spec/integration/rails/generators/graphql/union_generator_spec.rb +0 -67
  627. data/spec/integration/rails/graphql/input_object_type_spec.rb +0 -364
  628. data/spec/integration/rails/graphql/query/variables_spec.rb +0 -375
  629. data/spec/integration/rails/graphql/relay/array_connection_spec.rb +0 -290
  630. data/spec/integration/rails/graphql/relay/base_connection_spec.rb +0 -101
  631. data/spec/integration/rails/graphql/relay/connection_instrumentation_spec.rb +0 -80
  632. data/spec/integration/rails/graphql/relay/connection_resolve_spec.rb +0 -79
  633. data/spec/integration/rails/graphql/relay/connection_type_spec.rb +0 -106
  634. data/spec/integration/rails/graphql/relay/edge_spec.rb +0 -10
  635. data/spec/integration/rails/graphql/relay/mutation_spec.rb +0 -387
  636. data/spec/integration/rails/graphql/relay/node_spec.rb +0 -263
  637. data/spec/integration/rails/graphql/relay/page_info_spec.rb +0 -111
  638. data/spec/integration/rails/graphql/relay/range_add_spec.rb +0 -117
  639. data/spec/integration/rails/graphql/relay/relation_connection_spec.rb +0 -837
  640. data/spec/integration/rails/graphql/schema_spec.rb +0 -489
  641. data/spec/integration/rails/graphql/tracing/active_support_notifications_tracing_spec.rb +0 -62
  642. data/spec/integration/rails/spec_helper.rb +0 -25
  643. data/spec/integration/tmp/app/graphql/types/bird_type.rb +0 -7
  644. data/spec/spec_helper.rb +0 -116
  645. data/spec/support/dummy/data.rb +0 -45
  646. data/spec/support/dummy/schema.rb +0 -511
  647. data/spec/support/error_bubbling_helpers.rb +0 -23
  648. data/spec/support/global_id.rb +0 -23
  649. data/spec/support/jazz.rb +0 -772
  650. data/spec/support/lazy_helpers.rb +0 -192
  651. data/spec/support/magic_cards/schema.graphql +0 -33
  652. data/spec/support/minimum_input_object.rb +0 -21
  653. data/spec/support/new_relic.rb +0 -27
  654. data/spec/support/parser/filename_example.graphql +0 -5
  655. data/spec/support/parser/filename_example_error_1.graphql +0 -4
  656. data/spec/support/parser/filename_example_error_2.graphql +0 -5
  657. data/spec/support/skylight.rb +0 -39
  658. data/spec/support/star_wars/schema.rb +0 -465
  659. data/spec/support/static_validation_helpers.rb +0 -32
@@ -1,974 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
-
4
- describe GraphQL::Authorization do
5
- module AuthTest
6
- class Box
7
- attr_reader :value
8
- def initialize(value:)
9
- @value = value
10
- end
11
- end
12
-
13
- class BaseArgument < GraphQL::Schema::Argument
14
- def visible?(context)
15
- super && (context[:hide] ? @name != "hidden" : true)
16
- end
17
-
18
- def accessible?(context)
19
- super && (context[:hide] ? @name != "inaccessible" : true)
20
- end
21
-
22
- def authorized?(parent_object, context)
23
- super && parent_object != :hide2
24
- end
25
- end
26
-
27
- class BaseField < GraphQL::Schema::Field
28
- def initialize(*args, edge_class: nil, **kwargs, &block)
29
- @edge_class = edge_class
30
- super(*args, **kwargs, &block)
31
- end
32
-
33
- def to_graphql
34
- field_defn = super
35
- if @edge_class
36
- field_defn.edge_class = @edge_class
37
- end
38
- field_defn
39
- end
40
-
41
- argument_class BaseArgument
42
- def visible?(context)
43
- super && (context[:hide] ? @name != "hidden" : true)
44
- end
45
-
46
- def accessible?(context)
47
- super && (context[:hide] ? @name != "inaccessible" : true)
48
- end
49
-
50
- def authorized?(object, context)
51
- if object == :raise
52
- raise GraphQL::UnauthorizedFieldError.new("raised authorized field error", object: object)
53
- end
54
- super && object != :hide && object != :replace
55
- end
56
- end
57
-
58
- class BaseObject < GraphQL::Schema::Object
59
- field_class BaseField
60
- end
61
-
62
- module BaseInterface
63
- include GraphQL::Schema::Interface
64
- end
65
-
66
- class BaseEnumValue < GraphQL::Schema::EnumValue
67
- def initialize(*args, role: nil, **kwargs)
68
- @role = role
69
- super(*args, **kwargs)
70
- end
71
-
72
- def visible?(context)
73
- super && (context[:hide] ? @role != :hidden : true)
74
- end
75
- end
76
-
77
- class BaseEnum < GraphQL::Schema::Enum
78
- enum_value_class(BaseEnumValue)
79
- end
80
-
81
- module HiddenInterface
82
- include BaseInterface
83
-
84
- def self.visible?(ctx)
85
- super && !ctx[:hide]
86
- end
87
-
88
- def self.resolve_type(obj, ctx)
89
- HiddenObject
90
- end
91
- end
92
-
93
- module HiddenDefaultInterface
94
- include BaseInterface
95
- # visible? will call the super method
96
- def self.resolve_type(obj, ctx)
97
- HiddenObject
98
- end
99
- end
100
-
101
- class HiddenObject < BaseObject
102
- implements HiddenInterface
103
- implements HiddenDefaultInterface
104
- def self.visible?(ctx)
105
- super && !ctx[:hide]
106
- end
107
- end
108
-
109
- class RelayObject < BaseObject
110
- def self.visible?(ctx)
111
- super && !ctx[:hidden_relay]
112
- end
113
-
114
- def self.accessible?(ctx)
115
- super && !ctx[:inaccessible_relay]
116
- end
117
-
118
- def self.authorized?(_val, ctx)
119
- super && !ctx[:unauthorized_relay]
120
- end
121
- end
122
-
123
- # TODO test default behavior for abstract types,
124
- # that they check their concrete types
125
- module InaccessibleInterface
126
- include BaseInterface
127
-
128
- def self.accessible?(ctx)
129
- super && !ctx[:hide]
130
- end
131
-
132
- def self.resolve_type(obj, ctx)
133
- InaccessibleObject
134
- end
135
- end
136
-
137
- module InaccessibleDefaultInterface
138
- include BaseInterface
139
- # accessible? will call the super method
140
- def self.resolve_type(obj, ctx)
141
- InaccessibleObject
142
- end
143
- end
144
-
145
- class InaccessibleObject < BaseObject
146
- implements InaccessibleInterface
147
- implements InaccessibleDefaultInterface
148
- def self.accessible?(ctx)
149
- super && !ctx[:hide]
150
- end
151
- end
152
-
153
- class UnauthorizedObject < BaseObject
154
- def self.authorized?(value, context)
155
- if context[:raise]
156
- raise GraphQL::UnauthorizedError.new("raised authorized object error", object: value.object)
157
- end
158
- super && !context[:hide]
159
- end
160
-
161
- field :value, String, null: false, method: :itself
162
- end
163
-
164
- class UnauthorizedBox < BaseObject
165
- # Hide `"a"`
166
- def self.authorized?(value, context)
167
- super && value != "a"
168
- end
169
-
170
- field :value, String, null: false, method: :itself
171
- end
172
-
173
- module UnauthorizedInterface
174
- include BaseInterface
175
-
176
- def self.resolve_type(obj, ctx)
177
- if obj.is_a?(String)
178
- UnauthorizedCheckBox
179
- else
180
- raise "Unexpected value: #{obj.inspect}"
181
- end
182
- end
183
- end
184
-
185
- class UnauthorizedCheckBox < BaseObject
186
- implements UnauthorizedInterface
187
- # This authorized check returns a lazy object, it should be synced by the runtime.
188
- def self.authorized?(value, context)
189
- if !value.is_a?(String)
190
- raise "Unexpected box value: #{value.inspect}"
191
- end
192
- is_authed = super && value != "a"
193
- # Make it many levels nested just to make sure we support nested lazy objects
194
- Box.new(value: Box.new(value: Box.new(value: Box.new(value: is_authed))))
195
- end
196
-
197
- field :value, String, null: false, method: :itself
198
- end
199
-
200
- class IntegerObject < BaseObject
201
- def self.authorized?(obj, ctx)
202
- if !obj.is_a?(Integer)
203
- raise "Unexpected IntegerObject: #{obj}"
204
- end
205
- is_allowed = !(ctx[:unauthorized_relay] || obj == ctx[:exclude_integer])
206
- Box.new(value: Box.new(value: is_allowed))
207
- end
208
- field :value, Integer, null: false, method: :itself
209
- end
210
-
211
- class IntegerObjectEdge < GraphQL::Types::Relay::BaseEdge
212
- node_type(IntegerObject)
213
- end
214
-
215
- class IntegerObjectConnection < GraphQL::Types::Relay::BaseConnection
216
- edge_type(IntegerObjectEdge)
217
- end
218
-
219
- # This object responds with `replaced => false`,
220
- # but if its replacement value is used, it gives `replaced => true`
221
- class Replaceable
222
- def replacement
223
- { replaced: true }
224
- end
225
-
226
- def replaced
227
- false
228
- end
229
- end
230
-
231
- class ReplacedObject < BaseObject
232
- def self.authorized?(obj, ctx)
233
- super && !ctx[:replace_me]
234
- end
235
-
236
- field :replaced, Boolean, null: false
237
- end
238
-
239
- class LandscapeFeature < BaseEnum
240
- value "MOUNTAIN"
241
- value "STREAM", role: :unauthorized
242
- value "FIELD", role: :inaccessible
243
- value "TAR_PIT", role: :hidden
244
- end
245
-
246
- class Query < BaseObject
247
- def self.authorized?(obj, ctx)
248
- !ctx[:query_unauthorized]
249
- end
250
-
251
- field :hidden, Integer, null: false
252
- field :unauthorized, Integer, null: true, method: :itself
253
- field :int2, Integer, null: true do
254
- argument :int, Integer, required: false
255
- argument :hidden, Integer, required: false
256
- argument :inaccessible, Integer, required: false
257
- argument :unauthorized, Integer, required: false
258
- end
259
-
260
- def int2(**args)
261
- args[:unauthorized] || 1
262
- end
263
-
264
- field :landscape_feature, LandscapeFeature, null: false do
265
- argument :string, String, required: false
266
- argument :enum, LandscapeFeature, required: false
267
- end
268
-
269
- def landscape_feature(string: nil, enum: nil)
270
- string || enum
271
- end
272
-
273
- field :landscape_features, [LandscapeFeature], null: false do
274
- argument :strings, [String], required: false
275
- argument :enums, [LandscapeFeature], required: false
276
- end
277
-
278
- def landscape_features(strings: [], enums: [])
279
- strings + enums
280
- end
281
-
282
- def empty_array; []; end
283
- field :hidden_object, HiddenObject, null: false, resolver_method: :itself
284
- field :hidden_interface, HiddenInterface, null: false, resolver_method: :itself
285
- field :hidden_default_interface, HiddenDefaultInterface, null: false, resolver_method: :itself
286
- field :hidden_connection, RelayObject.connection_type, null: :false, resolver_method: :empty_array
287
- field :hidden_edge, RelayObject.edge_type, null: :false, resolver_method: :edge_object
288
-
289
- field :inaccessible, Integer, null: false, method: :object_id
290
- field :inaccessible_object, InaccessibleObject, null: false, resolver_method: :itself
291
- field :inaccessible_interface, InaccessibleInterface, null: false, resolver_method: :itself
292
- field :inaccessible_default_interface, InaccessibleDefaultInterface, null: false, resolver_method: :itself
293
- field :inaccessible_connection, RelayObject.connection_type, null: :false, resolver_method: :empty_array
294
- field :inaccessible_edge, RelayObject.edge_type, null: :false, resolver_method: :edge_object
295
-
296
- field :unauthorized_object, UnauthorizedObject, null: true, resolver_method: :itself
297
- field :unauthorized_connection, RelayObject.connection_type, null: false, resolver_method: :array_with_item
298
- field :unauthorized_edge, RelayObject.edge_type, null: false, resolver_method: :edge_object
299
-
300
- def edge_object
301
- OpenStruct.new(node: 100)
302
- end
303
-
304
- def array_with_item
305
- [1]
306
- end
307
-
308
- field :unauthorized_lazy_box, UnauthorizedBox, null: true do
309
- argument :value, String, required: true
310
- end
311
- def unauthorized_lazy_box(value:)
312
- # Make it extra nested, just for good measure.
313
- Box.new(value: Box.new(value: value))
314
- end
315
- field :unauthorized_list_items, [UnauthorizedObject], null: true
316
- def unauthorized_list_items
317
- [self, self]
318
- end
319
-
320
- field :unauthorized_lazy_check_box, UnauthorizedCheckBox, null: true, resolver_method: :unauthorized_lazy_box do
321
- argument :value, String, required: true
322
- end
323
-
324
- field :unauthorized_interface, UnauthorizedInterface, null: true, resolver_method: :unauthorized_lazy_box do
325
- argument :value, String, required: true
326
- end
327
-
328
- field :unauthorized_lazy_list_interface, [UnauthorizedInterface, null: true], null: true
329
-
330
- def unauthorized_lazy_list_interface
331
- ["z", Box.new(value: Box.new(value: "z2")), "a", Box.new(value: "a")]
332
- end
333
-
334
- field :integers, IntegerObjectConnection, null: false
335
-
336
- def integers
337
- [1,2,3]
338
- end
339
-
340
- field :lazy_integers, IntegerObjectConnection, null: false
341
-
342
- def lazy_integers
343
- Box.new(value: Box.new(value: [1,2,3]))
344
- end
345
-
346
- field :replaced_object, ReplacedObject, null: false
347
- def replaced_object
348
- Replaceable.new
349
- end
350
- end
351
-
352
- class DoHiddenStuff < GraphQL::Schema::RelayClassicMutation
353
- def self.visible?(ctx)
354
- super && (ctx[:hidden_mutation] ? false : true)
355
- end
356
- end
357
-
358
- class DoHiddenStuff2 < GraphQL::Schema::Mutation
359
- def self.visible?(ctx)
360
- super && !ctx[:hidden_mutation]
361
- end
362
- end
363
-
364
- class DoInaccessibleStuff < GraphQL::Schema::RelayClassicMutation
365
- def self.accessible?(ctx)
366
- super && (ctx[:inaccessible_mutation] ? false : true)
367
- end
368
- end
369
-
370
- class DoUnauthorizedStuff < GraphQL::Schema::RelayClassicMutation
371
- def self.authorized?(obj, ctx)
372
- super && (ctx[:unauthorized_mutation] ? false : true)
373
- end
374
- end
375
-
376
- class Mutation < BaseObject
377
- field :do_hidden_stuff, mutation: DoHiddenStuff
378
- field :do_hidden_stuff2, mutation: DoHiddenStuff2
379
- field :do_inaccessible_stuff, mutation: DoInaccessibleStuff
380
- field :do_unauthorized_stuff, mutation: DoUnauthorizedStuff
381
- end
382
-
383
- class Schema < GraphQL::Schema
384
- if TESTING_INTERPRETER
385
- use GraphQL::Execution::Interpreter
386
- end
387
- query(Query)
388
- mutation(Mutation)
389
-
390
- # Opt in to accessible? checks
391
- query_analyzer GraphQL::Authorization::Analyzer
392
-
393
- lazy_resolve(Box, :value)
394
-
395
- def self.unauthorized_object(err)
396
- if err.object.respond_to?(:replacement)
397
- err.object.replacement
398
- elsif err.object == :replace
399
- 33
400
- elsif err.object == :raise_from_object
401
- raise GraphQL::ExecutionError, err.message
402
- else
403
- raise GraphQL::ExecutionError, "Unauthorized #{err.type.graphql_name}: #{err.object.inspect}"
404
- end
405
- end
406
-
407
- # use GraphQL::Backtrace
408
- end
409
-
410
- class SchemaWithFieldHook < GraphQL::Schema
411
- if TESTING_INTERPRETER
412
- use GraphQL::Execution::Interpreter
413
- end
414
- query(Query)
415
-
416
- def self.unauthorized_field(err)
417
- if err.object == :replace
418
- 42
419
- elsif err.object == :raise
420
- raise GraphQL::ExecutionError, "#{err.message} in field #{err.field.name}"
421
- else
422
- raise GraphQL::ExecutionError, "Unauthorized field #{err.field.graphql_name} on #{err.type.graphql_name}: #{err.object}"
423
- end
424
- end
425
- end
426
- end
427
-
428
- def auth_execute(*args)
429
- AuthTest::Schema.execute(*args)
430
- end
431
-
432
- describe "applying the visible? method" do
433
- it "works in queries" do
434
- res = auth_execute(" { int int2 } ", context: { hide: true })
435
- assert_equal 1, res["errors"].size
436
- end
437
-
438
- it "applies return type visibility to fields" do
439
- error_queries = {
440
- "hiddenObject" => "{ hiddenObject { __typename } }",
441
- "hiddenInterface" => "{ hiddenInterface { __typename } }",
442
- "hiddenDefaultInterface" => "{ hiddenDefaultInterface { __typename } }",
443
- }
444
-
445
- error_queries.each do |name, q|
446
- hidden_res = auth_execute(q, context: { hide: true})
447
- assert_equal ["Field '#{name}' doesn't exist on type 'Query'"], hidden_res["errors"].map { |e| e["message"] }
448
-
449
- visible_res = auth_execute(q)
450
- # Both fields exist; the interface resolves to the object type, though
451
- assert_equal "HiddenObject", visible_res["data"][name]["__typename"]
452
- end
453
- end
454
-
455
- it "uses the mutation for derived fields, inputs and outputs" do
456
- query = "mutation { doHiddenStuff(input: {}) { __typename } }"
457
- res = auth_execute(query, context: { hidden_mutation: true })
458
- assert_equal ["Field 'doHiddenStuff' doesn't exist on type 'Mutation'"], res["errors"].map { |e| e["message"] }
459
-
460
- # `#resolve` isn't implemented, so this errors out:
461
- assert_raises NotImplementedError do
462
- auth_execute(query)
463
- end
464
-
465
- introspection_q = <<-GRAPHQL
466
- {
467
- t1: __type(name: "DoHiddenStuffInput") { name }
468
- t2: __type(name: "DoHiddenStuffPayload") { name }
469
- }
470
- GRAPHQL
471
- hidden_introspection_res = auth_execute(introspection_q, context: { hidden_mutation: true })
472
- assert_nil hidden_introspection_res["data"]["t1"]
473
- assert_nil hidden_introspection_res["data"]["t2"]
474
-
475
- visible_introspection_res = auth_execute(introspection_q)
476
- assert_equal "DoHiddenStuffInput", visible_introspection_res["data"]["t1"]["name"]
477
- assert_equal "DoHiddenStuffPayload", visible_introspection_res["data"]["t2"]["name"]
478
- end
479
-
480
- it "works with Schema::Mutation" do
481
- query = "mutation { doHiddenStuff2 { __typename } }"
482
- res = auth_execute(query, context: { hidden_mutation: true })
483
- assert_equal ["Field 'doHiddenStuff2' doesn't exist on type 'Mutation'"], res["errors"].map { |e| e["message"] }
484
-
485
- # `#resolve` isn't implemented, so this errors out:
486
- assert_raises NotImplementedError do
487
- auth_execute(query)
488
- end
489
- end
490
-
491
- it "uses the base type for edges and connections" do
492
- query = <<-GRAPHQL
493
- {
494
- hiddenConnection { __typename }
495
- hiddenEdge { __typename }
496
- }
497
- GRAPHQL
498
-
499
- hidden_res = auth_execute(query, context: { hidden_relay: true })
500
- assert_equal 2, hidden_res["errors"].size
501
-
502
- visible_res = auth_execute(query)
503
- assert_equal "RelayObjectConnection", visible_res["data"]["hiddenConnection"]["__typename"]
504
- assert_equal "RelayObjectEdge", visible_res["data"]["hiddenEdge"]["__typename"]
505
- end
506
-
507
- it "treats hidden enum values as non-existant, even in lists" do
508
- hidden_res_1 = auth_execute <<-GRAPHQL, context: { hide: true }
509
- {
510
- landscapeFeature(enum: TAR_PIT)
511
- }
512
- GRAPHQL
513
-
514
- assert_equal ["Argument 'enum' on Field 'landscapeFeature' has an invalid value. Expected type 'LandscapeFeature'."], hidden_res_1["errors"].map { |e| e["message"] }
515
-
516
- hidden_res_2 = auth_execute <<-GRAPHQL, context: { hide: true }
517
- {
518
- landscapeFeatures(enums: [STREAM, TAR_PIT])
519
- }
520
- GRAPHQL
521
-
522
- assert_equal ["Argument 'enums' on Field 'landscapeFeatures' has an invalid value. Expected type '[LandscapeFeature!]'."], hidden_res_2["errors"].map { |e| e["message"] }
523
-
524
- success_res = auth_execute <<-GRAPHQL, context: { hide: false }
525
- {
526
- landscapeFeature(enum: TAR_PIT)
527
- landscapeFeatures(enums: [STREAM, TAR_PIT])
528
- }
529
- GRAPHQL
530
-
531
- assert_equal "TAR_PIT", success_res["data"]["landscapeFeature"]
532
- assert_equal ["STREAM", "TAR_PIT"], success_res["data"]["landscapeFeatures"]
533
- end
534
-
535
- it "refuses to resolve to hidden enum values" do
536
- assert_raises(GraphQL::EnumType::UnresolvedValueError) do
537
- auth_execute <<-GRAPHQL, context: { hide: true }
538
- {
539
- landscapeFeature(string: "TAR_PIT")
540
- }
541
- GRAPHQL
542
- end
543
-
544
- assert_raises(GraphQL::EnumType::UnresolvedValueError) do
545
- auth_execute <<-GRAPHQL, context: { hide: true }
546
- {
547
- landscapeFeatures(strings: ["STREAM", "TAR_PIT"])
548
- }
549
- GRAPHQL
550
- end
551
- end
552
-
553
- it "works in introspection" do
554
- res = auth_execute <<-GRAPHQL, context: { hide: true, hidden_mutation: true }
555
- {
556
- query: __type(name: "Query") {
557
- fields {
558
- name
559
- args { name }
560
- }
561
- }
562
-
563
- hiddenObject: __type(name: "HiddenObject") { name }
564
- hiddenInterface: __type(name: "HiddenInterface") { name }
565
- landscapeFeatures: __type(name: "LandscapeFeature") { enumValues { name } }
566
- }
567
- GRAPHQL
568
- query_field_names = res["data"]["query"]["fields"].map { |f| f["name"] }
569
- refute_includes query_field_names, "int"
570
- int2_arg_names = res["data"]["query"]["fields"].find { |f| f["name"] == "int2" }["args"].map { |a| a["name"] }
571
- assert_equal ["int", "inaccessible", "unauthorized"], int2_arg_names
572
-
573
- assert_nil res["data"]["hiddenObject"]
574
- assert_nil res["data"]["hiddenInterface"]
575
-
576
- visible_landscape_features = res["data"]["landscapeFeatures"]["enumValues"].map { |v| v["name"] }
577
- assert_equal ["MOUNTAIN", "STREAM", "FIELD"], visible_landscape_features
578
- end
579
- end
580
-
581
- describe "applying the accessible? method" do
582
- it "works with fields and arguments" do
583
- queries = {
584
- "{ inaccessible }" => ["Some fields in this query are not accessible: inaccessible"],
585
- "{ int2(inaccessible: 1) }" => ["Some fields in this query are not accessible: int2"],
586
- }
587
-
588
- queries.each do |query_str, errors|
589
- res = auth_execute(query_str, context: { hide: true })
590
- assert_equal errors, res.fetch("errors").map { |e| e["message"] }
591
-
592
- res = auth_execute(query_str, context: { hide: false })
593
- refute res.key?("errors")
594
- end
595
- end
596
-
597
- it "works with return types" do
598
- queries = {
599
- "{ inaccessibleObject { __typename } }" => ["Some fields in this query are not accessible: inaccessibleObject"],
600
- "{ inaccessibleInterface { __typename } }" => ["Some fields in this query are not accessible: inaccessibleInterface"],
601
- "{ inaccessibleDefaultInterface { __typename } }" => ["Some fields in this query are not accessible: inaccessibleDefaultInterface"],
602
- }
603
-
604
- queries.each do |query_str, errors|
605
- res = auth_execute(query_str, context: { hide: true })
606
- assert_equal errors, res["errors"].map { |e| e["message"] }
607
-
608
- res = auth_execute(query_str, context: { hide: false })
609
- refute res.key?("errors")
610
- end
611
- end
612
-
613
- it "works with mutations" do
614
- query = "mutation { doInaccessibleStuff(input: {}) { __typename } }"
615
- res = auth_execute(query, context: { inaccessible_mutation: true })
616
- assert_equal ["Some fields in this query are not accessible: doInaccessibleStuff"], res["errors"].map { |e| e["message"] }
617
-
618
- assert_raises NotImplementedError do
619
- auth_execute(query)
620
- end
621
- end
622
-
623
- it "works with edges and connections" do
624
- query = <<-GRAPHQL
625
- {
626
- inaccessibleConnection { __typename }
627
- inaccessibleEdge { __typename }
628
- }
629
- GRAPHQL
630
-
631
- inaccessible_res = auth_execute(query, context: { inaccessible_relay: true })
632
- assert_equal ["Some fields in this query are not accessible: inaccessibleConnection, inaccessibleEdge"], inaccessible_res["errors"].map { |e| e["message"] }
633
-
634
- accessible_res = auth_execute(query)
635
- refute accessible_res.key?("errors")
636
- end
637
- end
638
-
639
- describe "applying the authorized? method" do
640
- it "halts on unauthorized objects, replacing the object with nil" do
641
- query = "{ unauthorizedObject { __typename } }"
642
- hidden_response = auth_execute(query, context: { hide: true })
643
- assert_nil hidden_response["data"].fetch("unauthorizedObject")
644
- visible_response = auth_execute(query, context: {})
645
- assert_equal({ "__typename" => "UnauthorizedObject" }, visible_response["data"]["unauthorizedObject"])
646
- end
647
-
648
- it "halts on unauthorized mutations" do
649
- query = "mutation { doUnauthorizedStuff(input: {}) { __typename } }"
650
- res = auth_execute(query, context: { unauthorized_mutation: true })
651
- assert_nil res["data"].fetch("doUnauthorizedStuff")
652
- assert_raises NotImplementedError do
653
- auth_execute(query)
654
- end
655
- end
656
-
657
- describe "field level authorization" do
658
- describe "unauthorized field" do
659
- describe "with an unauthorized field hook configured" do
660
- describe "when the hook returns a value" do
661
- it "replaces the response with the return value of the unauthorized field hook" do
662
- query = "{ unauthorized }"
663
- response = AuthTest::SchemaWithFieldHook.execute(query, root_value: :replace)
664
- assert_equal 42, response["data"].fetch("unauthorized")
665
- end
666
- end
667
-
668
- describe "when the field hook raises an error" do
669
- it "returns nil" do
670
- query = "{ unauthorized }"
671
- response = AuthTest::SchemaWithFieldHook.execute(query, root_value: :hide)
672
- assert_nil response["data"].fetch("unauthorized")
673
- end
674
-
675
- it "adds the error to the errors key" do
676
- query = "{ unauthorized }"
677
- response = AuthTest::SchemaWithFieldHook.execute(query, root_value: :hide)
678
- assert_equal ["Unauthorized field unauthorized on Query: hide"], response["errors"].map { |e| e["message"] }
679
- end
680
- end
681
-
682
- describe "when the field authorization raises an UnauthorizedFieldError" do
683
- it "receives the raised error" do
684
- query = "{ unauthorized }"
685
- response = AuthTest::SchemaWithFieldHook.execute(query, root_value: :raise)
686
- assert_equal ["raised authorized field error in field unauthorized"], response["errors"].map { |e| e["message"] }
687
- end
688
- end
689
- end
690
-
691
- describe "with an unauthorized field hook not configured" do
692
- describe "When the object hook replaces the field" do
693
- it "delegates to the unauthorized object hook, which replaces the object" do
694
- query = "{ unauthorized }"
695
- response = AuthTest::Schema.execute(query, root_value: :replace)
696
- assert_equal 33, response["data"].fetch("unauthorized")
697
- end
698
- end
699
- describe "When the object hook raises an error" do
700
- it "returns nil" do
701
- query = "{ unauthorized }"
702
- response = AuthTest::Schema.execute(query, root_value: :hide)
703
- assert_nil response["data"].fetch("unauthorized")
704
- end
705
-
706
- it "adds the error to the errors key" do
707
- query = "{ unauthorized }"
708
- response = AuthTest::Schema.execute(query, root_value: :hide)
709
- assert_equal ["Unauthorized Query: :hide"], response["errors"].map { |e| e["message"] }
710
- end
711
- end
712
- end
713
- end
714
-
715
- describe "authorized field" do
716
- it "returns the field data" do
717
- query = "{ unauthorized }"
718
- response = AuthTest::SchemaWithFieldHook.execute(query, root_value: 1)
719
- assert_equal 1, response["data"].fetch("unauthorized")
720
- end
721
- end
722
- end
723
-
724
- it "halts on unauthorized fields, using the parent object" do
725
- query = "{ unauthorized }"
726
- hidden_response = auth_execute(query, root_value: :hide)
727
- assert_nil hidden_response["data"].fetch("unauthorized")
728
- visible_response = auth_execute(query, root_value: 1)
729
- assert_equal 1, visible_response["data"]["unauthorized"]
730
- end
731
-
732
- it "halts on unauthorized arguments, using the parent object" do
733
- query = "{ int2(unauthorized: 5) }"
734
- hidden_response = auth_execute(query, root_value: :hide2)
735
- assert_nil hidden_response["data"].fetch("int2")
736
- visible_response = auth_execute(query)
737
- assert_equal 5, visible_response["data"]["int2"]
738
- end
739
-
740
- it "works with edges and connections" do
741
- query = <<-GRAPHQL
742
- {
743
- unauthorizedConnection {
744
- __typename
745
- edges {
746
- __typename
747
- node {
748
- __typename
749
- }
750
- }
751
- nodes {
752
- __typename
753
- }
754
- }
755
- unauthorizedEdge {
756
- __typename
757
- node {
758
- __typename
759
- }
760
- }
761
- }
762
- GRAPHQL
763
-
764
- unauthorized_res = auth_execute(query, context: { unauthorized_relay: true })
765
- conn = unauthorized_res["data"].fetch("unauthorizedConnection")
766
- assert_equal "RelayObjectConnection", conn.fetch("__typename")
767
- # This is tricky: the previous behavior was to replace the _whole_
768
- # list with `nil`. This was due to an implementation detail:
769
- # The list field's return value (an array of integers) was wrapped
770
- # _before_ returning, and during this wrapping, a cascading error
771
- # caused the entire field to be nilled out.
772
- #
773
- # In the interpreter, each list item is contained and the error doesn't propagate
774
- # up to the whole list.
775
- #
776
- # Originally, I thought that this was a _feature_ that obscured list entries.
777
- # But really, look at the test below: you don't get this "feature" if
778
- # you use `edges { node }`, so it can't be relied on in any way.
779
- #
780
- # All that to say, in the interpreter, `nodes` and `edges { node }` behave
781
- # the same.
782
- #
783
- # TODO revisit the docs for this.
784
- failed_nodes_value = TESTING_INTERPRETER ? [nil] : nil
785
- assert_equal failed_nodes_value, conn.fetch("nodes")
786
- assert_equal [{"node" => nil, "__typename" => "RelayObjectEdge"}], conn.fetch("edges")
787
-
788
- edge = unauthorized_res["data"].fetch("unauthorizedEdge")
789
- assert_nil edge.fetch("node")
790
- assert_equal "RelayObjectEdge", edge["__typename"]
791
-
792
- unauthorized_object_paths = [
793
- ["unauthorizedConnection", "edges", 0, "node"],
794
- TESTING_INTERPRETER ? ["unauthorizedConnection", "nodes", 0] : ["unauthorizedConnection", "nodes"],
795
- ["unauthorizedEdge", "node"]
796
- ]
797
-
798
- assert_equal unauthorized_object_paths, unauthorized_res["errors"].map { |e| e["path"] }
799
-
800
- authorized_res = auth_execute(query)
801
- conn = authorized_res["data"].fetch("unauthorizedConnection")
802
- assert_equal "RelayObjectConnection", conn.fetch("__typename")
803
- assert_equal [{"__typename"=>"RelayObject"}], conn.fetch("nodes")
804
- assert_equal [{"node" => {"__typename" => "RelayObject"}, "__typename" => "RelayObjectEdge"}], conn.fetch("edges")
805
-
806
- edge = authorized_res["data"].fetch("unauthorizedEdge")
807
- assert_equal "RelayObject", edge.fetch("node").fetch("__typename")
808
- assert_equal "RelayObjectEdge", edge["__typename"]
809
- end
810
-
811
- it "authorizes _after_ resolving lazy objects" do
812
- query = <<-GRAPHQL
813
- {
814
- a: unauthorizedLazyBox(value: "a") { value }
815
- b: unauthorizedLazyBox(value: "b") { value }
816
- }
817
- GRAPHQL
818
-
819
- unauthorized_res = auth_execute(query)
820
- assert_nil unauthorized_res["data"].fetch("a")
821
- assert_equal "b", unauthorized_res["data"]["b"]["value"]
822
- end
823
-
824
- it "authorizes items in a list" do
825
- query = <<-GRAPHQL
826
- {
827
- unauthorizedListItems { __typename }
828
- }
829
- GRAPHQL
830
-
831
- unauthorized_res = auth_execute(query, context: { hide: true })
832
-
833
- assert_nil unauthorized_res["data"]["unauthorizedListItems"]
834
- authorized_res = auth_execute(query, context: { hide: false })
835
- assert_equal 2, authorized_res["data"]["unauthorizedListItems"].size
836
- end
837
-
838
- it "syncs lazy objects from authorized? checks" do
839
- query = <<-GRAPHQL
840
- {
841
- a: unauthorizedLazyCheckBox(value: "a") { value }
842
- b: unauthorizedLazyCheckBox(value: "b") { value }
843
- }
844
- GRAPHQL
845
-
846
- unauthorized_res = auth_execute(query)
847
- assert_nil unauthorized_res["data"].fetch("a")
848
- assert_equal "b", unauthorized_res["data"]["b"]["value"]
849
- # Also, the custom handler was called:
850
- assert_equal ["Unauthorized UnauthorizedCheckBox: \"a\""], unauthorized_res["errors"].map { |e| e["message"] }
851
- end
852
-
853
- it "Works for lazy connections" do
854
- query = <<-GRAPHQL
855
- {
856
- lazyIntegers { edges { node { value } } }
857
- }
858
- GRAPHQL
859
- res = auth_execute(query)
860
- assert_equal [1,2,3], res["data"]["lazyIntegers"]["edges"].map { |e| e["node"]["value"] }
861
- end
862
-
863
- it "Works for eager connections" do
864
- query = <<-GRAPHQL
865
- {
866
- integers { edges { node { value } } }
867
- }
868
- GRAPHQL
869
- res = auth_execute(query)
870
- assert_equal [1,2,3], res["data"]["integers"]["edges"].map { |e| e["node"]["value"] }
871
- end
872
-
873
- it "filters out individual nodes by value" do
874
- query = <<-GRAPHQL
875
- {
876
- integers { edges { node { value } } }
877
- }
878
- GRAPHQL
879
- res = auth_execute(query, context: { exclude_integer: 1 })
880
- assert_equal [nil,2,3], res["data"]["integers"]["edges"].map { |e| e["node"] && e["node"]["value"] }
881
- assert_equal ["Unauthorized IntegerObject: 1"], res["errors"].map { |e| e["message"] }
882
- end
883
-
884
- it "works with lazy values / interfaces" do
885
- query = <<-GRAPHQL
886
- query($value: String!){
887
- unauthorizedInterface(value: $value) {
888
- ... on UnauthorizedCheckBox {
889
- value
890
- }
891
- }
892
- }
893
- GRAPHQL
894
-
895
- res = auth_execute(query, variables: { value: "a"})
896
- assert_nil res["data"]["unauthorizedInterface"]
897
-
898
- res2 = auth_execute(query, variables: { value: "b"})
899
- assert_equal "b", res2["data"]["unauthorizedInterface"]["value"]
900
- end
901
-
902
- it "works with lazy values / lists of interfaces" do
903
- query = <<-GRAPHQL
904
- {
905
- unauthorizedLazyListInterface {
906
- ... on UnauthorizedCheckBox {
907
- value
908
- }
909
- }
910
- }
911
- GRAPHQL
912
-
913
- res = auth_execute(query)
914
- # An error from two, values from the others
915
- assert_equal ["Unauthorized UnauthorizedCheckBox: \"a\"", "Unauthorized UnauthorizedCheckBox: \"a\""], res["errors"].map { |e| e["message"] }
916
- assert_equal [{"value" => "z"}, {"value" => "z2"}, nil, nil], res["data"]["unauthorizedLazyListInterface"]
917
- end
918
-
919
- describe "with an unauthorized field hook configured" do
920
- it "replaces objects from the unauthorized_object hook" do
921
- query = "{ replacedObject { replaced } }"
922
- res = auth_execute(query, context: { replace_me: true })
923
- assert_equal true, res["data"]["replacedObject"]["replaced"]
924
-
925
- res = auth_execute(query, context: { replace_me: false })
926
- assert_equal false, res["data"]["replacedObject"]["replaced"]
927
- end
928
-
929
- it "works when the query hook returns false and there's no root object" do
930
- query = "{ __typename }"
931
- res = auth_execute(query)
932
- assert_equal "Query", res["data"]["__typename"]
933
-
934
- unauth_res = auth_execute(query, context: { query_unauthorized: true })
935
- assert_nil unauth_res["data"]
936
- assert_equal [{"message"=>"Unauthorized Query: nil"}], unauth_res["errors"]
937
- end
938
-
939
- describe "when the object authorization raises an UnauthorizedFieldError" do
940
- it "receives the raised error" do
941
- query = "{ unauthorizedObject { value } }"
942
- response = auth_execute(query, context: { raise: true }, root_value: :raise_from_object)
943
- assert_equal ["raised authorized object error"], response["errors"].map { |e| e["message"] }
944
- end
945
- end
946
- end
947
- end
948
-
949
- describe "returning false" do
950
- class FalseSchema < GraphQL::Schema
951
- class Query < GraphQL::Schema::Object
952
- def self.authorized?(obj, ctx)
953
- false
954
- end
955
-
956
- field :int, Integer, null: false
957
-
958
- def int
959
- 1
960
- end
961
- end
962
- query(Query)
963
- if TESTING_INTERPRETER
964
- use GraphQL::Execution::Interpreter
965
- end
966
- end
967
-
968
- it "works out-of-the-box" do
969
- res = FalseSchema.execute("{ int }")
970
- assert_nil res.fetch("data")
971
- refute res.key?("errors")
972
- end
973
- end
974
- end