graphql 1.8.7 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (368) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install_generator.rb +2 -1
  3. data/lib/generators/graphql/scalar_generator.rb +20 -0
  4. data/lib/generators/graphql/templates/base_scalar.erb +4 -0
  5. data/lib/generators/graphql/templates/scalar.erb +13 -0
  6. data/lib/graphql/analysis/ast/analyzer.rb +62 -0
  7. data/lib/graphql/analysis/ast/field_usage.rb +28 -0
  8. data/lib/graphql/analysis/ast/max_query_complexity.rb +23 -0
  9. data/lib/graphql/analysis/ast/max_query_depth.rb +18 -0
  10. data/lib/graphql/analysis/ast/query_complexity.rb +114 -0
  11. data/lib/graphql/analysis/ast/query_depth.rb +66 -0
  12. data/lib/graphql/analysis/ast/visitor.rb +255 -0
  13. data/lib/graphql/analysis/ast.rb +82 -0
  14. data/lib/graphql/analysis.rb +1 -0
  15. data/lib/graphql/argument.rb +5 -0
  16. data/lib/graphql/authorization.rb +1 -0
  17. data/lib/graphql/backwards_compatibility.rb +1 -1
  18. data/lib/graphql/base_type.rb +1 -1
  19. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +1 -2
  20. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -6
  21. data/lib/graphql/dig.rb +19 -0
  22. data/lib/graphql/directive/include_directive.rb +1 -7
  23. data/lib/graphql/directive/skip_directive.rb +1 -8
  24. data/lib/graphql/directive.rb +13 -1
  25. data/lib/graphql/enum_type.rb +8 -0
  26. data/lib/graphql/execution/execute.rb +36 -17
  27. data/lib/graphql/execution/instrumentation.rb +2 -0
  28. data/lib/graphql/execution/interpreter/execution_errors.rb +29 -0
  29. data/lib/graphql/execution/interpreter/hash_response.rb +46 -0
  30. data/lib/graphql/execution/interpreter/resolve.rb +58 -0
  31. data/lib/graphql/execution/interpreter/runtime.rb +597 -0
  32. data/lib/graphql/execution/interpreter.rb +99 -0
  33. data/lib/graphql/execution/lazy.rb +8 -1
  34. data/lib/graphql/execution/lookahead.rb +351 -0
  35. data/lib/graphql/execution/multiplex.rb +37 -29
  36. data/lib/graphql/execution.rb +2 -0
  37. data/lib/graphql/execution_error.rb +1 -1
  38. data/lib/graphql/field.rb +1 -7
  39. data/lib/graphql/integer_encoding_error.rb +12 -0
  40. data/lib/graphql/internal_representation/rewrite.rb +127 -142
  41. data/lib/graphql/introspection/dynamic_fields.rb +8 -2
  42. data/lib/graphql/introspection/entry_points.rb +11 -6
  43. data/lib/graphql/introspection/enum_value_type.rb +4 -0
  44. data/lib/graphql/introspection/schema_type.rb +7 -2
  45. data/lib/graphql/introspection/type_type.rb +9 -5
  46. data/lib/graphql/invalid_null_error.rb +1 -1
  47. data/lib/graphql/language/block_string.rb +37 -0
  48. data/lib/graphql/language/document_from_schema_definition.rb +10 -7
  49. data/lib/graphql/language/lexer.rb +55 -36
  50. data/lib/graphql/language/lexer.rl +8 -3
  51. data/lib/graphql/language/nodes.rb +440 -362
  52. data/lib/graphql/language/parser.rb +56 -56
  53. data/lib/graphql/language/parser.y +12 -12
  54. data/lib/graphql/language/printer.rb +2 -2
  55. data/lib/graphql/language/visitor.rb +158 -15
  56. data/lib/graphql/language.rb +0 -1
  57. data/lib/graphql/literal_validation_error.rb +6 -0
  58. data/lib/graphql/query/arguments.rb +3 -2
  59. data/lib/graphql/query/arguments_cache.rb +1 -1
  60. data/lib/graphql/query/context.rb +14 -5
  61. data/lib/graphql/query/executor.rb +1 -1
  62. data/lib/graphql/query/result.rb +1 -1
  63. data/lib/graphql/query/validation_pipeline.rb +35 -11
  64. data/lib/graphql/query/variable_validation_error.rb +10 -1
  65. data/lib/graphql/query.rb +16 -2
  66. data/lib/graphql/relay/base_connection.rb +2 -0
  67. data/lib/graphql/relay/connection_instrumentation.rb +3 -1
  68. data/lib/graphql/relay/connection_resolve.rb +1 -1
  69. data/lib/graphql/relay/node.rb +2 -28
  70. data/lib/graphql/relay/relation_connection.rb +1 -1
  71. data/lib/graphql/schema/argument.rb +13 -5
  72. data/lib/graphql/schema/base_64_encoder.rb +4 -4
  73. data/lib/graphql/schema/build_from_definition.rb +2 -4
  74. data/lib/graphql/schema/default_type_error.rb +1 -1
  75. data/lib/graphql/schema/directive/feature.rb +66 -0
  76. data/lib/graphql/schema/directive/include.rb +25 -0
  77. data/lib/graphql/schema/directive/skip.rb +25 -0
  78. data/lib/graphql/schema/directive/transform.rb +48 -0
  79. data/lib/graphql/schema/directive.rb +103 -0
  80. data/lib/graphql/schema/enum_value.rb +3 -2
  81. data/lib/graphql/schema/field/connection_extension.rb +50 -0
  82. data/lib/graphql/schema/field/scope_extension.rb +18 -0
  83. data/lib/graphql/schema/field.rb +273 -64
  84. data/lib/graphql/schema/field_extension.rb +69 -0
  85. data/lib/graphql/schema/input_object.rb +16 -8
  86. data/lib/graphql/schema/interface.rb +1 -0
  87. data/lib/graphql/schema/loader.rb +22 -16
  88. data/lib/graphql/schema/member/base_dsl_methods.rb +8 -2
  89. data/lib/graphql/schema/member/build_type.rb +33 -1
  90. data/lib/graphql/schema/member/has_arguments.rb +6 -2
  91. data/lib/graphql/schema/member/has_fields.rb +18 -70
  92. data/lib/graphql/schema/member/has_path.rb +25 -0
  93. data/lib/graphql/schema/member/instrumentation.rb +10 -7
  94. data/lib/graphql/schema/member.rb +2 -0
  95. data/lib/graphql/schema/mutation.rb +6 -48
  96. data/lib/graphql/schema/non_null.rb +5 -1
  97. data/lib/graphql/schema/object.rb +18 -4
  98. data/lib/graphql/schema/printer.rb +1 -1
  99. data/lib/graphql/schema/relay_classic_mutation.rb +42 -9
  100. data/lib/graphql/schema/resolver/has_payload_type.rb +65 -0
  101. data/lib/graphql/schema/resolver.rb +45 -20
  102. data/lib/graphql/schema/subscription.rb +97 -0
  103. data/lib/graphql/schema/traversal.rb +11 -7
  104. data/lib/graphql/schema.rb +186 -38
  105. data/lib/graphql/static_validation/all_rules.rb +3 -2
  106. data/lib/graphql/static_validation/base_visitor.rb +199 -0
  107. data/lib/graphql/static_validation/default_visitor.rb +15 -0
  108. data/lib/graphql/static_validation/definition_dependencies.rb +62 -68
  109. data/lib/graphql/static_validation/{message.rb → error.rb} +11 -11
  110. data/lib/graphql/static_validation/interpreter_visitor.rb +14 -0
  111. data/lib/graphql/static_validation/literal_validator.rb +54 -11
  112. data/lib/graphql/static_validation/no_validate_visitor.rb +10 -0
  113. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +87 -16
  114. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +31 -0
  115. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +11 -11
  116. data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +30 -0
  117. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +52 -8
  118. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +35 -0
  119. data/lib/graphql/static_validation/rules/directives_are_defined.rb +12 -15
  120. data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +29 -0
  121. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +19 -14
  122. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +31 -0
  123. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +17 -19
  124. data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +32 -0
  125. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +30 -14
  126. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +31 -0
  127. data/lib/graphql/static_validation/rules/fields_will_merge.rb +356 -29
  128. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +32 -0
  129. data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +20 -13
  130. data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +29 -0
  131. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +37 -29
  132. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +35 -0
  133. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +25 -17
  134. data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +29 -0
  135. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +12 -10
  136. data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +29 -0
  137. data/lib/graphql/static_validation/rules/fragments_are_named.rb +7 -11
  138. data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +26 -0
  139. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +16 -16
  140. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +30 -0
  141. data/lib/graphql/static_validation/rules/fragments_are_used.rb +21 -14
  142. data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +29 -0
  143. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +10 -14
  144. data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +26 -0
  145. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +30 -30
  146. data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +25 -0
  147. data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +25 -17
  148. data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +28 -0
  149. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +17 -18
  150. data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +35 -0
  151. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +47 -0
  152. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +35 -0
  153. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +10 -14
  154. data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +26 -0
  155. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +28 -17
  156. data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +29 -0
  157. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +35 -27
  158. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +39 -0
  159. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +15 -14
  160. data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +29 -0
  161. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +41 -30
  162. data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +38 -0
  163. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +18 -14
  164. data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +32 -0
  165. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +73 -65
  166. data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +37 -0
  167. data/lib/graphql/static_validation/validation_context.rb +8 -51
  168. data/lib/graphql/static_validation/validator.rb +23 -15
  169. data/lib/graphql/static_validation.rb +5 -3
  170. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -2
  171. data/lib/graphql/subscriptions/event.rb +28 -5
  172. data/lib/graphql/subscriptions/subscription_root.rb +66 -0
  173. data/lib/graphql/subscriptions.rb +16 -2
  174. data/lib/graphql/tracing/active_support_notifications_tracing.rb +0 -1
  175. data/lib/graphql/tracing/appsignal_tracing.rb +1 -1
  176. data/lib/graphql/tracing/data_dog_tracing.rb +1 -1
  177. data/lib/graphql/tracing/new_relic_tracing.rb +3 -3
  178. data/lib/graphql/tracing/platform_tracing.rb +17 -1
  179. data/lib/graphql/tracing/prometheus_tracing.rb +1 -1
  180. data/lib/graphql/tracing/scout_tracing.rb +1 -1
  181. data/lib/graphql/tracing/skylight_tracing.rb +3 -3
  182. data/lib/graphql/tracing.rb +8 -8
  183. data/lib/graphql/types/float.rb +1 -1
  184. data/lib/graphql/types/int.rb +11 -2
  185. data/lib/graphql/types/iso_8601_date_time.rb +15 -1
  186. data/lib/graphql/types/relay/base_connection.rb +15 -1
  187. data/lib/graphql/types/relay/node.rb +0 -1
  188. data/lib/graphql/types/relay/node_field.rb +43 -0
  189. data/lib/graphql/types/relay/nodes_field.rb +45 -0
  190. data/lib/graphql/types/relay.rb +2 -0
  191. data/lib/graphql/unauthorized_error.rb +4 -0
  192. data/lib/graphql/unauthorized_field_error.rb +23 -0
  193. data/lib/graphql/upgrader/member.rb +5 -0
  194. data/lib/graphql/version.rb +1 -1
  195. data/lib/graphql.rb +6 -1
  196. data/readme.md +7 -7
  197. data/spec/dummy/Gemfile +1 -1
  198. data/spec/dummy/Gemfile.lock +157 -0
  199. data/spec/dummy/app/channels/graphql_channel.rb +22 -11
  200. data/spec/dummy/config/locales/en.yml +1 -1
  201. data/spec/dummy/log/test.log +199 -0
  202. data/spec/dummy/test/test_helper.rb +1 -0
  203. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4w/4wzXRZrAkwKdgYaSE0pid5eB-fer8vSfSku_NPg4rMA.cache +0 -0
  204. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7I/7IHVBiJT06QSpgLpLoJIxboQ0B-D_tMTxsvoezBTV3Q.cache +1 -0
  205. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8w/8wY_SKagj8wHuwGNAAf6JnQ8joMbC6cEYpHrTAI8Urc.cache +1 -0
  206. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/AK/AKzz1u6bGb4auXcrObA_g5LL-oV0ejNGa448AgAi_WQ.cache +1 -0
  207. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ET/ETW4uxvaYpruL8y6_ZptUH82ZowMaHIqvg5WexBFdEM.cache +3 -0
  208. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F1/F1TWpjjyA56k9Z90n5B3xRn7DUdGjX73QCkYC6k07JQ.cache +0 -0
  209. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +2 -0
  210. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +2 -0
  211. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ms/MsKSimH_UCB-H1tLvDABDHuvGciuoW6kVqQWDrXU5FQ.cache +0 -0
  212. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Mt/Mtci-Kim50aPOmeClD4AIicKn1d1WJ0n454IjSd94sk.cache +0 -0
  213. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QH/QHt3Tc1Y6M66Oo_pDuMyWrQNs4Pp3SMeZR5K1wJj2Ts.cache +1 -0
  214. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/XU/XU4k1OXnfMils5SrirorPvDSyDSqiOWLZNtmAH1HH8k.cache +0 -0
  215. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ZI/ZIof7mZxWWCnraIFOCuV6a8QRWzKJXJnx2Xd7C0ZyX0.cache +1 -0
  216. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cG/cGc_puuPS5pZKgUcy1Y_i1L6jl5UtsiIrMH59rTzR6c.cache +3 -0
  217. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/df/dfro_B6bx3KP1Go-7jEOqqZ2j4hVRseXIc3es9PKQno.cache +1 -0
  218. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jO/jO1DfbqnG0mTULsjJJANc3fefrG2zt7DIMmcptMT628.cache +1 -0
  219. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pE/pE7gO6pQ-z187Swb4hT554wmqsq-cNzgPWLrCz-LQQQ.cache +0 -0
  220. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/r9/r9iU1l58a6rxkZSW5RSC52_tD-_UQuHxoMVnkfJ7Mhs.cache +1 -0
  221. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xi/xitPPFfPIyDMpaznV0sBBcw8eSCV8PJcLLWin78sCgE.cache +0 -0
  222. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  223. data/spec/graphql/analysis/analyze_query_spec.rb +1 -1
  224. data/spec/graphql/analysis/ast/field_usage_spec.rb +51 -0
  225. data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +120 -0
  226. data/spec/graphql/analysis/ast/max_query_depth_spec.rb +114 -0
  227. data/spec/graphql/analysis/ast/query_complexity_spec.rb +299 -0
  228. data/spec/graphql/analysis/ast/query_depth_spec.rb +108 -0
  229. data/spec/graphql/analysis/ast_spec.rb +269 -0
  230. data/spec/graphql/authorization_spec.rb +120 -23
  231. data/spec/graphql/base_type_spec.rb +6 -4
  232. data/spec/graphql/enum_type_spec.rb +6 -1
  233. data/spec/graphql/execution/execute_spec.rb +9 -9
  234. data/spec/graphql/execution/instrumentation_spec.rb +19 -0
  235. data/spec/graphql/execution/interpreter_spec.rb +485 -0
  236. data/spec/graphql/execution/lazy_spec.rb +67 -1
  237. data/spec/graphql/execution/lookahead_spec.rb +363 -0
  238. data/spec/graphql/execution/multiplex_spec.rb +31 -3
  239. data/spec/graphql/execution/typecast_spec.rb +20 -20
  240. data/spec/graphql/execution_error_spec.rb +110 -96
  241. data/spec/graphql/field_spec.rb +1 -1
  242. data/spec/graphql/input_object_type_spec.rb +13 -352
  243. data/spec/graphql/int_type_spec.rb +19 -0
  244. data/spec/graphql/interface_type_spec.rb +4 -4
  245. data/spec/graphql/internal_representation/rewrite_spec.rb +2 -0
  246. data/spec/graphql/introspection/input_value_type_spec.rb +1 -1
  247. data/spec/graphql/introspection/type_type_spec.rb +1 -2
  248. data/spec/graphql/language/document_from_schema_definition_spec.rb +2 -2
  249. data/spec/graphql/language/lexer_spec.rb +72 -3
  250. data/spec/graphql/language/nodes_spec.rb +20 -0
  251. data/spec/graphql/language/printer_spec.rb +18 -6
  252. data/spec/graphql/language/visitor_spec.rb +320 -14
  253. data/spec/graphql/non_null_type_spec.rb +1 -1
  254. data/spec/graphql/object_type_spec.rb +32 -27
  255. data/spec/graphql/query/arguments_spec.rb +21 -0
  256. data/spec/graphql/query/context_spec.rb +28 -0
  257. data/spec/graphql/query/executor_spec.rb +40 -36
  258. data/spec/graphql/query_spec.rb +12 -6
  259. data/spec/graphql/schema/argument_spec.rb +35 -1
  260. data/spec/graphql/schema/build_from_definition_spec.rb +144 -29
  261. data/spec/graphql/schema/catchall_middleware_spec.rb +16 -15
  262. data/spec/graphql/schema/directive/feature_spec.rb +81 -0
  263. data/spec/graphql/schema/directive/transform_spec.rb +39 -0
  264. data/spec/graphql/schema/enum_spec.rb +12 -3
  265. data/spec/graphql/schema/enum_value_spec.rb +11 -0
  266. data/spec/graphql/schema/field_extension_spec.rb +115 -0
  267. data/spec/graphql/schema/field_spec.rb +47 -7
  268. data/spec/graphql/schema/input_object_spec.rb +95 -0
  269. data/spec/graphql/schema/instrumentation_spec.rb +3 -0
  270. data/spec/graphql/schema/interface_spec.rb +8 -2
  271. data/spec/graphql/schema/introspection_system_spec.rb +9 -1
  272. data/spec/graphql/schema/loader_spec.rb +5 -0
  273. data/spec/graphql/schema/member/accepts_definition_spec.rb +4 -0
  274. data/spec/graphql/schema/member/build_type_spec.rb +46 -0
  275. data/spec/graphql/schema/member/scoped_spec.rb +19 -3
  276. data/spec/graphql/schema/mutation_spec.rb +5 -3
  277. data/spec/graphql/schema/object_spec.rb +9 -1
  278. data/spec/graphql/schema/printer_spec.rb +255 -93
  279. data/spec/graphql/schema/relay_classic_mutation_spec.rb +133 -0
  280. data/spec/graphql/schema/resolver_spec.rb +173 -9
  281. data/spec/graphql/schema/scalar_spec.rb +6 -0
  282. data/spec/graphql/schema/subscription_spec.rb +416 -0
  283. data/spec/graphql/schema/traversal_spec.rb +10 -10
  284. data/spec/graphql/schema/type_expression_spec.rb +2 -2
  285. data/spec/graphql/schema/union_spec.rb +7 -0
  286. data/spec/graphql/schema/validation_spec.rb +1 -1
  287. data/spec/graphql/schema/warden_spec.rb +145 -88
  288. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +213 -73
  289. data/spec/graphql/static_validation/rules/argument_names_are_unique_spec.rb +2 -2
  290. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +72 -29
  291. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +4 -2
  292. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +4 -2
  293. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +10 -5
  294. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +10 -5
  295. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +131 -5
  296. data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +2 -1
  297. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +6 -3
  298. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +4 -2
  299. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +4 -2
  300. data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +2 -1
  301. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +6 -3
  302. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +22 -2
  303. data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +2 -1
  304. data/spec/graphql/static_validation/rules/operation_names_are_valid_spec.rb +6 -3
  305. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +13 -4
  306. data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb +58 -0
  307. data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +2 -1
  308. data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +14 -7
  309. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +14 -7
  310. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +8 -4
  311. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +8 -4
  312. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +23 -3
  313. data/spec/graphql/static_validation/type_stack_spec.rb +10 -19
  314. data/spec/graphql/static_validation/validator_spec.rb +50 -2
  315. data/spec/graphql/subscriptions_spec.rb +27 -16
  316. data/spec/graphql/tracing/new_relic_tracing_spec.rb +16 -0
  317. data/spec/graphql/tracing/platform_tracing_spec.rb +59 -37
  318. data/spec/graphql/tracing/prometheus_tracing_spec.rb +3 -0
  319. data/spec/graphql/tracing/skylight_tracing_spec.rb +16 -0
  320. data/spec/graphql/types/iso_8601_date_time_spec.rb +29 -2
  321. data/spec/graphql/union_type_spec.rb +2 -2
  322. data/spec/graphql/upgrader/member_spec.rb +67 -0
  323. data/spec/{graphql → integration/mongoid/graphql}/relay/mongo_relation_connection_spec.rb +11 -22
  324. data/spec/integration/mongoid/spec_helper.rb +2 -0
  325. data/spec/{support → integration/mongoid}/star_trek/data.rb +0 -0
  326. data/spec/{support → integration/mongoid}/star_trek/schema.rb +56 -34
  327. data/spec/{support/star_wars → integration/rails}/data.rb +1 -0
  328. data/spec/{support → integration/rails/generators}/base_generator_test.rb +0 -0
  329. data/spec/{generators → integration/rails/generators}/graphql/enum_generator_spec.rb +0 -0
  330. data/spec/{generators → integration/rails/generators}/graphql/install_generator_spec.rb +1 -1
  331. data/spec/{generators → integration/rails/generators}/graphql/interface_generator_spec.rb +0 -0
  332. data/spec/{generators → integration/rails/generators}/graphql/loader_generator_spec.rb +0 -0
  333. data/spec/{generators → integration/rails/generators}/graphql/mutation_generator_spec.rb +0 -0
  334. data/spec/{generators → integration/rails/generators}/graphql/object_generator_spec.rb +0 -0
  335. data/spec/integration/rails/generators/graphql/scalar_generator_spec.rb +28 -0
  336. data/spec/{generators → integration/rails/generators}/graphql/union_generator_spec.rb +0 -0
  337. data/spec/integration/rails/graphql/input_object_type_spec.rb +364 -0
  338. data/spec/{graphql → integration/rails/graphql}/query/variables_spec.rb +7 -7
  339. data/spec/{graphql → integration/rails/graphql}/relay/array_connection_spec.rb +9 -9
  340. data/spec/{graphql → integration/rails/graphql}/relay/base_connection_spec.rb +11 -3
  341. data/spec/{graphql → integration/rails/graphql}/relay/connection_instrumentation_spec.rb +19 -22
  342. data/spec/{graphql → integration/rails/graphql}/relay/connection_resolve_spec.rb +16 -0
  343. data/spec/{graphql → integration/rails/graphql}/relay/connection_type_spec.rb +0 -0
  344. data/spec/{graphql → integration/rails/graphql}/relay/edge_spec.rb +0 -0
  345. data/spec/{graphql → integration/rails/graphql}/relay/mutation_spec.rb +48 -0
  346. data/spec/{graphql → integration/rails/graphql}/relay/node_spec.rb +0 -0
  347. data/spec/{graphql → integration/rails/graphql}/relay/page_info_spec.rb +22 -22
  348. data/spec/{graphql → integration/rails/graphql}/relay/range_add_spec.rb +4 -4
  349. data/spec/{graphql → integration/rails/graphql}/relay/relation_connection_spec.rb +56 -27
  350. data/spec/{graphql → integration/rails/graphql}/schema_spec.rb +15 -11
  351. data/spec/{graphql → integration/rails/graphql}/tracing/active_support_notifications_tracing_spec.rb +16 -9
  352. data/spec/integration/rails/spec_helper.rb +25 -0
  353. data/spec/integration/tmp/app/graphql/types/family_type.rb +9 -0
  354. data/spec/spec_helper.rb +23 -39
  355. data/spec/support/dummy/data.rb +20 -17
  356. data/spec/support/dummy/schema.rb +315 -305
  357. data/spec/support/error_bubbling_helpers.rb +23 -0
  358. data/spec/support/jazz.rb +213 -46
  359. data/spec/support/lazy_helpers.rb +69 -27
  360. data/spec/support/new_relic.rb +3 -0
  361. data/spec/support/skylight.rb +3 -0
  362. data/spec/support/star_wars/schema.rb +131 -81
  363. data/spec/support/static_validation_helpers.rb +9 -5
  364. metadata +418 -261
  365. data/lib/graphql/language/comments.rb +0 -45
  366. data/lib/graphql/static_validation/arguments_validator.rb +0 -50
  367. data/spec/graphql/schema/member/has_fields_spec.rb +0 -129
  368. data/spec/rails_dependency_sanity_spec.rb +0 -14
