graphql 1.9.11 → 1.9.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (286) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/analysis/ast/query_complexity.rb +0 -8
  3. data/lib/graphql/analysis/ast/query_depth.rb +0 -8
  4. data/lib/graphql/analysis/ast/visitor.rb +26 -24
  5. data/lib/graphql/execution.rb +1 -0
  6. data/lib/graphql/execution/errors.rb +60 -0
  7. data/lib/graphql/execution/interpreter/runtime.rb +21 -17
  8. data/lib/graphql/static_validation/rules/fields_will_merge.rb +15 -8
  9. data/lib/graphql/version.rb +1 -1
  10. metadata +5 -556
  11. data/spec/dummy/Gemfile +0 -12
  12. data/spec/dummy/README.md +0 -24
  13. data/spec/dummy/Rakefile +0 -7
  14. data/spec/dummy/app/assets/config/manifest.js +0 -1
  15. data/spec/dummy/app/assets/javascripts/application.js +0 -66
  16. data/spec/dummy/app/channels/application_cable/channel.rb +0 -5
  17. data/spec/dummy/app/channels/application_cable/connection.rb +0 -5
  18. data/spec/dummy/app/channels/graphql_channel.rb +0 -116
  19. data/spec/dummy/app/controllers/application_controller.rb +0 -4
  20. data/spec/dummy/app/controllers/pages_controller.rb +0 -5
  21. data/spec/dummy/app/helpers/application_helper.rb +0 -3
  22. data/spec/dummy/app/jobs/application_job.rb +0 -3
  23. data/spec/dummy/app/views/layouts/application.html.erb +0 -12
  24. data/spec/dummy/app/views/pages/show.html +0 -16
  25. data/spec/dummy/bin/bundle +0 -4
  26. data/spec/dummy/bin/rails +0 -5
  27. data/spec/dummy/bin/rake +0 -5
  28. data/spec/dummy/bin/setup +0 -31
  29. data/spec/dummy/bin/update +0 -27
  30. data/spec/dummy/bin/yarn +0 -12
  31. data/spec/dummy/config.ru +0 -6
  32. data/spec/dummy/config/application.rb +0 -30
  33. data/spec/dummy/config/boot.rb +0 -4
  34. data/spec/dummy/config/cable.yml +0 -10
  35. data/spec/dummy/config/environment.rb +0 -6
  36. data/spec/dummy/config/environments/development.rb +0 -40
  37. data/spec/dummy/config/environments/production.rb +0 -76
  38. data/spec/dummy/config/environments/test.rb +0 -37
  39. data/spec/dummy/config/initializers/application_controller_renderer.rb +0 -9
  40. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -8
  41. data/spec/dummy/config/initializers/cookies_serializer.rb +0 -6
  42. data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -5
  43. data/spec/dummy/config/initializers/inflections.rb +0 -17
  44. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  45. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -10
  46. data/spec/dummy/config/locales/en.yml +0 -33
  47. data/spec/dummy/config/puma.rb +0 -57
  48. data/spec/dummy/config/routes.rb +0 -4
  49. data/spec/dummy/config/secrets.yml +0 -32
  50. data/spec/dummy/package.json +0 -5
  51. data/spec/dummy/public/404.html +0 -67
  52. data/spec/dummy/public/422.html +0 -67
  53. data/spec/dummy/public/500.html +0 -66
  54. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  55. data/spec/dummy/public/apple-touch-icon.png +0 -0
  56. data/spec/dummy/public/favicon.ico +0 -0
  57. data/spec/dummy/public/robots.txt +0 -1
  58. data/spec/dummy/test/application_system_test_case.rb +0 -6
  59. data/spec/dummy/test/system/action_cable_subscription_test.rb +0 -45
  60. data/spec/dummy/test/test_helper.rb +0 -4
  61. data/spec/fixtures/upgrader/account.original.rb +0 -19
  62. data/spec/fixtures/upgrader/account.transformed.rb +0 -20
  63. data/spec/fixtures/upgrader/blame_range.original.rb +0 -43
  64. data/spec/fixtures/upgrader/blame_range.transformed.rb +0 -30
  65. data/spec/fixtures/upgrader/date_time.original.rb +0 -24
  66. data/spec/fixtures/upgrader/date_time.transformed.rb +0 -23
  67. data/spec/fixtures/upgrader/delete_project.original.rb +0 -28
  68. data/spec/fixtures/upgrader/delete_project.transformed.rb +0 -27
  69. data/spec/fixtures/upgrader/gist_order_field.original.rb +0 -14
  70. data/spec/fixtures/upgrader/gist_order_field.transformed.rb +0 -13
  71. data/spec/fixtures/upgrader/increment_count.original.rb +0 -59
  72. data/spec/fixtures/upgrader/increment_count.transformed.rb +0 -50
  73. data/spec/fixtures/upgrader/mutation.original.rb +0 -28
  74. data/spec/fixtures/upgrader/mutation.transformed.rb +0 -28
  75. data/spec/fixtures/upgrader/photo.original.rb +0 -10
  76. data/spec/fixtures/upgrader/photo.transformed.rb +0 -12
  77. data/spec/fixtures/upgrader/release_order.original.rb +0 -15
  78. data/spec/fixtures/upgrader/release_order.transformed.rb +0 -14
  79. data/spec/fixtures/upgrader/starrable.original.rb +0 -49
  80. data/spec/fixtures/upgrader/starrable.transformed.rb +0 -46
  81. data/spec/fixtures/upgrader/subscribable.original.rb +0 -55
  82. data/spec/fixtures/upgrader/subscribable.transformed.rb +0 -51
  83. data/spec/fixtures/upgrader/type_x.original.rb +0 -65
  84. data/spec/fixtures/upgrader/type_x.transformed.rb +0 -56
  85. data/spec/graphql/analysis/analyze_query_spec.rb +0 -261
  86. data/spec/graphql/analysis/ast/field_usage_spec.rb +0 -51
  87. data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +0 -120
  88. data/spec/graphql/analysis/ast/max_query_depth_spec.rb +0 -134
  89. data/spec/graphql/analysis/ast/query_complexity_spec.rb +0 -299
  90. data/spec/graphql/analysis/ast/query_depth_spec.rb +0 -108
  91. data/spec/graphql/analysis/ast_spec.rb +0 -296
  92. data/spec/graphql/analysis/field_usage_spec.rb +0 -62
  93. data/spec/graphql/analysis/max_query_complexity_spec.rb +0 -102
  94. data/spec/graphql/analysis/max_query_depth_spec.rb +0 -103
  95. data/spec/graphql/analysis/query_complexity_spec.rb +0 -301
  96. data/spec/graphql/analysis/query_depth_spec.rb +0 -81
  97. data/spec/graphql/argument_spec.rb +0 -159
  98. data/spec/graphql/authorization_spec.rb +0 -974
  99. data/spec/graphql/backtrace_spec.rb +0 -206
  100. data/spec/graphql/base_type_spec.rb +0 -171
  101. data/spec/graphql/boolean_type_spec.rb +0 -21
  102. data/spec/graphql/compatibility/execution_specification_spec.rb +0 -4
  103. data/spec/graphql/compatibility/lazy_execution_specification_spec.rb +0 -4
  104. data/spec/graphql/compatibility/query_parser_specification_spec.rb +0 -6
  105. data/spec/graphql/compatibility/schema_parser_specification_spec.rb +0 -6
  106. data/spec/graphql/define/assign_argument_spec.rb +0 -61
  107. data/spec/graphql/define/instance_definable_spec.rb +0 -203
  108. data/spec/graphql/directive/skip_directive_spec.rb +0 -9
  109. data/spec/graphql/directive_spec.rb +0 -295
  110. data/spec/graphql/enum_type_spec.rb +0 -158
  111. data/spec/graphql/execution/execute_spec.rb +0 -303
  112. data/spec/graphql/execution/instrumentation_spec.rb +0 -212
  113. data/spec/graphql/execution/interpreter_spec.rb +0 -485
  114. data/spec/graphql/execution/lazy/lazy_method_map_spec.rb +0 -57
  115. data/spec/graphql/execution/lazy_spec.rb +0 -247
  116. data/spec/graphql/execution/lookahead_spec.rb +0 -390
  117. data/spec/graphql/execution/multiplex_spec.rb +0 -222
  118. data/spec/graphql/execution/typecast_spec.rb +0 -47
  119. data/spec/graphql/execution_error_spec.rb +0 -329
  120. data/spec/graphql/field_spec.rb +0 -246
  121. data/spec/graphql/float_type_spec.rb +0 -16
  122. data/spec/graphql/function_spec.rb +0 -152
  123. data/spec/graphql/id_type_spec.rb +0 -33
  124. data/spec/graphql/input_object_type_spec.rb +0 -25
  125. data/spec/graphql/int_type_spec.rb +0 -35
  126. data/spec/graphql/interface_type_spec.rb +0 -196
  127. data/spec/graphql/internal_representation/print_spec.rb +0 -41
  128. data/spec/graphql/internal_representation/rewrite_spec.rb +0 -381
  129. data/spec/graphql/introspection/directive_type_spec.rb +0 -66
  130. data/spec/graphql/introspection/input_value_type_spec.rb +0 -144
  131. data/spec/graphql/introspection/introspection_query_spec.rb +0 -64
  132. data/spec/graphql/introspection/schema_type_spec.rb +0 -57
  133. data/spec/graphql/introspection/type_type_spec.rb +0 -155
  134. data/spec/graphql/language/block_string_spec.rb +0 -70
  135. data/spec/graphql/language/definition_slice_spec.rb +0 -226
  136. data/spec/graphql/language/document_from_schema_definition_spec.rb +0 -770
  137. data/spec/graphql/language/equality_spec.rb +0 -84
  138. data/spec/graphql/language/generation_spec.rb +0 -38
  139. data/spec/graphql/language/lexer_spec.rb +0 -153
  140. data/spec/graphql/language/nodes_spec.rb +0 -67
  141. data/spec/graphql/language/parser_spec.rb +0 -183
  142. data/spec/graphql/language/printer_spec.rb +0 -215
  143. data/spec/graphql/language/visitor_spec.rb +0 -419
  144. data/spec/graphql/list_type_spec.rb +0 -57
  145. data/spec/graphql/non_null_type_spec.rb +0 -48
  146. data/spec/graphql/object_type_spec.rb +0 -197
  147. data/spec/graphql/query/arguments_spec.rb +0 -346
  148. data/spec/graphql/query/context_spec.rb +0 -292
  149. data/spec/graphql/query/executor_spec.rb +0 -341
  150. data/spec/graphql/query/literal_input_spec.rb +0 -91
  151. data/spec/graphql/query/result_spec.rb +0 -29
  152. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +0 -109
  153. data/spec/graphql/query_spec.rb +0 -803
  154. data/spec/graphql/rake_task_spec.rb +0 -59
  155. data/spec/graphql/scalar_type_spec.rb +0 -66
  156. data/spec/graphql/schema/argument_spec.rb +0 -186
  157. data/spec/graphql/schema/build_from_definition_spec.rb +0 -1197
  158. data/spec/graphql/schema/catchall_middleware_spec.rb +0 -32
  159. data/spec/graphql/schema/directive/feature_spec.rb +0 -81
  160. data/spec/graphql/schema/directive/transform_spec.rb +0 -39
  161. data/spec/graphql/schema/enum_spec.rb +0 -83
  162. data/spec/graphql/schema/enum_value_spec.rb +0 -24
  163. data/spec/graphql/schema/field_extension_spec.rb +0 -159
  164. data/spec/graphql/schema/field_spec.rb +0 -319
  165. data/spec/graphql/schema/finder_spec.rb +0 -135
  166. data/spec/graphql/schema/input_object_spec.rb +0 -421
  167. data/spec/graphql/schema/instrumentation_spec.rb +0 -43
  168. data/spec/graphql/schema/interface_spec.rb +0 -215
  169. data/spec/graphql/schema/introspection_system_spec.rb +0 -80
  170. data/spec/graphql/schema/list_spec.rb +0 -73
  171. data/spec/graphql/schema/loader_spec.rb +0 -350
  172. data/spec/graphql/schema/member/accepts_definition_spec.rb +0 -115
  173. data/spec/graphql/schema/member/build_type_spec.rb +0 -63
  174. data/spec/graphql/schema/member/scoped_spec.rb +0 -217
  175. data/spec/graphql/schema/member/type_system_helpers_spec.rb +0 -63
  176. data/spec/graphql/schema/middleware_chain_spec.rb +0 -57
  177. data/spec/graphql/schema/mutation_spec.rb +0 -150
  178. data/spec/graphql/schema/non_null_spec.rb +0 -46
  179. data/spec/graphql/schema/object_spec.rb +0 -355
  180. data/spec/graphql/schema/printer_spec.rb +0 -883
  181. data/spec/graphql/schema/relay_classic_mutation_spec.rb +0 -252
  182. data/spec/graphql/schema/rescue_middleware_spec.rb +0 -88
  183. data/spec/graphql/schema/resolver_spec.rb +0 -743
  184. data/spec/graphql/schema/scalar_spec.rb +0 -101
  185. data/spec/graphql/schema/subscription_spec.rb +0 -505
  186. data/spec/graphql/schema/timeout_middleware_spec.rb +0 -188
  187. data/spec/graphql/schema/timeout_spec.rb +0 -206
  188. data/spec/graphql/schema/traversal_spec.rb +0 -222
  189. data/spec/graphql/schema/type_expression_spec.rb +0 -39
  190. data/spec/graphql/schema/union_spec.rb +0 -72
  191. data/spec/graphql/schema/unique_within_type_spec.rb +0 -44
  192. data/spec/graphql/schema/validation_spec.rb +0 -355
  193. data/spec/graphql/schema/warden_spec.rb +0 -926
  194. data/spec/graphql/schema_spec.rb +0 -169
  195. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +0 -466
  196. data/spec/graphql/static_validation/rules/argument_names_are_unique_spec.rb +0 -44
  197. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +0 -112
  198. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +0 -35
  199. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +0 -42
  200. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +0 -167
  201. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +0 -66
  202. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +0 -740
  203. data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +0 -28
  204. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +0 -52
  205. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +0 -42
  206. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +0 -123
  207. data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +0 -24
  208. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +0 -56
  209. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +0 -61
  210. data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +0 -39
  211. data/spec/graphql/static_validation/rules/no_definitions_are_present_spec.rb +0 -62
  212. data/spec/graphql/static_validation/rules/operation_names_are_valid_spec.rb +0 -82
  213. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +0 -98
  214. data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb +0 -86
  215. data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +0 -34
  216. data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +0 -188
  217. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +0 -196
  218. data/spec/graphql/static_validation/rules/variable_names_are_unique_spec.rb +0 -23
  219. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +0 -236
  220. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +0 -78
  221. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +0 -81
  222. data/spec/graphql/static_validation/type_stack_spec.rb +0 -29
  223. data/spec/graphql/static_validation/validator_spec.rb +0 -204
  224. data/spec/graphql/string_type_spec.rb +0 -80
  225. data/spec/graphql/subscriptions/serialize_spec.rb +0 -49
  226. data/spec/graphql/subscriptions_spec.rb +0 -540
  227. data/spec/graphql/tracing/new_relic_tracing_spec.rb +0 -84
  228. data/spec/graphql/tracing/platform_tracing_spec.rb +0 -141
  229. data/spec/graphql/tracing/prometheus_tracing_spec.rb +0 -42
  230. data/spec/graphql/tracing/scout_tracing_spec.rb +0 -17
  231. data/spec/graphql/tracing/skylight_tracing_spec.rb +0 -63
  232. data/spec/graphql/tracing_spec.rb +0 -52
  233. data/spec/graphql/types/big_int_spec.rb +0 -24
  234. data/spec/graphql/types/iso_8601_date_time_spec.rb +0 -137
  235. data/spec/graphql/types/relay/base_edge_spec.rb +0 -33
  236. data/spec/graphql/union_type_spec.rb +0 -211
  237. data/spec/graphql/upgrader/member_spec.rb +0 -583
  238. data/spec/graphql/upgrader/schema_spec.rb +0 -82
  239. data/spec/integration/mongoid/graphql/relay/mongo_relation_connection_spec.rb +0 -528
  240. data/spec/integration/mongoid/spec_helper.rb +0 -2
  241. data/spec/integration/mongoid/star_trek/data.rb +0 -126
  242. data/spec/integration/mongoid/star_trek/schema.rb +0 -424
  243. data/spec/integration/rails/data.rb +0 -110
  244. data/spec/integration/rails/generators/base_generator_test.rb +0 -7
  245. data/spec/integration/rails/generators/graphql/enum_generator_spec.rb +0 -30
  246. data/spec/integration/rails/generators/graphql/install_generator_spec.rb +0 -238
  247. data/spec/integration/rails/generators/graphql/interface_generator_spec.rb +0 -34
  248. data/spec/integration/rails/generators/graphql/loader_generator_spec.rb +0 -59
  249. data/spec/integration/rails/generators/graphql/mutation_generator_spec.rb +0 -71
  250. data/spec/integration/rails/generators/graphql/object_generator_spec.rb +0 -54
  251. data/spec/integration/rails/generators/graphql/scalar_generator_spec.rb +0 -28
  252. data/spec/integration/rails/generators/graphql/union_generator_spec.rb +0 -67
  253. data/spec/integration/rails/graphql/input_object_spec.rb +0 -19
  254. data/spec/integration/rails/graphql/input_object_type_spec.rb +0 -364
  255. data/spec/integration/rails/graphql/query/variables_spec.rb +0 -375
  256. data/spec/integration/rails/graphql/relay/array_connection_spec.rb +0 -309
  257. data/spec/integration/rails/graphql/relay/base_connection_spec.rb +0 -101
  258. data/spec/integration/rails/graphql/relay/connection_instrumentation_spec.rb +0 -80
  259. data/spec/integration/rails/graphql/relay/connection_resolve_spec.rb +0 -79
  260. data/spec/integration/rails/graphql/relay/connection_type_spec.rb +0 -106
  261. data/spec/integration/rails/graphql/relay/edge_spec.rb +0 -10
  262. data/spec/integration/rails/graphql/relay/mutation_spec.rb +0 -387
  263. data/spec/integration/rails/graphql/relay/node_spec.rb +0 -263
  264. data/spec/integration/rails/graphql/relay/page_info_spec.rb +0 -111
  265. data/spec/integration/rails/graphql/relay/range_add_spec.rb +0 -117
  266. data/spec/integration/rails/graphql/relay/relation_connection_spec.rb +0 -837
  267. data/spec/integration/rails/graphql/schema_spec.rb +0 -507
  268. data/spec/integration/rails/graphql/tracing/active_support_notifications_tracing_spec.rb +0 -62
  269. data/spec/integration/rails/spec_helper.rb +0 -25
  270. data/spec/spec_helper.rb +0 -116
  271. data/spec/support/dummy/data.rb +0 -45
  272. data/spec/support/dummy/schema.rb +0 -519
  273. data/spec/support/error_bubbling_helpers.rb +0 -23
  274. data/spec/support/global_id.rb +0 -23
  275. data/spec/support/jazz.rb +0 -778
  276. data/spec/support/lazy_helpers.rb +0 -192
  277. data/spec/support/magic_cards/schema.graphql +0 -33
  278. data/spec/support/minimum_input_object.rb +0 -21
  279. data/spec/support/new_relic.rb +0 -27
  280. data/spec/support/parser/filename_example.graphql +0 -5
  281. data/spec/support/parser/filename_example_error_1.graphql +0 -4
  282. data/spec/support/parser/filename_example_error_2.graphql +0 -5
  283. data/spec/support/parser/filename_example_invalid_utf8.graphql +0 -1
  284. data/spec/support/skylight.rb +0 -39
  285. data/spec/support/star_wars/schema.rb +0 -464
  286. data/spec/support/static_validation_helpers.rb +0 -32