@@ -0,0 +1,364 @@
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
3
+
4
+ describe GraphQL::InputObjectType do
5
+ let(:input_object) { Dummy::DairyProductInput.graphql_definition }
6
+ it "has a description" do
7
+ assert(input_object.description)
8
+ end
9
+
10
+ it "has input fields" do
11
+ assert(input_object.input_fields["fatContent"])
12
+ end
13
+
14
+ describe "on a type unused by the schema" do
15
+ it "has input fields" do
16
+ UnreachedInputType = GraphQL::InputObjectType.define do
17
+ name 'UnreachedInputType'
18
+ description 'An input object type not directly used in the schema.'
19
+
20
+ input_field :field, types.String
21
+ end
22
+ assert(UnreachedInputType.input_fields['field'])
23
+ end
24
+ end
25
+
26
+ describe "input validation" do
27
+ it "Accepts anything that yields key-value pairs to #all?" do
28
+ values_obj = MinimumInputObject.new({"source" => "COW", "fatContent" => 0.4})
29
+ assert input_object.valid_isolated_input?(values_obj)
30
+ end
31
+
32
+ describe "validate_input with non-enumerable input" do
33
+ it "returns a valid result for MinimumInputObject" do
34
+ result = input_object.validate_isolated_input(MinimumInputObject.new({"source" => "COW", "fatContent" => 0.4}))
35
+ assert(result.valid?)
36
+ end
37
+
38
+ it "returns an invalid result for MinimumInvalidInputObject" do
39
+ invalid_input = MinimumInputObject.new({"source" => "KOALA", "fatContent" => 0.4})
40
+ result = input_object.validate_isolated_input(invalid_input)
41
+ assert(!result.valid?)
42
+ end
43
+ end
44
+
45
+ describe "validate_input with null" do
46
+ let(:schema) { GraphQL::Schema.from_definition(%|
47
+ type Query {
48
+ a: Int
49
+ }
50
+
51
+ input ExampleInputObject {
52
+ a: String
53
+ b: Int!
54
+ }
55
+ |) }
56
+ let(:input_type) { schema.types['ExampleInputObject'] }
57
+
58
+ it "returns an invalid result when value is null for non-null argument" do
59
+ invalid_input = MinimumInputObject.new({"a" => "Test", "b" => nil})
60
+ result = input_type.validate_isolated_input(invalid_input)
61
+ assert(!result.valid?)
62
+ end
63
+
64
+ it "returns valid result when value is null for nullable argument" do
65
+ invalid_input = MinimumInputObject.new({"a" => nil, "b" => 1})
66
+ result = input_type.validate_isolated_input(invalid_input)
67
+ assert(result.valid?)
68
+ end
69
+ end
70
+
71
+ describe "validate_input with enumerable input" do
72
+ describe "with good input" do
73
+ let(:input) do
74
+ {
75
+ "source" => "COW",
76
+ "fatContent" => 0.4
77
+ }
78
+ end
79
+ let(:result) { input_object.validate_isolated_input(input) }
80
+
81
+ it "returns a valid result" do
82
+ assert(result.valid?)
83
+ end
84
+ end
85
+
86
+ if ActionPack::VERSION::MAJOR > 3
87
+ describe "with a ActionController::Parameters" do
88
+ let(:input) do
89
+ ActionController::Parameters.new(
90
+ "source" => "COW",
91
+ "fatContent" => 0.4,
92
+ )
93
+ end
94
+ let(:result) { input_object.validate_isolated_input(input) }
95
+
96
+ it "returns a valid result" do
97
+ assert(result.valid?)
98
+ end
99
+ end
100
+ end
101
+
102
+ describe "with bad enum and float" do
103
+ let(:result) { input_object.validate_isolated_input({"source" => "KOALA", "fatContent" => "bad_num"}) }
104
+
105
+ it "returns an invalid result" do
106
+ assert(!result.valid?)
107
+ end
108
+
109
+ it "has problems with correct paths" do
110
+ paths = result.problems.map { |p| p["path"] }
111
+ assert(paths.include?(["source"]))
112
+ assert(paths.include?(["fatContent"]))
113
+ end
114
+
115
+ it "has correct problem explanation" do
116
+ expected = Dummy::DairyAnimal.graphql_definition.validate_isolated_input("KOALA").problems[0]["explanation"]
117
+
118
+ source_problem = result.problems.detect { |p| p["path"] == ["source"] }
119
+ actual = source_problem["explanation"]
120
+
121
+ assert_equal(expected, actual)
122
+ end
123
+ end
124
+
125
+ describe 'with a string as input' do
126
+ let(:result) { input_object.validate_isolated_input("just a string") }
127
+
128
+ it "returns an invalid result" do
129
+ assert(!result.valid?)
130
+ end
131
+
132
+ it "has problem with correct path" do
133
+ paths = result.problems.map { |p| p["path"] }
134
+ assert(paths.include?([]))
135
+ end
136
+
137
+ it "has correct problem explanation" do
138
+ assert(result.problems[0]["explanation"].include?("to be a key, value object"))
139
+ end
140
+ end
141
+
142
+ describe 'with an array as input' do
143
+ let(:result) { input_object.validate_isolated_input(["string array"]) }
144
+
145
+ it "returns an invalid result" do
146
+ assert(!result.valid?)
147
+ end
148
+
149
+ it "has problem with correct path" do
150
+ paths = result.problems.map { |p| p["path"] }
151
+ assert(paths.include?([]))
152
+ end
153
+
154
+ it "has correct problem explanation" do
155
+ assert(result.problems[0]["explanation"].include?("to be a key, value object"))
156
+ end
157
+ end
158
+
159
+ describe 'with a int as input' do
160
+ let(:result) { input_object.validate_isolated_input(10) }
161
+
162
+ it "returns an invalid result" do
163
+ assert(!result.valid?)
164
+ end
165
+
166
+ it "has problem with correct path" do
167
+ paths = result.problems.map { |p| p["path"] }
168
+ assert(paths.include?([]))
169
+ end
170
+
171
+ it "has correct problem explanation" do
172
+ assert(result.problems[0]["explanation"].include?("to be a key, value object"))
173
+ end
174
+ end
175
+
176
+ describe "with extra argument" do
177
+ let(:result) { input_object.validate_isolated_input({"source" => "COW", "fatContent" => 0.4, "isDelicious" => false}) }
178
+
179
+ it "returns an invalid result" do
180
+ assert(!result.valid?)
181
+ end
182
+
183
+ it "has problem with correct path" do
184
+ paths = result.problems.map { |p| p["path"] }
185
+ assert_equal([["isDelicious"]], paths)
186
+ end
187
+
188
+ it "has correct problem explanation" do
189
+ assert(result.problems[0]["explanation"].include?("Field is not defined"))
190
+ end
191
+ end
192
+
193
+ describe "list with one invalid element" do
194
+ let(:list_type) { GraphQL::ListType.new(of_type: Dummy::DairyProductInput.graphql_definition) }
195
+ let(:result) do
196
+ list_type.validate_isolated_input([
197
+ { "source" => "COW", "fatContent" => 0.4 },
198
+ { "source" => "KOALA", "fatContent" => 0.4 }
199
+ ])
200
+ end
201
+
202
+ it "returns an invalid result" do
203
+ assert(!result.valid?)
204
+ end
205
+
206
+ it "has one problem" do
207
+ assert_equal(result.problems.length, 1)
208
+ end
209
+
210
+ it "has problem with correct path" do
211
+ path = result.problems[0]["path"]
212
+ assert_equal(path, [1, "source"])
213
+ end
214
+
215
+ it "has problem with correct explanation" do
216
+ expected = Dummy::DairyAnimal.graphql_definition.validate_isolated_input("KOALA").problems[0]["explanation"]
217
+ actual = result.problems[0]["explanation"]
218
+ assert_equal(expected, actual)
219
+ end
220
+ end
221
+
222
+ describe 'with invalid name' do
223
+ it 'raises the correct error' do
224
+ assert_raises(GraphQL::InvalidNameError) do
225
+ InvalidInputTest = GraphQL::InputObjectType.define do
226
+ name "Some::Invalid Name"
227
+ end
228
+
229
+ # Force evaluation
230
+ InvalidInputTest.name
231
+ end
232
+ end
233
+ end
234
+ end
235
+ end
236
+
237
+ describe "coerce_result" do
238
+ it "omits unspecified arguments" do
239
+ result = input_object.coerce_isolated_result({fatContent: 0.3})
240
+ assert_equal ["fatContent"], result.keys
241
+ assert_equal 0.3, result["fatContent"]
242
+ end
243
+ end
244
+
245
+ describe "coercion of null inputs" do
246
+ let(:schema) { GraphQL::Schema.from_definition(%|
247
+ type Query {
248
+ a: Int
249
+ }
250
+
251
+ input ExampleInputObject {
252
+ a: String
253
+ b: Int!
254
+ c: String = "Default"
255
+ d: Boolean = false
256
+ }
257
+
258
+ input SecondLevelInputObject {
259
+ example: ExampleInputObject = {b: 42, d: true}
260
+ }
261
+ |) }
262
+ let(:input_type) { schema.types['ExampleInputObject'] }
263
+
264
+ it "null values are returned in coerced input" do
265
+ input = MinimumInputObject.new({"a" => "Test", "b" => nil,"c" => "Test"})
266
+ result = input_type.coerce_isolated_input(input)
267
+
268
+ assert_equal 'Test', result['a']
269
+
270
+ assert result.key?('b')
271
+ assert_nil result['b']
272
+
273
+ assert_equal "Test", result['c']
274
+ end
275
+
276
+ it "null values are preserved when argument has a default value" do
277
+ input = MinimumInputObject.new({"a" => "Test", "b" => 1, "c" => nil})
278
+ result = input_type.coerce_isolated_input(input)
279
+
280
+ assert_equal 'Test', result['a']
281
+ assert_equal 1, result['b']
282
+
283
+ assert result.key?('c')
284
+ assert_nil result['c']
285
+ end
286
+
287
+ it "omitted arguments are not returned" do
288
+ input = MinimumInputObject.new({"b" => 1, "c" => "Test"})
289
+ result = input_type.coerce_isolated_input(input)
290
+
291
+ assert !result.key?('a')
292
+ assert_equal 1, result['b']
293
+ assert_equal 'Test', result['c']
294
+ end
295
+
296
+ it "false default values are returned" do
297
+ input = MinimumInputObject.new({"b" => 1})
298
+ result = input_type.coerce_isolated_input(input)
299
+
300
+ assert_equal false, result['d']
301
+ end
302
+
303
+ it "merges defaults of nested input objects" do
304
+ result = schema.types['SecondLevelInputObject'].coerce_isolated_input({})
305
+ assert_equal 42, result['example']['b']
306
+ assert_equal "Default", result['example']['c']
307
+ assert_equal true, result['example']['d']
308
+ end
309
+ end
310
+
311
+ describe "when sent into a query" do
312
+ let(:variables) { {} }
313
+ let(:result) { Dummy::Schema.execute(query_string, variables: variables) }
314
+
315
+ describe "list inputs" do
316
+ let(:variables) { {"search" => [MinimumInputObject.new({"source" => "COW", "fatContent" => 0.4})]} }
317
+ let(:query_string) {%|
318
+ query getCheeses($search: [DairyProductInput]!){
319
+ sheep: searchDairy(product: [{source: SHEEP, fatContent: 0.1}]) {
320
+ ... cheeseFields
321
+ }
322
+ cow: searchDairy(product: $search) {
323
+ ... cheeseFields
324
+ }
325
+ }
326
+
327
+ fragment cheeseFields on Cheese {
328
+ flavor
329
+ }
330
+ |}
331
+
332
+ it "converts items to plain values" do
333
+ sheep_value = result["data"]["sheep"]["flavor"]
334
+ cow_value = result["data"]["cow"]["flavor"]
335
+ assert_equal("Manchego", sheep_value)
336
+ assert_equal("Brie", cow_value)
337
+ end
338
+ end
339
+
340
+ describe "scalar inputs" do
341
+ let(:query_string) {%|
342
+ {
343
+ cheese(id: 1.4) {
344
+ flavor
345
+ }
346
+ }
347
+ |}
348
+
349
+ it "converts them to the correct type" do
350
+ cheese_name = result["data"]["cheese"]["flavor"]
351
+ assert_equal("Brie", cheese_name)
352
+ end
353
+ end
354
+ end
355
+
356
+ describe "#dup" do
357
+ it "shallow-copies internal state" do
358
+ input_object_2 = input_object.dup
359
+ input_object_2.arguments["nonsense"] = GraphQL::Argument.define(name: "int", type: GraphQL::INT_TYPE)
360
+ assert_equal 5, input_object.arguments.size
361
+ assert_equal 6, input_object_2.arguments.size
362
+ end
363
+ end
364
+ end
@@ -69,21 +69,21 @@ describe GraphQL::Query::Variables do
69
69
  it "checks for string matches" do
70
70
  # These get merged into all the values above
71
71
  default_values = {
72
- "originDairy"=>"Sugar Hollow Dairy",
73
- "organic"=>false,
74
- "order_by"=>{"direction"=>"ASC"}
72
+ origin_dairy: "Sugar Hollow Dairy",
73
+ organic: false,
74
+ order_by: { direction: "ASC" },
75
75
  }
76
76
 
77
77
  expected_input_1 = {
78
- "source" => 1,
79
- "fatContent" => 0.99,
78
+ source: 1,
79
+ fat_content: 0.99,
80
80
  }.merge(default_values)
81
81
 
82
82
  assert_equal(expected_input_1, variables["dairy_product_1"].to_h)
83
83
 
84
84
  expected_input_2 = {
85
- "source" => :donkey,
86
- "fatContent" => 0.89,
85
+ source: :donkey,
86
+ fat_content: 0.89,
87
87
  }.merge(default_values)
88
88
  assert_equal(expected_input_2, variables["dairy_product_2"].to_h)
89
89
  end
@@ -43,8 +43,8 @@ describe GraphQL::Relay::ArrayConnection do
43
43
  assert_equal(2, number_of_ships)
44
44
  assert_equal(true, result["data"]["rebels"]["ships"]["pageInfo"]["hasNextPage"])