@@ -1,252 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
-
4
- describe GraphQL::Schema::RelayClassicMutation do
5
- describe ".input_object_class" do
6
- it "is inherited, with a default" do
7
- custom_input = Class.new(GraphQL::Schema::InputObject)
8
- mutation_base_class = Class.new(GraphQL::Schema::RelayClassicMutation) do
9
- input_object_class(custom_input)
10
- end
11
- mutation_subclass = Class.new(mutation_base_class)
12
-
13
- assert_equal GraphQL::Schema::InputObject, GraphQL::Schema::RelayClassicMutation.input_object_class
14
- assert_equal custom_input, mutation_base_class.input_object_class
15
- assert_equal custom_input, mutation_subclass.input_object_class
16
- end
17
- end
18
-
19
- describe ".input_type" do
20
- it "has a reference to the mutation" do
21
- mutation = Class.new(GraphQL::Schema::RelayClassicMutation) do
22
- graphql_name "Test"
23
- end
24
- assert_equal mutation, mutation.input_type.mutation
25
- assert_equal mutation, mutation.input_type.graphql_definition.mutation
26
- end
27
- end
28
-
29
- describe ".null" do
30
- it "is inherited as true" do
31
- mutation = Class.new(GraphQL::Schema::RelayClassicMutation) do
32
- graphql_name "Test"
33
- end
34
-
35
- assert mutation.null
36
- end
37
- end
38
-
39
- describe "execution" do
40
- after do
41
- Jazz::Models.reset
42
- end
43
-
44
- it "works with no arguments" do
45
- res = Jazz::Schema.execute <<-GRAPHQL
46
- mutation {
47
- addSitar(input: {}) {
48
- instrument {
49
- name
50
- }
51
- }
52
- }
53
- GRAPHQL
54
-
55
- assert_equal "Sitar", res["data"]["addSitar"]["instrument"]["name"]
56
- end
57
-
58
- it "works with InputObject arguments" do
59
- res = Jazz::Schema.execute <<-GRAPHQL
60
- mutation {
61
- addEnsembleRelay(input: { ensemble: { name: "Miles Davis Quartet" } }) {
62
- ensemble {
63
- name
64
- }
65
- }
66
- }
67
- GRAPHQL
68
-
69
- assert_equal "Miles Davis Quartet", res["data"]["addEnsembleRelay"]["ensemble"]["name"]
70
- end
71
-
72
- it "supports extras" do
73
- res = Jazz::Schema.execute <<-GRAPHQL
74
- mutation {
75
- hasExtras(input: {}) {
76
- nodeClass
77
- int
78
- }
79
- }
80
- GRAPHQL
81
-
82
- assert_equal "GraphQL::Language::Nodes::Field", res["data"]["hasExtras"]["nodeClass"]
83
- assert_nil res["data"]["hasExtras"]["int"]
84
-
85
- # Also test with given args
86
- res = Jazz::Schema.execute <<-GRAPHQL
87
- mutation {
88
- hasExtras(input: {int: 5}) {
89
- nodeClass
90
- int
91
- }
92
- }
93
- GRAPHQL
94
- assert_equal "GraphQL::Language::Nodes::Field", res["data"]["hasExtras"]["nodeClass"]
95
- assert_equal 5, res["data"]["hasExtras"]["int"]
96
- end
97
- end
98
-
99
- describe "loading multiple application objects" do
100
- let(:query_str) {
101
- <<-GRAPHQL
102
- mutation($ids: [ID!]!) {
103
- upvoteEnsembles(input: {ensembleIds: $ids}) {
104
- ensembles {
105
- id
106
- }
107
- }
108
- }
109
- GRAPHQL
110
- }
111
-
112
- it "loads arguments as objects of the given type and strips `_ids` suffix off argument name and appends `s`" do
113
- res = Jazz::Schema.execute(query_str, variables: { ids: ["Ensemble/Robert Glasper Experiment", "Ensemble/Bela Fleck and the Flecktones"]})
114
- assert_equal ["Ensemble/Robert Glasper Experiment", "Ensemble/Bela Fleck and the Flecktones"], res["data"]["upvoteEnsembles"]["ensembles"].map { |e| e["id"] }
115
- end
116
-
117
- it "uses the `as:` name when loading" do
118
- as_bands_query_str = query_str.sub("upvoteEnsembles", "upvoteEnsemblesAsBands")
119
- res = Jazz::Schema.execute(as_bands_query_str, variables: { ids: ["Ensemble/Robert Glasper Experiment", "Ensemble/Bela Fleck and the Flecktones"]})
120
- assert_equal ["Ensemble/Robert Glasper Experiment", "Ensemble/Bela Fleck and the Flecktones"], res["data"]["upvoteEnsemblesAsBands"]["ensembles"].map { |e| e["id"] }
121
- end
122
-
123
- it "doesn't append `s` to argument names that already end in `s`" do
124
- query = <<-GRAPHQL
125
- mutation($ids: [ID!]!) {
126
- upvoteEnsemblesIds(input: {ensemblesIds: $ids}) {
127
- ensembles {
128
- id
129
- }
130
- }
131
- }
132
- GRAPHQL
133
-
134
- res = Jazz::Schema.execute(query, variables: { ids: ["Ensemble/Robert Glasper Experiment", "Ensemble/Bela Fleck and the Flecktones"]})
135
- assert_equal ["Ensemble/Robert Glasper Experiment", "Ensemble/Bela Fleck and the Flecktones"], res["data"]["upvoteEnsemblesIds"]["ensembles"].map { |e| e["id"] }
136
- end
137
-
138
- it "returns an error instead when the ID resolves to nil" do
139
- res = Jazz::Schema.execute(query_str, variables: {
140
- ids: ["Ensemble/Nonexistant Name"],
141
- })
142
- assert_nil res["data"].fetch("upvoteEnsembles")
143
- assert_equal ['No object found for `ensembleIds: "Ensemble/Nonexistant Name"`'], res["errors"].map { |e| e["message"] }
144
- end
145
-
146
- it "returns an error instead when the ID resolves to an object of the wrong type" do
147
- res = Jazz::Schema.execute(query_str, variables: {
148
- ids: ["Instrument/Organ"],
149
- })
150
- assert_nil res["data"].fetch("upvoteEnsembles")
151
- assert_equal ["No object found for `ensembleIds: \"Instrument/Organ\"`"], res["errors"].map { |e| e["message"] }
152
- end
153
-
154
- it "raises an authorization error when the type's auth fails" do
155
- res = Jazz::Schema.execute(query_str, variables: {
156
- ids: ["Ensemble/Spinal Tap"],
157
- })
158
- assert_nil res["data"].fetch("upvoteEnsembles")
159
- # Failed silently
160
- refute res.key?("errors")
161
- end
162
- end
163
-
164
- describe "loading application objects" do
165
- let(:query_str) {
166
- <<-GRAPHQL
167
- mutation($id: ID!, $newName: String!) {
168
- renameEnsemble(input: {ensembleId: $id, newName: $newName}) {
169
- ensemble {
170
- name
171
- }
172
- }
173
- }
174
- GRAPHQL
175
- }
176
-
177
- it "loads arguments as objects of the given type" do
178
- res = Jazz::Schema.execute(query_str, variables: { id: "Ensemble/Robert Glasper Experiment", newName: "August Greene"})
179
- assert_equal "August Greene", res["data"]["renameEnsemble"]["ensemble"]["name"]
180
- end
181
-
182
- it "loads arguments as objects when provided an interface type" do
183
- query = <<-GRAPHQL
184
- mutation($id: ID!, $newName: String!) {
185
- renameNamedEntity(input: {namedEntityId: $id, newName: $newName}) {
186
- namedEntity {
187
- __typename
188
- name
189
- }
190
- }
191
- }
192
- GRAPHQL
193
-
194
- res = Jazz::Schema.execute(query, variables: { id: "Ensemble/Robert Glasper Experiment", newName: "August Greene"})
195
- assert_equal "August Greene", res["data"]["renameNamedEntity"]["namedEntity"]["name"]
196
- assert_equal "Ensemble", res["data"]["renameNamedEntity"]["namedEntity"]["__typename"]
197
- end
198
-
199
- it "loads arguments as objects when provided an union type" do
200
- query = <<-GRAPHQL
201
- mutation($id: ID!, $newName: String!) {
202
- renamePerformingAct(input: {performingActId: $id, newName: $newName}) {
203
- performingAct {
204
- __typename
205
- ... on Ensemble {
206
- name
207
- }
208
- }
209
- }
210
- }
211
- GRAPHQL
212
-
213
- res = Jazz::Schema.execute(query, variables: { id: "Ensemble/Robert Glasper Experiment", newName: "August Greene"})
214
- assert_equal "August Greene", res["data"]["renamePerformingAct"]["performingAct"]["name"]
215
- assert_equal "Ensemble", res["data"]["renamePerformingAct"]["performingAct"]["__typename"]
216
- end
217
-
218
- it "uses the `as:` name when loading" do
219
- band_query_str = query_str.sub("renameEnsemble", "renameEnsembleAsBand")
220
- res = Jazz::Schema.execute(band_query_str, variables: { id: "Ensemble/Robert Glasper Experiment", newName: "August Greene"})
221
- assert_equal "August Greene", res["data"]["renameEnsembleAsBand"]["ensemble"]["name"]
222
- end
223
-
224
- it "returns an error instead when the ID resolves to nil" do
225
- res = Jazz::Schema.execute(query_str, variables: {
226
- id: "Ensemble/Nonexistant Name",
227
- newName: "August Greene"
228
- })
229
- assert_nil res["data"].fetch("renameEnsemble")
230
- assert_equal ['No object found for `ensembleId: "Ensemble/Nonexistant Name"`'], res["errors"].map { |e| e["message"] }
231
- end
232
-
233
- it "returns an error instead when the ID resolves to an object of the wrong type" do
234
- res = Jazz::Schema.execute(query_str, variables: {
235
- id: "Instrument/Organ",
236
- newName: "August Greene"
237
- })
238
- assert_nil res["data"].fetch("renameEnsemble")
239
- assert_equal ["No object found for `ensembleId: \"Instrument/Organ\"`"], res["errors"].map { |e| e["message"] }
240
- end
241
-
242
- it "raises an authorization error when the type's auth fails" do
243
- res = Jazz::Schema.execute(query_str, variables: {
244
- id: "Ensemble/Spinal Tap",
245
- newName: "August Greene"
246
- })
247
- assert_nil res["data"].fetch("renameEnsemble")
248
- # Failed silently
249
- refute res.key?("errors")
250
- end
251
- end
252
- end
@@ -1,88 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
-
4
- class SpecExampleError < StandardError; end
5
- class SecondSpecExampleError < StandardError; end
6
-
7
- describe GraphQL::Schema::RescueMiddleware do
8
- let(:error_middleware) { ->{ raise(error_class) } }
9
-
10
- let(:rescue_middleware) do
11
- middleware = GraphQL::Schema::RescueMiddleware.new
12
- middleware.rescue_from(SpecExampleError) { |err| "there was an example error: #{err.class.name}" }
13
- middleware
14
- end
15
-
16
- let(:steps) { [rescue_middleware, error_middleware] }
17
-
18
- let(:middleware_chain) { GraphQL::Schema::MiddlewareChain.new(steps: steps) }
19
-
20
- describe "known errors" do
21
- let(:error_class) { SpecExampleError }
22
- it "handles them as execution errors" do
23
- result = middleware_chain.invoke([])
24
- assert_equal("there was an example error: SpecExampleError", result.message)
25
- assert_equal(GraphQL::ExecutionError, result.class)
26
- end
27
-
28
- describe "rescue_from superclass" do
29
- class ChildSpecExampleError < SpecExampleError; end
30
-
31
- let(:error_class) { ChildSpecExampleError }
32
- it "handles them as execution errors" do
33
- result = middleware_chain.invoke([])
34
- assert_equal("there was an example error: ChildSpecExampleError", result.message)
35
- assert_equal(GraphQL::ExecutionError, result.class)
36
- end
37
- end
38
-
39
- describe "with multiple error classes" do
40
- let(:error_class) { SecondSpecExampleError }
41
- let(:rescue_middleware) do
42
- middleware = GraphQL::Schema::RescueMiddleware.new
43
- middleware.rescue_from(SpecExampleError, SecondSpecExampleError) { |err| "there was an example error: #{err.class.name}" }
44
- middleware
45
- end
46
-
47
- it "handles errors for all of the classes" do
48
- result = middleware_chain.invoke([])
49
- assert_equal("there was an example error: SecondSpecExampleError", result.message)
50
- end
51
- end
52
-
53
- describe "with GraphQL::ExecutionError as an argument" do
54
- let(:rescue_middleware) do
55
- middleware = GraphQL::Schema::RescueMiddleware.new
56
- middleware.rescue_from(SpecExampleError) { |err| GraphQL::ExecutionError.new("there was an example error: #{err.class.name}", extensions: { code: "EXAMPLE_ERROR" }) }
57
- middleware
58
- end
59
-
60
- it "has the extensions key" do
61
- result = middleware_chain.invoke([])
62
- assert_equal("there was an example error: SpecExampleError", result.message)
63
- assert_equal({ code: "EXAMPLE_ERROR" }, result.extensions)
64
- end
65
- end
66
- end
67
-
68
- describe "unknown errors" do
69
- let(:error_class) { RuntimeError }
70
- it "re-raises them" do
71
- assert_raises(RuntimeError) { middleware_chain.invoke([]) }
72
- end
73
- end
74
-
75
- describe "removing multiple error handlers" do
76
- let(:error_class) { SpecExampleError }
77
- let(:rescue_middleware) do
78
- middleware = GraphQL::Schema::RescueMiddleware.new
79
- middleware.rescue_from(SpecExampleError, SecondSpecExampleError) { |err| "there was an example error: #{err.class.name}" }
80
- middleware.remove_handler(SpecExampleError, SecondSpecExampleError)
81
- middleware
82
- end
83
-
84
- it "no longer handles those errors" do
85
- assert_raises(SpecExampleError) { middleware_chain.invoke([]) }
86
- end
87
- end
88
- end
@@ -1,743 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
-
4
- describe GraphQL::Schema::Resolver do
5
- module ResolverTest
6
- class LazyBlock
7
- def initialize
8
- @get_value = Proc.new
9
- end
10
-
11
- def value
12
- @get_value.call
13
- end
14
- end
15
-
16
- class BaseResolver < GraphQL::Schema::Resolver
17
- end
18
-
19
- class Resolver1 < BaseResolver
20
- argument :value, Integer, required: false
21
- type [Integer, null: true], null: false
22
-
23
- def initialize(object:, context:)
24
- super
25
- if defined?(@value)
26
- raise "The instance should start fresh"
27
- end
28
- @value = [100]
29
- end
30
-
31
- def resolve(value: nil)
32
- @value << value
33
- @value
34
- end
35
- end
36
-
37
- class Resolver2 < Resolver1
38
- argument :extra_value, Integer, required: true
39
-
40
- def resolve(extra_value:, **_rest)
41
- value = super(_rest)
42
- value << extra_value
43
- value
44
- end
45
- end
46
-
47
- class Resolver3 < Resolver1
48
- end
49
-
50
- class Resolver4 < BaseResolver
51
- type Integer, null: false
52
-
53
- extras [:ast_node]
54
- def resolve(ast_node:)
55
- object.value + ast_node.name.size
56
- end
57
- end
58
-
59
- class ResolverWithPath < BaseResolver
60
- type String, null: false
61
-
62
- extras [:path]
63
- def resolve(path:)
64
- path.inspect
65
- end
66
- end
67
-
68
- class Resolver5 < Resolver4
69
- end
70
-
71
- class Resolver6 < Resolver1
72
- type Integer, null: false
73
-
74
- def resolve
75
- self.class.complexity
76
- end
77
- end
78
-
79
- class Resolver7 < Resolver6
80
- complexity 2
81
- end
82
-
83
- class Resolver8 < Resolver7
84
- end
85
-
86
- class PrepResolver1 < BaseResolver
87
- argument :int, Integer, required: true
88
- undef_method :load_int
89
- def load_int(i)
90
- i * 10
91
- end
92
-
93
- type Integer, null: false
94
-
95
- def resolve(int:)
96
- int
97
- end
98
-
99
- private
100
-
101
- def check_for_magic_number(int)
102
- if int == 13
103
- raise GraphQL::ExecutionError, "13 is unlucky!"
104
- elsif int > 99
105
- raise GraphQL::UnauthorizedError, "Top secret big number: #{int}"
106
- else
107
- int
108
- end
109
- end
110
- end
111
-
112
- class PrepResolver2 < PrepResolver1
113
- def load_int(i)
114
- LazyBlock.new {
115
- super - 35
116
- }
117
- end
118
- end
119
-
120
- class PrepResolver3 < PrepResolver1
121
- type Integer, null: true
122
-
123
- def load_int(i)
124
- check_for_magic_number(i)
125
- end
126
- end
127
-
128
- class PrepResolver4 < PrepResolver3
129
- def load_int(i)
130
- LazyBlock.new {
131
- super
132
- }
133
- end
134
- end
135
-
136
- class PrepResolver5 < PrepResolver1
137
- type Integer, null: true
138
-
139
- def ready?(int:)
140
- check_for_magic_number(int)
141
- end
142
- end
143
-
144
- class PrepResolver6 < PrepResolver5
145
- def ready?(**args)
146
- LazyBlock.new {
147
- super
148
- }
149
- end
150
- end
151
-
152
- class PrepResolver7 < GraphQL::Schema::Mutation
153
- argument :int, Integer, required: true
154
- field :errors, [String], null: true
155
- field :int, Integer, null: true
156
-
157
- def ready?(int:)
158
- if int == 13
159
- return false, { errors: ["Bad number!"] }
160
- else
161
- true
162
- end
163
- end
164
-
165
- def resolve(int:)
166
- { int: int }
167
- end
168
- end
169
-
170
- module HasValue
171
- include GraphQL::Schema::Interface
172
- field :value, Integer, null: false
173
- def self.resolve_type(obj, ctx)
174
- LazyBlock.new {
175
- if obj.is_a?(Integer)
176
- IntegerWrapper
177
- elsif obj == :resolve_type_as_wrong_type
178
- GraphQL::Types::String
179
- else
180
- raise "Unexpected: #{obj.inspect}"
181
- end
182
- }
183
- end
184
- end
185
-
186
- class IntegerWrapper < GraphQL::Schema::Object
187
- implements HasValue
188
- field :value, Integer, null: false, method: :itself
189
-
190
- def self.authorized?(value, ctx)
191
- if ctx[:max_value] && value > ctx[:max_value]
192
- false
193
- else
194
- true
195
- end
196
- end
197
- end
198
-
199
- class PrepResolver9 < BaseResolver
200
- argument :int_id, ID, required: true, loads: HasValue
201
- # Make sure the lazy object is resolved properly:
202
- type HasValue, null: true
203
- def object_from_id(type, id, ctx)
204
- # Make sure a lazy object is handled appropriately
205
- LazyBlock.new {
206
- # Make sure that the right type ends up here
207
- id.to_i + type.graphql_name.length
208
- }
209
- end
210
-
211
- def resolve(int:)
212
- int * 3
213
- end
214
- end
215
-
216
- class PrepResolver9Array < BaseResolver
217
- argument :int_ids, [ID], required: true, loads: HasValue, as: :ints
218
- # Make sure the lazy object is resolved properly:
219
- type [HasValue], null: false
220
- def object_from_id(type, id, ctx)
221
- # Make sure a lazy object is handled appropriately
222
- LazyBlock.new {
223
- # Make sure that the right type ends up here
224
- id.to_i + type.graphql_name.length
225
- }
226
- end
227
-
228
- def resolve(ints:)
229
- ints.map { |int| int * 3}
230
- end
231
- end
232
-
233
- class ResolverWithErrorHandler < BaseResolver
234
- argument :int, ID, required: true, loads: HasValue
235
- type HasValue, null: true
236
- def object_from_id(type, id, ctx)
237
- LazyBlock.new {
238
- if id == "failed_to_find"
239
- nil
240
- elsif id == "resolve_type_as_wrong_type"
241
- :resolve_type_as_wrong_type
242
- else
243
- id.length
244
- end
245
- }
246
- end
247
-
248
- def resolve(int:)
249
- int * 4
250
- end
251
-
252
- def load_application_object_failed(err)
253
- raise GraphQL::ExecutionError.new("ResolverWithErrorHandler failed for id: #{err.id.inspect} (#{err.object.inspect}) (#{err.class.name})")
254
- end
255
- end
256
-
257
- class PrepResolver10 < BaseResolver
258
- argument :int1, Integer, required: true
259
- argument :int2, Integer, required: true, as: :integer_2
260
- type Integer, null: true
261
- def authorized?(int1:, integer_2:)
262
- if int1 + integer_2 > context[:max_int]
263
- raise GraphQL::ExecutionError, "Inputs too big"
264
- elsif context[:min_int] && (int1 + integer_2 < context[:min_int])
265
- false
266
- else
267
- true
268
- end
269
- end
270
-
271
- def resolve(int1:, integer_2:)
272
- int1 + integer_2
273
- end
274
- end
275
-
276
- class PrepResolver11 < PrepResolver10
277
- def authorized?(int1:, integer_2:)
278
- LazyBlock.new { super(int1: int1 * 2, integer_2: integer_2) }
279
- end
280
- end
281
-
282
- class PrepResolver12 < GraphQL::Schema::Mutation
283
- argument :int1, Integer, required: true
284
- argument :int2, Integer, required: true
285
- field :error_messages, [String], null: true
286
- field :value, Integer, null: true
287
- def authorized?(int1:, int2:)
288
- if int1 + int2 > context[:max_int]
289
- return false, { error_messages: ["Inputs must be less than #{context[:max_int]} (but you provided #{int1 + int2})"] }
290
- else
291
- true
292
- end
293
- end
294
-
295
- def resolve(int1:, int2:)
296
- { value: int1 + int2 }
297
- end
298
- end
299
-
300
- class PrepResolver13 < PrepResolver12
301
- def authorized?(int1:, int2:)
302
- # Increment the numbers so we can be sure they're passing through here
303
- LazyBlock.new { super(int1: int1 + 1, int2: int2 + 1) }
304
- end
305
- end
306
-
307
- class PrepResolver14 < GraphQL::Schema::RelayClassicMutation
308
- field :number, Integer, null: false
309
-
310
- def authorized?
311
- true
312
- end
313
-
314
- def resolve
315
- { number: 1 }
316
- end
317
- end
318
-
319
- class MutationWithNullableLoadsArgument < GraphQL::Schema::Mutation
320
- argument :label_id, ID, required: false, loads: HasValue
321
- argument :label_ids, [ID], required: false, loads: HasValue
322
-
323
- field :inputs, String, null: false
324
-
325
- def resolve(**inputs)
326
- {
327
- inputs: JSON.dump(inputs)
328
- }
329
- end
330
- end
331
-
332
- class MutationWithRequiredLoadsArgument < GraphQL::Schema::Mutation
333
- argument :label_id, ID, required: true, loads: HasValue
334
-
335
- field :inputs, String, null: false
336
-
337
- def resolve(**inputs)
338
- {
339
- inputs: JSON.dump(inputs)
340
- }
341
- end
342
- end
343
-
344
- class Mutation < GraphQL::Schema::Object
345
- field :mutation_with_nullable_loads_argument, mutation: MutationWithNullableLoadsArgument
346
- field :mutation_with_required_loads_argument, mutation: MutationWithRequiredLoadsArgument
347
- end
348
-
349
- class Query < GraphQL::Schema::Object
350
- class CustomField < GraphQL::Schema::Field
351
- def resolve_field(*args)
352
- value = super
353
- if @name == "resolver3"
354
- value << -1
355
- end
356
- value
357
- end
358
-
359
- def resolve(*)
360
- value = super
361
- if @name == "resolver3"
362
- value << -1
363
- end
364
- value
365
- end
366
- end
367
-
368
- field_class(CustomField)
369
-
370
- field :resolver_1, resolver: Resolver1
371
- field :resolver_2, resolver: Resolver2
372
- field :resolver_3, resolver: Resolver3
373
- field :resolver_3_again, resolver: Resolver3, description: "field desc"
374
- field :resolver_4, "Positional description", resolver: Resolver4
375
- field :resolver_5, resolver: Resolver5
376
- field :resolver_6, resolver: Resolver6
377
- field :resolver_7, resolver: Resolver7
378
- field :resolver_8, resolver: Resolver8
379
- field :resolver_with_path, resolver: ResolverWithPath
380
-
381
- field :prep_resolver_1, resolver: PrepResolver1
382
- field :prep_resolver_2, resolver: PrepResolver2
383
- field :prep_resolver_3, resolver: PrepResolver3
384
- field :prep_resolver_4, resolver: PrepResolver4
385
- field :prep_resolver_5, resolver: PrepResolver5
386
- field :prep_resolver_6, resolver: PrepResolver6
387
- field :prep_resolver_7, resolver: PrepResolver7
388
- field :prep_resolver_9, resolver: PrepResolver9
389
- field :prep_resolver_9_array, resolver: PrepResolver9Array
390
- field :prep_resolver_10, resolver: PrepResolver10
391
- field :prep_resolver_11, resolver: PrepResolver11
392
- field :prep_resolver_12, resolver: PrepResolver12
393
- field :prep_resolver_13, resolver: PrepResolver13
394
- field :prep_resolver_14, resolver: PrepResolver14
395
- field :resolver_with_error_handler, resolver: ResolverWithErrorHandler
396
- end
397
-
398
- class Schema < GraphQL::Schema
399
- query(Query)
400
- mutation(Mutation)
401
- lazy_resolve LazyBlock, :value
402
- orphan_types IntegerWrapper
403
- if TESTING_INTERPRETER
404
- use GraphQL::Execution::Interpreter
405
- end
406
-
407
- def object_from_id(id, ctx)
408
- if id == "invalid"
409
- nil
410
- else
411
- 1
412
- end
413
- end
414
- end
415
- end
416
-
417
- def exec_query(*args)
418
- ResolverTest::Schema.execute(*args)
419
- end
420
-
421
- describe ".path" do
422
- it "is the name" do
423
- assert_equal "Resolver1", ResolverTest::Resolver1.path
424
- end
425
-
426
- it "is used for arguments and fields" do
427
- assert_equal "Resolver1.value", ResolverTest::Resolver1.arguments["value"].path
428
- assert_equal "PrepResolver7.int", ResolverTest::PrepResolver7.fields["int"].path
429
- end
430
-
431
- it "works on instances" do
432
- r = ResolverTest::Resolver1.new(object: nil, context: nil)
433
- assert_equal "Resolver1", r.path
434
- end
435
- end
436
-
437
- it "gets initialized for each resolution" do
438
- # State isn't shared between calls:
439
- res = exec_query " { r1: resolver1(value: 1) r2: resolver1 }"
440
- assert_equal [100, 1], res["data"]["r1"]
441
- assert_equal [100, nil], res["data"]["r2"]
442
- end
443
-
444
- it "inherits type and arguments" do
445
- res = exec_query " { r1: resolver2(value: 1, extraValue: 2) r2: resolver2(extraValue: 3) }"
446
- assert_equal [100, 1, 2], res["data"]["r1"]
447
- assert_equal [100, nil, 3], res["data"]["r2"]
448
- end
449
-
450
- it "uses the object's field_class" do
451
- res = exec_query " { r1: resolver3(value: 1) r2: resolver3 }"
452
- assert_equal [100, 1, -1], res["data"]["r1"]
453
- assert_equal [100, nil, -1], res["data"]["r2"]
454
- end
455
-
456
- describe "resolve method" do
457
- it "has access to the application object" do
458
- res = exec_query " { resolver4 } ", root_value: OpenStruct.new(value: 4)
459
- assert_equal 13, res["data"]["resolver4"]
460
- end
461
-
462
- it "gets extras" do
463
- res = exec_query " { resolver4 } ", root_value: OpenStruct.new(value: 0)
464
- assert_equal 9, res["data"]["resolver4"]
465
- end
466
-
467
- it "gets path from extras" do
468
- res = exec_query " { resolverWithPath } ", root_value: OpenStruct.new(value: 0)
469
- assert_equal '["resolverWithPath"]', res["data"]["resolverWithPath"]
470
- end
471
- end
472
-
473
- describe "load_application_object_failed hook" do
474
- it "isn't called for successful queries" do
475
- query_str = <<-GRAPHQL
476
- {
477
- resolverWithErrorHandler(int: "abcd") { value }
478
- }
479
- GRAPHQL
480
-
481
- res = exec_query(query_str)
482
- assert_equal 16, res["data"]["resolverWithErrorHandler"]["value"]
483
- refute res.key?("errors")
484
- end
485
-
486
- describe "when the id doesn't find anything" do
487
- it "passes an error to the handler" do
488
- query_str = <<-GRAPHQL
489
- {
490
- resolverWithErrorHandler(int: "failed_to_find") { value }
491
- }
492
- GRAPHQL
493
-
494
- res = exec_query(query_str)
495
- assert_nil res["data"].fetch("resolverWithErrorHandler")
496
- expected_err = "ResolverWithErrorHandler failed for id: \"failed_to_find\" (nil) (GraphQL::LoadApplicationObjectFailedError)"
497
- assert_equal [expected_err], res["errors"].map { |e| e["message"] }
498
- end
499
- end
500
-
501
- describe "when resolve_type returns a no-good type" do
502
- it "calls the handler" do
503
- query_str = <<-GRAPHQL
504
- {
505
- resolverWithErrorHandler(int: "resolve_type_as_wrong_type") { value }
506
- }
507
- GRAPHQL
508
-
509
- res = exec_query(query_str)
510
- assert_nil res["data"].fetch("resolverWithErrorHandler")
511
- expected_err = "ResolverWithErrorHandler failed for id: \"resolve_type_as_wrong_type\" (:resolve_type_as_wrong_type) (GraphQL::LoadApplicationObjectFailedError)"
512
- assert_equal [expected_err], res["errors"].map { |e| e["message"] }
513
- end
514
- end
515
- end
516
-
517
-
518
- describe "extras" do
519
- it "is inherited" do
520
- res = exec_query " { resolver4 resolver5 } ", root_value: OpenStruct.new(value: 0)
521
- assert_equal 9, res["data"]["resolver4"]
522
- assert_equal 9, res["data"]["resolver5"]
523
- end
524
- end
525
-
526
- describe "complexity" do
527
- it "has default values" do
528
- res = exec_query " { resolver6 } ", root_value: OpenStruct.new(value: 0)
529
- assert_equal 1, res["data"]["resolver6"]
530
- end
531
-
532
- it "is inherited" do
533
- res = exec_query " { resolver7 resolver8 } ", root_value: OpenStruct.new(value: 0)
534
- assert_equal 2, res["data"]["resolver7"]
535
- assert_equal 2, res["data"]["resolver8"]
536
- end
537
- end
538
-
539
- describe "when applied to a field" do
540
- it "gets the field's description" do
541
- assert_nil ResolverTest::Schema.find("Query.resolver3").description
542
- assert_equal "field desc", ResolverTest::Schema.find("Query.resolver3Again").description
543
- assert_equal "Positional description", ResolverTest::Schema.find("Query.resolver4").description
544
- end
545
-
546
- it "gets the field's name" do
547
- # Matching name:
548
- assert ResolverTest::Schema.find("Query.resolver3")
549
- # Mismatched name:
550
- assert ResolverTest::Schema.find("Query.resolver3Again")
551
- end
552
- end
553
-
554
- describe "preparing inputs" do
555
- # Add assertions for a given field, assuming the behavior of `check_for_magic_number`
556
- def add_error_assertions(field_name, description)
557
- res = exec_query("{ int: #{field_name}(int: 13) }")
558
- assert_nil res["data"].fetch("int"), "#{description}: no result for execution error"
559
- assert_equal ["13 is unlucky!"], res["errors"].map { |e| e["message"] }, "#{description}: top-level error is added"
560
-
561
- res = exec_query("{ int: #{field_name}(int: 200) }")
562
- assert_nil res["data"].fetch("int"), "#{description}: No result for authorization error"
563
- refute res.key?("errors"), "#{description}: silent auth failure (no top-level error)"
564
- end
565
-
566
- it "keeps track of the `loads:` option" do
567
- arg = ResolverTest::MutationWithNullableLoadsArgument.arguments["labelId"]
568
- assert_equal ResolverTest::HasValue, arg.loads
569
- end
570
-
571
- describe "ready?" do
572
- it "can raise errors" do
573
- res = exec_query("{ int: prepResolver5(int: 5) }")
574
- assert_equal 50, res["data"]["int"]
575
- add_error_assertions("prepResolver5", "ready?")
576
- end
577
-
578
- it "can raise errors in lazy sync" do
579
- res = exec_query("{ int: prepResolver6(int: 5) }")
580
- assert_equal 50, res["data"]["int"]
581
- add_error_assertions("prepResolver6", "lazy ready?")
582
- end
583
-
584
- it "can return false and data" do
585
- res = exec_query("{ int: prepResolver7(int: 13) { errors int } }")
586
- assert_equal ["Bad number!"], res["data"]["int"]["errors"]
587
-
588
- res = exec_query("{ int: prepResolver7(int: 213) { errors int } }")
589
- assert_equal 213, res["data"]["int"]["int"]
590
- end
591
- end
592
-
593
- describe "loading arguments" do
594
- it "calls load methods and injects the return value" do
595
- res = exec_query("{ prepResolver1(int: 5) }")
596
- assert_equal 50, res["data"]["prepResolver1"], "The load multiplier was called"
597
- end
598
-
599
- it "supports lazy values" do
600
- res = exec_query("{ prepResolver2(int: 5) }")
601
- assert_equal 15, res["data"]["prepResolver2"], "The load multiplier was called"
602
- end
603
-
604
- it "supports raising GraphQL::UnauthorizedError and GraphQL::ExecutionError" do
605
- res = exec_query("{ prepResolver3(int: 5) }")
606
- assert_equal 5, res["data"]["prepResolver3"]
607
- add_error_assertions("prepResolver3", "load_ hook")
608
- end
609
-
610
- it "supports raising errors from promises" do
611
- res = exec_query("{ prepResolver4(int: 5) }")
612
- assert_equal 5, res["data"]["prepResolver4"]
613
- add_error_assertions("prepResolver4", "lazy load_ hook")
614
- end
615
- end
616
-
617
- describe "validating arguments" do
618
- describe ".authorized?" do
619
- it "can raise an error to halt" do
620
- res = exec_query("{ prepResolver10(int1: 5, int2: 6) }", context: { max_int: 9 })
621
- assert_equal ["Inputs too big"], res["errors"].map { |e| e["message"] }
622
-
623
- res = exec_query("{ prepResolver10(int1: 5, int2: 6) }", context: { max_int: 90 })
624
- assert_equal 11, res["data"]["prepResolver10"]
625
- end
626
-
627
- it "uses the argument name provided in `as:`" do
628
- res = exec_query("{ prepResolver10(int1: 5, int2: 6) }", context: { max_int: 90 })
629
- assert_equal 11, res["data"]["prepResolver10"]
630
- end
631
-
632
- it "can return a lazy object" do
633
- # This is too big because it's modified in the overridden authorized? hook:
634
- res = exec_query("{ prepResolver11(int1: 3, int2: 5) }", context: { max_int: 9 })
635
- assert_equal ["Inputs too big"], res["errors"].map { |e| e["message"] }
636
-
637
- res = exec_query("{ prepResolver11(int1: 3, int2: 5) }", context: { max_int: 90 })
638
- assert_equal 8, res["data"]["prepResolver11"]
639
- end
640
-
641
- it "can return data early" do
642
- res = exec_query("{ prepResolver12(int1: 9, int2: 5) { errorMessages } }", context: { max_int: 9 })
643
- assert_equal ["Inputs must be less than 9 (but you provided 14)"], res["data"]["prepResolver12"]["errorMessages"]
644
- # This works
645
- res = exec_query("{ prepResolver12(int1: 2, int2: 5) { value } }", context: { max_int: 9 })
646
- assert_equal 7, res["data"]["prepResolver12"]["value"]
647
- end
648
-
649
- it "can return data early in a promise" do
650
- # This is too big because it's modified in the overridden authorized? hook:
651
- res = exec_query("{ prepResolver13(int1: 4, int2: 4) { errorMessages } }", context: { max_int: 9 })
652
- assert_equal ["Inputs must be less than 9 (but you provided 10)"], res["data"]["prepResolver13"]["errorMessages"]
653
- # This works
654
- res = exec_query("{ prepResolver13(int1: 2, int2: 5) { value } }", context: { max_int: 9 })
655
- assert_equal 7, res["data"]["prepResolver13"]["value"]
656
- end
657
-
658
- it "can return false to halt" do
659
- str = <<-GRAPHQL
660
- {
661
- prepResolver10(int1: 5, int2: 10)
662
- prepResolver11(int1: 3, int2: 5)
663
- }
664
- GRAPHQL
665
- res = exec_query(str, context: { max_int: 100, min_int: 20 })
666
- assert_equal({ "prepResolver10" => nil, "prepResolver11" => nil }, res["data"])
667
- end
668
-
669
- it "works with no arguments for RelayClassicMutation" do
670
- res = exec_query("{ prepResolver14(input: {}) { number } }")
671
- assert_equal 1, res["data"]["prepResolver14"]["number"]
672
- end
673
-
674
- it "uses loaded objects" do
675
- query_str = "{ prepResolver9(intId: 9) { value } }"
676
- # This will cause an unauthorized response
677
- # by `HasValue.authorized?`
678
- context = { max_value: 8 }
679
- res = exec_query(query_str, context: context)
680
- assert_nil res["data"]["prepResolver9"]
681
- # This is OK
682
- context = { max_value: 900 }
683
- res = exec_query(query_str, context: context)
684
- assert_equal 51, res["data"]["prepResolver9"]["value"]
685
- # This is the transformation applied by the resolver,
686
- # just make sure it matches the response
687
- assert_equal 51, (9 + "HasValue".size) * 3
688
- end
689
- end
690
- end
691
-
692
- describe "Loading inputs" do
693
- it "calls object_from_id" do
694
- res = exec_query('{ prepResolver9(intId: "5") { value } }')
695
- # (5 + 8) * 3
696
- assert_equal 39, res["data"]["prepResolver9"]["value"]
697
- end
698
-
699
- it "supports loading array of ids" do
700
- res = exec_query('{ prepResolver9Array(intIds: ["1", "10", "100"]) { value } }')
701
- # (1 + 8) * 3
702
- # (10 + 8) * 3
703
- # (100 + 8) * 3
704
- assert_equal [27, 54, 324], res["data"]["prepResolver9Array"].map { |v| v["value"] }
705
- end
706
-
707
- it "preserves `nil` when nullable argument is provided `null`" do
708
- res = exec_query("mutation { mutationWithNullableLoadsArgument(labelId: null) { inputs } }")
709
-
710
- assert_equal nil, res["errors"]
711
- assert_equal '{"label":null}', res["data"]["mutationWithNullableLoadsArgument"]["inputs"]
712
- end
713
-
714
- it "preserves `nil` when nullable list argument is provided `null`" do
715
- res = exec_query("mutation { mutationWithNullableLoadsArgument(labelIds: null) { inputs } }")
716
-
717
- assert_equal nil, res["errors"]
718
- assert_equal '{"labels":null}', res["data"]["mutationWithNullableLoadsArgument"]["inputs"]
719
- end
720
-
721
- it "omits omitted nullable argument" do
722
- res = exec_query("mutation { mutationWithNullableLoadsArgument { inputs } }")
723
-
724
- assert_equal nil, res["errors"]
725
- assert_equal "{}", res["data"]["mutationWithNullableLoadsArgument"]["inputs"]
726
- end
727
-
728
- it "returns an error when nullable argument is provided an invalid value" do
729
- res = exec_query('mutation { mutationWithNullableLoadsArgument(labelId: "invalid") { inputs } }')
730
-
731
- assert res["errors"]
732
- assert_equal 'No object found for `labelId: "invalid"`', res["errors"][0]["message"]
733
- end
734
-
735
- it "returns an error when a non-nullable argument is provided an invalid value" do
736
- res = exec_query('mutation { mutationWithRequiredLoadsArgument(labelId: "invalid") { inputs } }')
737
-
738
- assert res["errors"]
739
- assert_equal 'No object found for `labelId: "invalid"`', res["errors"][0]["message"]
740
- end
741
- end
742
- end
743
- end