45
45
  assert_equal(false, result["data"]["rebels"]["ships"]["pageInfo"]["hasPreviousPage"])
46
- assert_equal("MQ==", result["data"]["rebels"]["ships"]["pageInfo"]["startCursor"])
47
- assert_equal("Mg==", result["data"]["rebels"]["ships"]["pageInfo"]["endCursor"])
46
+ assert_equal("MQ", result["data"]["rebels"]["ships"]["pageInfo"]["startCursor"])
47
+ assert_equal("Mg", result["data"]["rebels"]["ships"]["pageInfo"]["endCursor"])
48
48
 
49
49
  result = star_wars_query(query_string, "first" => 3)
50
50
  number_of_ships = get_names(result).length
@@ -55,14 +55,14 @@ describe GraphQL::Relay::ArrayConnection do
55
55
  result = star_wars_query(query_string, "first" => 2)
56
56
  assert_equal(true, result["data"]["rebels"]["ships"]["pageInfo"]["hasNextPage"])
57
57
  assert_equal(false, result["data"]["rebels"]["ships"]["pageInfo"]["hasPreviousPage"])
58
- assert_equal("MQ==", result["data"]["rebels"]["ships"]["pageInfo"]["startCursor"])
59
- assert_equal("Mg==", result["data"]["rebels"]["ships"]["pageInfo"]["endCursor"])
58
+ assert_equal("MQ", result["data"]["rebels"]["ships"]["pageInfo"]["startCursor"])
59
+ assert_equal("Mg", result["data"]["rebels"]["ships"]["pageInfo"]["endCursor"])
60
60
 
61
61
  result = star_wars_query(query_string, "first" => 100)
62
62
  assert_equal(false, result["data"]["rebels"]["ships"]["pageInfo"]["hasNextPage"])
63
63
  assert_equal(false, result["data"]["rebels"]["ships"]["pageInfo"]["hasPreviousPage"])
64
- assert_equal("MQ==", result["data"]["rebels"]["ships"]["pageInfo"]["startCursor"])
65
- assert_equal("NQ==", result["data"]["rebels"]["ships"]["pageInfo"]["endCursor"])
64
+ assert_equal("MQ", result["data"]["rebels"]["ships"]["pageInfo"]["startCursor"])
65
+ assert_equal("NQ", result["data"]["rebels"]["ships"]["pageInfo"]["endCursor"])
66
66
  end
67
67
 
68
68
  it "provides bidirectional_pagination" do
@@ -166,8 +166,8 @@ describe GraphQL::Relay::ArrayConnection do
166
166
 
167
167
  assert_equal(false, result["data"]["rebels"]["ships"]["pageInfo"]["hasNextPage"])
168
168
  assert_equal(false, result["data"]["rebels"]["ships"]["pageInfo"]["hasPreviousPage"])
169
- assert_equal("MQ==", result["data"]["rebels"]["ships"]["pageInfo"]["startCursor"])
170
- assert_equal("NQ==", result["data"]["rebels"]["ships"]["pageInfo"]["endCursor"])
169
+ assert_equal("MQ", result["data"]["rebels"]["ships"]["pageInfo"]["startCursor"])
170
+ assert_equal("NQ", result["data"]["rebels"]["ships"]["pageInfo"]["endCursor"])
171
171
  assert_equal(5, result["data"]["rebels"]["ships"]["edges"].length)
172
172
  end
173
173
 
@@ -217,7 +217,7 @@ describe GraphQL::Relay::ArrayConnection do
217
217
  assert_equal(["Yavin", "Echo Base"], get_names(result))
218
218
  assert_equal(false, get_page_info(result)["hasPreviousPage"], "hasPreviousPage is false when last is not specified")
219
219
 
220
- third_cursor = "Mw=="
220
+ third_cursor = "Mw"
221
221
  first_and_second_names = ["Yavin", "Echo Base"]
222
222
  result = star_wars_query(query_string, "last" => 100, "before" => third_cursor)
223
223
  assert_equal(first_and_second_names, get_names(result))
@@ -77,11 +77,11 @@ describe GraphQL::Relay::BaseConnection do
77
77
  assert_equal "Person/1", conn.decode("1/nosreP")
78
78
  end
79
79
 
80
- it "defaults to base64" do
80
+ it "defaults to base64 (urlsafe_base64 without padding)" do
81
81
  conn = GraphQL::Relay::BaseConnection.new([], {}, context: nil)
82
82
 
83
- assert_equal "UGVyc29uLzE=", conn.encode("Person/1")
84
- assert_equal "Person/1", conn.decode("UGVyc29uLzE=")
83
+ assert_equal "UGVyc29uLzE", conn.encode("Person/1")
84
+ assert_equal "Person/1", conn.decode("UGVyc29uLzE=") # can decode with padding
85
85
  end
86
86
 
87
87
  it "handles trimmed base64" do
@@ -89,5 +89,13 @@ describe GraphQL::Relay::BaseConnection do
89
89
 
90
90
  assert_equal "Person/1", conn.decode("UGVyc29uLzE")
91
91
  end
92
+
93
+ it "raises an execution error when an invalid cursor is given" do
94
+ conn = GraphQL::Relay::BaseConnection.new([], {}, context: nil)
95
+
96
+ assert_raises(GraphQL::ExecutionError) do
97
+ conn.decode("0")
98
+ end
99
+ end
92
100
  end
93
101
  end
@@ -11,11 +11,6 @@ describe GraphQL::Relay::ConnectionInstrumentation do
11
11
  assert_equal ["tests"], test_type.fields.keys
12
12
  end
13
13
 
14
- it "keeps a reference to the function" do
15
- conn_field = StarWars::Faction.graphql_definition.fields["shipsWithMaxPageSize"]
16
- assert_instance_of StarWars::ShipsWithMaxPageSize, conn_field.function
17
- end
18
-
19
14
  let(:build_schema) {
20
15
  test_type = nil
21
16
 
@@ -58,26 +53,28 @@ describe GraphQL::Relay::ConnectionInstrumentation do
58
53
  assert_instance_of GraphQL::Relay::ConnectionResolve, redefined_connection_field.resolve_proc
59
54
  end
60
55
 
61
- describe "after_built_ins instrumentation" do
62
- it "has access to connection objects" do
63
- query_str = <<-GRAPHQL
64
- {
65
- rebels {
66
- ships {
67
- pageInfo {
68
- __typename
56
+ # field instrumentation doesn't exist here
57
+ if !TESTING_INTERPRETER
58
+ describe "after_built_ins instrumentation" do
59
+ it "has access to connection objects" do
60
+ query_str = <<-GRAPHQL
61
+ {
62
+ rebels {
63
+ ships {
64
+ pageInfo {
65
+ __typename
66
+ }
69
67
  }
70
68
  }
71
69
  }
72
- }
73
- GRAPHQL
74
- ctx = { before_built_ins: [], after_built_ins: [] }
75
- star_wars_query(query_str, {}, context: ctx)
76
- # The second item is different here:
77
- # Before the object is wrapped in a connection, the instrumentation sees `Array`
78
- assert_equal ["StarWars::FactionRecord", "Array", "GraphQL::Relay::ArrayConnection"], ctx[:before_built_ins]
79
- # After the object is wrapped in a connection, it sees the connection object
80
- assert_equal ["StarWars::Faction", "StarWars::ShipConnectionWithParentType", "GraphQL::Types::Relay::PageInfo"], ctx[:after_built_ins]
70
+ GRAPHQL
71
+ ctx = { before_built_ins: [], after_built_ins: [] }
72
+ star_wars_query(query_str, {}, context: ctx)
73
+ # These are data classes, later they're wrapped with type proxies
74
+ assert_equal ["StarWars::FactionRecord", "GraphQL::Relay::ArrayConnection", "GraphQL::Relay::ArrayConnection"], ctx[:before_built_ins]
75
+ # After the object is wrapped in a connection, it sees the connection object
76
+ assert_equal ["StarWars::Faction", "StarWars::ShipConnectionWithParentType", "GraphQL::Types::Relay::PageInfo"], ctx[:after_built_ins]
77
+ end
81
78
  end
82
79
  end
83
80
  end
@@ -53,6 +53,22 @@ describe GraphQL::Relay::ConnectionResolve do
53
53
  end
54
54
  end
55
55
 
56
+ describe "when a resolver is used" do
57
+ it "returns the items with the correct parent" do
58
+ resolver_query_str = <<-GRAPHQL
59
+ {
60
+ rebels {
61
+ shipsByResolver {
62
+ parentClassName
63
+ }
64
+ }
65
+ }
66
+ GRAPHQL
67
+ result = star_wars_query(resolver_query_str)
68
+ assert_equal "StarWars::FactionRecord", result["data"]["rebels"]["shipsByResolver"]["parentClassName"]
69
+ end
70
+ end
71
+
56
72
  describe "when nil is returned" do
57
73
  it "becomes null" do
58
74
  result = star_wars_query(query_string, { "name" => "null" })
@@ -336,4 +336,52 @@ describe GraphQL::Relay::Mutation do
336
336
  assert_equal(expected, result)
337
337
  end
338
338
  end
339
+
340
+ describe 'supports new input object definition with old mutation definition' do
341
+ let(:some_attribute_type) do
342
+ Class.new(GraphQL::Schema::InputObject) do
343
+ graphql_name 'SomeAttribute'
344
+ argument :something, String, required: false
345
+ end
346
+ end
347
+
348
+ let(:do_something_mutation) do
349
+ some_attribute = some_attribute_type
350
+
351
+ GraphQL::Relay::Mutation.define do
352
+ name 'DoSomethingMutation'
353
+ input_field :someAttributes, types[some_attribute.graphql_definition]
354
+
355
+ return_field :anything, types.String
356
+
357
+ resolve ->(_obj, inputs, _ctx) {
358
+ {
359
+ anything: inputs.to_h['someAttributes'][0].class.to_s
360
+ }
361
+ }
362
+ end
363
+ end
364
+
365
+ let(:mutation_type) do
366
+ do_something = do_something_mutation
367
+
368
+ Class.new(GraphQL::Schema::Object) do
369
+ graphql_name 'Mutation'
370
+ field :doSomething, field: do_something.field
371
+ end
372
+ end
373
+
374
+ let(:schema) do
375
+ mutation = mutation_type
376
+
377
+ Class.new(GraphQL::Schema) do
378
+ mutation mutation
379
+ end
380
+ end
381
+
382
+ it 'converts to hash the whole input' do
383
+ result = schema.execute('mutation { doSomething(input: {someAttributes: [{something: "string"}]}) { anything } }')
384
+ assert_equal 'Hash', result['data']['doSomething']['anything']
385
+ end
386
+ end
339
387
  end