graphql 1.8.7 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (368) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install_generator.rb +2 -1
  3. data/lib/generators/graphql/scalar_generator.rb +20 -0
  4. data/lib/generators/graphql/templates/base_scalar.erb +4 -0
  5. data/lib/generators/graphql/templates/scalar.erb +13 -0
  6. data/lib/graphql/analysis/ast/analyzer.rb +62 -0
  7. data/lib/graphql/analysis/ast/field_usage.rb +28 -0
  8. data/lib/graphql/analysis/ast/max_query_complexity.rb +23 -0
  9. data/lib/graphql/analysis/ast/max_query_depth.rb +18 -0
  10. data/lib/graphql/analysis/ast/query_complexity.rb +114 -0
  11. data/lib/graphql/analysis/ast/query_depth.rb +66 -0
  12. data/lib/graphql/analysis/ast/visitor.rb +255 -0
  13. data/lib/graphql/analysis/ast.rb +82 -0
  14. data/lib/graphql/analysis.rb +1 -0
  15. data/lib/graphql/argument.rb +5 -0
  16. data/lib/graphql/authorization.rb +1 -0
  17. data/lib/graphql/backwards_compatibility.rb +1 -1
  18. data/lib/graphql/base_type.rb +1 -1
  19. data/lib/graphql/compatibility/execution_specification/specification_schema.rb +1 -2
  20. data/lib/graphql/compatibility/schema_parser_specification.rb +2 -6
  21. data/lib/graphql/dig.rb +19 -0
  22. data/lib/graphql/directive/include_directive.rb +1 -7
  23. data/lib/graphql/directive/skip_directive.rb +1 -8
  24. data/lib/graphql/directive.rb +13 -1
  25. data/lib/graphql/enum_type.rb +8 -0
  26. data/lib/graphql/execution/execute.rb +36 -17
  27. data/lib/graphql/execution/instrumentation.rb +2 -0
  28. data/lib/graphql/execution/interpreter/execution_errors.rb +29 -0
  29. data/lib/graphql/execution/interpreter/hash_response.rb +46 -0
  30. data/lib/graphql/execution/interpreter/resolve.rb +58 -0
  31. data/lib/graphql/execution/interpreter/runtime.rb +597 -0
  32. data/lib/graphql/execution/interpreter.rb +99 -0
  33. data/lib/graphql/execution/lazy.rb +8 -1
  34. data/lib/graphql/execution/lookahead.rb +351 -0
  35. data/lib/graphql/execution/multiplex.rb +37 -29
  36. data/lib/graphql/execution.rb +2 -0
  37. data/lib/graphql/execution_error.rb +1 -1
  38. data/lib/graphql/field.rb +1 -7
  39. data/lib/graphql/integer_encoding_error.rb +12 -0
  40. data/lib/graphql/internal_representation/rewrite.rb +127 -142
  41. data/lib/graphql/introspection/dynamic_fields.rb +8 -2
  42. data/lib/graphql/introspection/entry_points.rb +11 -6
  43. data/lib/graphql/introspection/enum_value_type.rb +4 -0
  44. data/lib/graphql/introspection/schema_type.rb +7 -2
  45. data/lib/graphql/introspection/type_type.rb +9 -5
  46. data/lib/graphql/invalid_null_error.rb +1 -1
  47. data/lib/graphql/language/block_string.rb +37 -0
  48. data/lib/graphql/language/document_from_schema_definition.rb +10 -7
  49. data/lib/graphql/language/lexer.rb +55 -36
  50. data/lib/graphql/language/lexer.rl +8 -3
  51. data/lib/graphql/language/nodes.rb +440 -362
  52. data/lib/graphql/language/parser.rb +56 -56
  53. data/lib/graphql/language/parser.y +12 -12
  54. data/lib/graphql/language/printer.rb +2 -2
  55. data/lib/graphql/language/visitor.rb +158 -15
  56. data/lib/graphql/language.rb +0 -1
  57. data/lib/graphql/literal_validation_error.rb +6 -0
  58. data/lib/graphql/query/arguments.rb +3 -2
  59. data/lib/graphql/query/arguments_cache.rb +1 -1
  60. data/lib/graphql/query/context.rb +14 -5
  61. data/lib/graphql/query/executor.rb +1 -1
  62. data/lib/graphql/query/result.rb +1 -1
  63. data/lib/graphql/query/validation_pipeline.rb +35 -11
  64. data/lib/graphql/query/variable_validation_error.rb +10 -1
  65. data/lib/graphql/query.rb +16 -2
  66. data/lib/graphql/relay/base_connection.rb +2 -0
  67. data/lib/graphql/relay/connection_instrumentation.rb +3 -1
  68. data/lib/graphql/relay/connection_resolve.rb +1 -1
  69. data/lib/graphql/relay/node.rb +2 -28
  70. data/lib/graphql/relay/relation_connection.rb +1 -1
  71. data/lib/graphql/schema/argument.rb +13 -5
  72. data/lib/graphql/schema/base_64_encoder.rb +4 -4
  73. data/lib/graphql/schema/build_from_definition.rb +2 -4
  74. data/lib/graphql/schema/default_type_error.rb +1 -1
  75. data/lib/graphql/schema/directive/feature.rb +66 -0
  76. data/lib/graphql/schema/directive/include.rb +25 -0
  77. data/lib/graphql/schema/directive/skip.rb +25 -0
  78. data/lib/graphql/schema/directive/transform.rb +48 -0
  79. data/lib/graphql/schema/directive.rb +103 -0
  80. data/lib/graphql/schema/enum_value.rb +3 -2
  81. data/lib/graphql/schema/field/connection_extension.rb +50 -0
  82. data/lib/graphql/schema/field/scope_extension.rb +18 -0
  83. data/lib/graphql/schema/field.rb +273 -64
  84. data/lib/graphql/schema/field_extension.rb +69 -0
  85. data/lib/graphql/schema/input_object.rb +16 -8
  86. data/lib/graphql/schema/interface.rb +1 -0
  87. data/lib/graphql/schema/loader.rb +22 -16
  88. data/lib/graphql/schema/member/base_dsl_methods.rb +8 -2
  89. data/lib/graphql/schema/member/build_type.rb +33 -1
  90. data/lib/graphql/schema/member/has_arguments.rb +6 -2
  91. data/lib/graphql/schema/member/has_fields.rb +18 -70
  92. data/lib/graphql/schema/member/has_path.rb +25 -0
  93. data/lib/graphql/schema/member/instrumentation.rb +10 -7
  94. data/lib/graphql/schema/member.rb +2 -0
  95. data/lib/graphql/schema/mutation.rb +6 -48
  96. data/lib/graphql/schema/non_null.rb +5 -1
  97. data/lib/graphql/schema/object.rb +18 -4
  98. data/lib/graphql/schema/printer.rb +1 -1
  99. data/lib/graphql/schema/relay_classic_mutation.rb +42 -9
  100. data/lib/graphql/schema/resolver/has_payload_type.rb +65 -0
  101. data/lib/graphql/schema/resolver.rb +45 -20
  102. data/lib/graphql/schema/subscription.rb +97 -0
  103. data/lib/graphql/schema/traversal.rb +11 -7
  104. data/lib/graphql/schema.rb +186 -38
  105. data/lib/graphql/static_validation/all_rules.rb +3 -2
  106. data/lib/graphql/static_validation/base_visitor.rb +199 -0
  107. data/lib/graphql/static_validation/default_visitor.rb +15 -0
  108. data/lib/graphql/static_validation/definition_dependencies.rb +62 -68
  109. data/lib/graphql/static_validation/{message.rb → error.rb} +11 -11
  110. data/lib/graphql/static_validation/interpreter_visitor.rb +14 -0
  111. data/lib/graphql/static_validation/literal_validator.rb +54 -11
  112. data/lib/graphql/static_validation/no_validate_visitor.rb +10 -0
  113. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +87 -16
  114. data/lib/graphql/static_validation/rules/argument_literals_are_compatible_error.rb +31 -0
  115. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +11 -11
  116. data/lib/graphql/static_validation/rules/argument_names_are_unique_error.rb +30 -0
  117. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +52 -8
  118. data/lib/graphql/static_validation/rules/arguments_are_defined_error.rb +35 -0
  119. data/lib/graphql/static_validation/rules/directives_are_defined.rb +12 -15
  120. data/lib/graphql/static_validation/rules/directives_are_defined_error.rb +29 -0
  121. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +19 -14
  122. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations_error.rb +31 -0
  123. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +17 -19
  124. data/lib/graphql/static_validation/rules/fields_are_defined_on_type_error.rb +32 -0
  125. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +30 -14
  126. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections_error.rb +31 -0
  127. data/lib/graphql/static_validation/rules/fields_will_merge.rb +356 -29
  128. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +32 -0
  129. data/lib/graphql/static_validation/rules/fragment_names_are_unique.rb +20 -13
  130. data/lib/graphql/static_validation/rules/fragment_names_are_unique_error.rb +29 -0
  131. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +37 -29
  132. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb +35 -0
  133. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +25 -17
  134. data/lib/graphql/static_validation/rules/fragment_types_exist_error.rb +29 -0
  135. data/lib/graphql/static_validation/rules/fragments_are_finite.rb +12 -10
  136. data/lib/graphql/static_validation/rules/fragments_are_finite_error.rb +29 -0
  137. data/lib/graphql/static_validation/rules/fragments_are_named.rb +7 -11
  138. data/lib/graphql/static_validation/rules/fragments_are_named_error.rb +26 -0
  139. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +16 -16
  140. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types_error.rb +30 -0
  141. data/lib/graphql/static_validation/rules/fragments_are_used.rb +21 -14
  142. data/lib/graphql/static_validation/rules/fragments_are_used_error.rb +29 -0
  143. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +10 -14
  144. data/lib/graphql/static_validation/rules/mutation_root_exists_error.rb +26 -0
  145. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +30 -30
  146. data/lib/graphql/static_validation/rules/no_definitions_are_present_error.rb +25 -0
  147. data/lib/graphql/static_validation/rules/operation_names_are_valid.rb +25 -17
  148. data/lib/graphql/static_validation/rules/operation_names_are_valid_error.rb +28 -0
  149. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +17 -18
  150. data/lib/graphql/static_validation/rules/required_arguments_are_present_error.rb +35 -0
  151. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +47 -0
  152. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present_error.rb +35 -0
  153. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +10 -14
  154. data/lib/graphql/static_validation/rules/subscription_root_exists_error.rb +26 -0
  155. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +28 -17
  156. data/lib/graphql/static_validation/rules/unique_directives_per_location_error.rb +29 -0
  157. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +35 -27
  158. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed_error.rb +39 -0
  159. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +15 -14
  160. data/lib/graphql/static_validation/rules/variable_names_are_unique_error.rb +29 -0
  161. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +41 -30
  162. data/lib/graphql/static_validation/rules/variable_usages_are_allowed_error.rb +38 -0
  163. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +18 -14
  164. data/lib/graphql/static_validation/rules/variables_are_input_types_error.rb +32 -0
  165. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +73 -65
  166. data/lib/graphql/static_validation/rules/variables_are_used_and_defined_error.rb +37 -0
  167. data/lib/graphql/static_validation/validation_context.rb +8 -51
  168. data/lib/graphql/static_validation/validator.rb +23 -15
  169. data/lib/graphql/static_validation.rb +5 -3
  170. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +21 -2
  171. data/lib/graphql/subscriptions/event.rb +28 -5
  172. data/lib/graphql/subscriptions/subscription_root.rb +66 -0
  173. data/lib/graphql/subscriptions.rb +16 -2
  174. data/lib/graphql/tracing/active_support_notifications_tracing.rb +0 -1
  175. data/lib/graphql/tracing/appsignal_tracing.rb +1 -1
  176. data/lib/graphql/tracing/data_dog_tracing.rb +1 -1
  177. data/lib/graphql/tracing/new_relic_tracing.rb +3 -3
  178. data/lib/graphql/tracing/platform_tracing.rb +17 -1
  179. data/lib/graphql/tracing/prometheus_tracing.rb +1 -1
  180. data/lib/graphql/tracing/scout_tracing.rb +1 -1
  181. data/lib/graphql/tracing/skylight_tracing.rb +3 -3
  182. data/lib/graphql/tracing.rb +8 -8
  183. data/lib/graphql/types/float.rb +1 -1
  184. data/lib/graphql/types/int.rb +11 -2
  185. data/lib/graphql/types/iso_8601_date_time.rb +15 -1
  186. data/lib/graphql/types/relay/base_connection.rb +15 -1
  187. data/lib/graphql/types/relay/node.rb +0 -1
  188. data/lib/graphql/types/relay/node_field.rb +43 -0
  189. data/lib/graphql/types/relay/nodes_field.rb +45 -0
  190. data/lib/graphql/types/relay.rb +2 -0
  191. data/lib/graphql/unauthorized_error.rb +4 -0
  192. data/lib/graphql/unauthorized_field_error.rb +23 -0
  193. data/lib/graphql/upgrader/member.rb +5 -0
  194. data/lib/graphql/version.rb +1 -1
  195. data/lib/graphql.rb +6 -1
  196. data/readme.md +7 -7
  197. data/spec/dummy/Gemfile +1 -1
  198. data/spec/dummy/Gemfile.lock +157 -0
  199. data/spec/dummy/app/channels/graphql_channel.rb +22 -11
  200. data/spec/dummy/config/locales/en.yml +1 -1
  201. data/spec/dummy/log/test.log +199 -0
  202. data/spec/dummy/test/test_helper.rb +1 -0
  203. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4w/4wzXRZrAkwKdgYaSE0pid5eB-fer8vSfSku_NPg4rMA.cache +0 -0
  204. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7I/7IHVBiJT06QSpgLpLoJIxboQ0B-D_tMTxsvoezBTV3Q.cache +1 -0
  205. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8w/8wY_SKagj8wHuwGNAAf6JnQ8joMbC6cEYpHrTAI8Urc.cache +1 -0
  206. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/AK/AKzz1u6bGb4auXcrObA_g5LL-oV0ejNGa448AgAi_WQ.cache +1 -0
  207. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ET/ETW4uxvaYpruL8y6_ZptUH82ZowMaHIqvg5WexBFdEM.cache +3 -0
  208. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F1/F1TWpjjyA56k9Z90n5B3xRn7DUdGjX73QCkYC6k07JQ.cache +0 -0
  209. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +2 -0
  210. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +2 -0
  211. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ms/MsKSimH_UCB-H1tLvDABDHuvGciuoW6kVqQWDrXU5FQ.cache +0 -0
  212. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Mt/Mtci-Kim50aPOmeClD4AIicKn1d1WJ0n454IjSd94sk.cache +0 -0
  213. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QH/QHt3Tc1Y6M66Oo_pDuMyWrQNs4Pp3SMeZR5K1wJj2Ts.cache +1 -0
  214. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/XU/XU4k1OXnfMils5SrirorPvDSyDSqiOWLZNtmAH1HH8k.cache +0 -0
  215. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ZI/ZIof7mZxWWCnraIFOCuV6a8QRWzKJXJnx2Xd7C0ZyX0.cache +1 -0
  216. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cG/cGc_puuPS5pZKgUcy1Y_i1L6jl5UtsiIrMH59rTzR6c.cache +3 -0
  217. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/df/dfro_B6bx3KP1Go-7jEOqqZ2j4hVRseXIc3es9PKQno.cache +1 -0
  218. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jO/jO1DfbqnG0mTULsjJJANc3fefrG2zt7DIMmcptMT628.cache +1 -0
  219. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pE/pE7gO6pQ-z187Swb4hT554wmqsq-cNzgPWLrCz-LQQQ.cache +0 -0
  220. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/r9/r9iU1l58a6rxkZSW5RSC52_tD-_UQuHxoMVnkfJ7Mhs.cache +1 -0
  221. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xi/xitPPFfPIyDMpaznV0sBBcw8eSCV8PJcLLWin78sCgE.cache +0 -0
  222. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  223. data/spec/graphql/analysis/analyze_query_spec.rb +1 -1
  224. data/spec/graphql/analysis/ast/field_usage_spec.rb +51 -0
  225. data/spec/graphql/analysis/ast/max_query_complexity_spec.rb +120 -0
  226. data/spec/graphql/analysis/ast/max_query_depth_spec.rb +114 -0
  227. data/spec/graphql/analysis/ast/query_complexity_spec.rb +299 -0
  228. data/spec/graphql/analysis/ast/query_depth_spec.rb +108 -0
  229. data/spec/graphql/analysis/ast_spec.rb +269 -0
  230. data/spec/graphql/authorization_spec.rb +120 -23
  231. data/spec/graphql/base_type_spec.rb +6 -4
  232. data/spec/graphql/enum_type_spec.rb +6 -1
  233. data/spec/graphql/execution/execute_spec.rb +9 -9
  234. data/spec/graphql/execution/instrumentation_spec.rb +19 -0
  235. data/spec/graphql/execution/interpreter_spec.rb +485 -0
  236. data/spec/graphql/execution/lazy_spec.rb +67 -1
  237. data/spec/graphql/execution/lookahead_spec.rb +363 -0
  238. data/spec/graphql/execution/multiplex_spec.rb +31 -3
  239. data/spec/graphql/execution/typecast_spec.rb +20 -20
  240. data/spec/graphql/execution_error_spec.rb +110 -96
  241. data/spec/graphql/field_spec.rb +1 -1
  242. data/spec/graphql/input_object_type_spec.rb +13 -352
  243. data/spec/graphql/int_type_spec.rb +19 -0
  244. data/spec/graphql/interface_type_spec.rb +4 -4
  245. data/spec/graphql/internal_representation/rewrite_spec.rb +2 -0
  246. data/spec/graphql/introspection/input_value_type_spec.rb +1 -1
  247. data/spec/graphql/introspection/type_type_spec.rb +1 -2
  248. data/spec/graphql/language/document_from_schema_definition_spec.rb +2 -2
  249. data/spec/graphql/language/lexer_spec.rb +72 -3
  250. data/spec/graphql/language/nodes_spec.rb +20 -0
  251. data/spec/graphql/language/printer_spec.rb +18 -6
  252. data/spec/graphql/language/visitor_spec.rb +320 -14
  253. data/spec/graphql/non_null_type_spec.rb +1 -1
  254. data/spec/graphql/object_type_spec.rb +32 -27
  255. data/spec/graphql/query/arguments_spec.rb +21 -0
  256. data/spec/graphql/query/context_spec.rb +28 -0
  257. data/spec/graphql/query/executor_spec.rb +40 -36
  258. data/spec/graphql/query_spec.rb +12 -6
  259. data/spec/graphql/schema/argument_spec.rb +35 -1
  260. data/spec/graphql/schema/build_from_definition_spec.rb +144 -29
  261. data/spec/graphql/schema/catchall_middleware_spec.rb +16 -15
  262. data/spec/graphql/schema/directive/feature_spec.rb +81 -0
  263. data/spec/graphql/schema/directive/transform_spec.rb +39 -0
  264. data/spec/graphql/schema/enum_spec.rb +12 -3
  265. data/spec/graphql/schema/enum_value_spec.rb +11 -0
  266. data/spec/graphql/schema/field_extension_spec.rb +115 -0
  267. data/spec/graphql/schema/field_spec.rb +47 -7
  268. data/spec/graphql/schema/input_object_spec.rb +95 -0
  269. data/spec/graphql/schema/instrumentation_spec.rb +3 -0
  270. data/spec/graphql/schema/interface_spec.rb +8 -2
  271. data/spec/graphql/schema/introspection_system_spec.rb +9 -1
  272. data/spec/graphql/schema/loader_spec.rb +5 -0
  273. data/spec/graphql/schema/member/accepts_definition_spec.rb +4 -0
  274. data/spec/graphql/schema/member/build_type_spec.rb +46 -0
  275. data/spec/graphql/schema/member/scoped_spec.rb +19 -3
  276. data/spec/graphql/schema/mutation_spec.rb +5 -3
  277. data/spec/graphql/schema/object_spec.rb +9 -1
  278. data/spec/graphql/schema/printer_spec.rb +255 -93
  279. data/spec/graphql/schema/relay_classic_mutation_spec.rb +133 -0
  280. data/spec/graphql/schema/resolver_spec.rb +173 -9
  281. data/spec/graphql/schema/scalar_spec.rb +6 -0
  282. data/spec/graphql/schema/subscription_spec.rb +416 -0
  283. data/spec/graphql/schema/traversal_spec.rb +10 -10
  284. data/spec/graphql/schema/type_expression_spec.rb +2 -2
  285. data/spec/graphql/schema/union_spec.rb +7 -0
  286. data/spec/graphql/schema/validation_spec.rb +1 -1
  287. data/spec/graphql/schema/warden_spec.rb +145 -88
  288. data/spec/graphql/static_validation/rules/argument_literals_are_compatible_spec.rb +213 -73
  289. data/spec/graphql/static_validation/rules/argument_names_are_unique_spec.rb +2 -2
  290. data/spec/graphql/static_validation/rules/arguments_are_defined_spec.rb +72 -29
  291. data/spec/graphql/static_validation/rules/directives_are_defined_spec.rb +4 -2
  292. data/spec/graphql/static_validation/rules/directives_are_in_valid_locations_spec.rb +4 -2
  293. data/spec/graphql/static_validation/rules/fields_are_defined_on_type_spec.rb +10 -5
  294. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +10 -5
  295. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +131 -5
  296. data/spec/graphql/static_validation/rules/fragment_names_are_unique_spec.rb +2 -1
  297. data/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb +6 -3
  298. data/spec/graphql/static_validation/rules/fragment_types_exist_spec.rb +4 -2
  299. data/spec/graphql/static_validation/rules/fragments_are_finite_spec.rb +4 -2
  300. data/spec/graphql/static_validation/rules/fragments_are_named_spec.rb +2 -1
  301. data/spec/graphql/static_validation/rules/fragments_are_on_composite_types_spec.rb +6 -3
  302. data/spec/graphql/static_validation/rules/fragments_are_used_spec.rb +22 -2
  303. data/spec/graphql/static_validation/rules/mutation_root_exists_spec.rb +2 -1
  304. data/spec/graphql/static_validation/rules/operation_names_are_valid_spec.rb +6 -3
  305. data/spec/graphql/static_validation/rules/required_arguments_are_present_spec.rb +13 -4
  306. data/spec/graphql/static_validation/rules/required_input_object_attributes_are_present_spec.rb +58 -0
  307. data/spec/graphql/static_validation/rules/subscription_root_exists_spec.rb +2 -1
  308. data/spec/graphql/static_validation/rules/unique_directives_per_location_spec.rb +14 -7
  309. data/spec/graphql/static_validation/rules/variable_default_values_are_correctly_typed_spec.rb +14 -7
  310. data/spec/graphql/static_validation/rules/variable_usages_are_allowed_spec.rb +8 -4
  311. data/spec/graphql/static_validation/rules/variables_are_input_types_spec.rb +8 -4
  312. data/spec/graphql/static_validation/rules/variables_are_used_and_defined_spec.rb +23 -3
  313. data/spec/graphql/static_validation/type_stack_spec.rb +10 -19
  314. data/spec/graphql/static_validation/validator_spec.rb +50 -2
  315. data/spec/graphql/subscriptions_spec.rb +27 -16
  316. data/spec/graphql/tracing/new_relic_tracing_spec.rb +16 -0
  317. data/spec/graphql/tracing/platform_tracing_spec.rb +59 -37
  318. data/spec/graphql/tracing/prometheus_tracing_spec.rb +3 -0
  319. data/spec/graphql/tracing/skylight_tracing_spec.rb +16 -0
  320. data/spec/graphql/types/iso_8601_date_time_spec.rb +29 -2
  321. data/spec/graphql/union_type_spec.rb +2 -2
  322. data/spec/graphql/upgrader/member_spec.rb +67 -0
  323. data/spec/{graphql → integration/mongoid/graphql}/relay/mongo_relation_connection_spec.rb +11 -22
  324. data/spec/integration/mongoid/spec_helper.rb +2 -0
  325. data/spec/{support → integration/mongoid}/star_trek/data.rb +0 -0
  326. data/spec/{support → integration/mongoid}/star_trek/schema.rb +56 -34
  327. data/spec/{support/star_wars → integration/rails}/data.rb +1 -0
  328. data/spec/{support → integration/rails/generators}/base_generator_test.rb +0 -0
  329. data/spec/{generators → integration/rails/generators}/graphql/enum_generator_spec.rb +0 -0
  330. data/spec/{generators → integration/rails/generators}/graphql/install_generator_spec.rb +1 -1
  331. data/spec/{generators → integration/rails/generators}/graphql/interface_generator_spec.rb +0 -0
  332. data/spec/{generators → integration/rails/generators}/graphql/loader_generator_spec.rb +0 -0
  333. data/spec/{generators → integration/rails/generators}/graphql/mutation_generator_spec.rb +0 -0
  334. data/spec/{generators → integration/rails/generators}/graphql/object_generator_spec.rb +0 -0
  335. data/spec/integration/rails/generators/graphql/scalar_generator_spec.rb +28 -0
  336. data/spec/{generators → integration/rails/generators}/graphql/union_generator_spec.rb +0 -0
  337. data/spec/integration/rails/graphql/input_object_type_spec.rb +364 -0
  338. data/spec/{graphql → integration/rails/graphql}/query/variables_spec.rb +7 -7
  339. data/spec/{graphql → integration/rails/graphql}/relay/array_connection_spec.rb +9 -9
  340. data/spec/{graphql → integration/rails/graphql}/relay/base_connection_spec.rb +11 -3
  341. data/spec/{graphql → integration/rails/graphql}/relay/connection_instrumentation_spec.rb +19 -22
  342. data/spec/{graphql → integration/rails/graphql}/relay/connection_resolve_spec.rb +16 -0
  343. data/spec/{graphql → integration/rails/graphql}/relay/connection_type_spec.rb +0 -0
  344. data/spec/{graphql → integration/rails/graphql}/relay/edge_spec.rb +0 -0
  345. data/spec/{graphql → integration/rails/graphql}/relay/mutation_spec.rb +48 -0
  346. data/spec/{graphql → integration/rails/graphql}/relay/node_spec.rb +0 -0
  347. data/spec/{graphql → integration/rails/graphql}/relay/page_info_spec.rb +22 -22
  348. data/spec/{graphql → integration/rails/graphql}/relay/range_add_spec.rb +4 -4
  349. data/spec/{graphql → integration/rails/graphql}/relay/relation_connection_spec.rb +56 -27
  350. data/spec/{graphql → integration/rails/graphql}/schema_spec.rb +15 -11
  351. data/spec/{graphql → integration/rails/graphql}/tracing/active_support_notifications_tracing_spec.rb +16 -9
  352. data/spec/integration/rails/spec_helper.rb +25 -0
  353. data/spec/integration/tmp/app/graphql/types/family_type.rb +9 -0
  354. data/spec/spec_helper.rb +23 -39
  355. data/spec/support/dummy/data.rb +20 -17
  356. data/spec/support/dummy/schema.rb +315 -305
  357. data/spec/support/error_bubbling_helpers.rb +23 -0
  358. data/spec/support/jazz.rb +213 -46
  359. data/spec/support/lazy_helpers.rb +69 -27
  360. data/spec/support/new_relic.rb +3 -0
  361. data/spec/support/skylight.rb +3 -0
  362. data/spec/support/star_wars/schema.rb +131 -81
  363. data/spec/support/static_validation_helpers.rb +9 -5
  364. metadata +418 -261
  365. data/lib/graphql/language/comments.rb +0 -45
  366. data/lib/graphql/static_validation/arguments_validator.rb +0 -50
  367. data/spec/graphql/schema/member/has_fields_spec.rb +0 -129
  368. data/spec/rails_dependency_sanity_spec.rb +0 -14
@@ -124,7 +124,9 @@ describe GraphQL::InternalRepresentation::Rewrite do
124
124
 
125
125
  nut_selections = plant_selection.typed_children[schema.types["Nut"]]
126
126
  # `... on Tree`, `... on Nut`, and `NutFields`, but not `... on Fruit { ... on Tree }`
127
+
127
128
  assert_equal 3, nut_selections["leafType"].ast_nodes.size
129
+
128
130
  # Multi-level merging when including fragments:
129
131
  habitats_selections = nut_selections["habitats"].typed_children[schema.types["Habitat"]]
130
132
  assert_equal ["averageWeight", "seasons"], habitats_selections.keys
@@ -40,7 +40,7 @@ describe GraphQL::Introspection::InputValueType do
40
40
  ]
41
41
  }
42
42
  }}
43
- assert_equal(expected, result)
43
+ assert_equal(expected, result.to_h)
44
44
  end
45
45
 
46
46
  let(:cheese_type) {
@@ -144,10 +144,9 @@ describe GraphQL::Introspection::TypeType do
144
144
  }
145
145
  }
146
146
  GRAPHQL
147
-
148
147
  type_result = res["data"]["__schema"]["types"].find { |t| t["name"] == "Faction" }
149
148
  field_result = type_result["fields"].find { |f| f["name"] == "bases" }
150
- all_arg_names = ["first", "after", "last", "before", "nameIncludes"]
149
+ all_arg_names = ["after", "before", "first", "last", "nameIncludes", "complexOrder"]
151
150
  returned_arg_names = field_result["args"].map { |a| a["name"] }
152
151
  assert_equal all_arg_names, returned_arg_names
153
152
  end
@@ -433,7 +433,7 @@ describe GraphQL::Language::DocumentFromSchemaDefinition do
433
433
  }
434
434
 
435
435
  # Represents signed double-precision fractional values as specified by [IEEE
436
- # 754](http://en.wikipedia.org/wiki/IEEE_floating_point).
436
+ # 754](https://en.wikipedia.org/wiki/IEEE_floating_point).
437
437
  scalar Float
438
438
 
439
439
  # Represents a unique identifier that is Base64 obfuscated. It is often used to
@@ -698,7 +698,7 @@ describe GraphQL::Language::DocumentFromSchemaDefinition do
698
698
  }
699
699
 
700
700
  # Represents signed double-precision fractional values as specified by [IEEE
701
- # 754](http://en.wikipedia.org/wiki/IEEE_floating_point).
701
+ # 754](https://en.wikipedia.org/wiki/IEEE_floating_point).
702
702
  scalar Float
703
703
 
704
704
  # Represents a unique identifier that is Base64 obfuscated. It is often used to
@@ -26,12 +26,32 @@ describe GraphQL::Language::Lexer do
26
26
  assert_equal tokens[0], tokens[1].prev_token
27
27
  end
28
28
 
29
+ it "allows escaped quotes in strings" do
30
+ tokens = subject.tokenize('"a\\"b""c"')
31
+ assert_equal 'a"b', tokens[0].value
32
+ assert_equal 'c', tokens[1].value
33
+ end
34
+
29
35
  describe "block strings" do
30
- let(:query_string) { %|{ a(b: """\nc\n d\n""")}|}
36
+ let(:query_string) { %|{ a(b: """\nc\n \\""" d\n""" """""e""""")}|}
31
37
 
32
38
  it "tokenizes them" do
33
- str_token = tokens[5]
34
- assert_equal "c\n d", str_token.value
39
+ assert_equal "c\n \"\"\" d", tokens[5].value
40
+ assert_equal "\"\"e\"\"", tokens[6].value
41
+ end
42
+
43
+ it "tokenizes 10 quote edge case correctly" do
44
+ tokens = subject.tokenize('""""""""""')
45
+ assert_equal '""', tokens[0].value # first 8 quotes are a valid block string """"""""
46
+ assert_equal '', tokens[1].value # last 2 quotes are a valid string ""
47
+ end
48
+
49
+ it "tokenizes with nested single quote strings correctly" do
50
+ tokens = subject.tokenize('"""{"x"}"""')
51
+ assert_equal '{"x"}', tokens[0].value
52
+
53
+ tokens = subject.tokenize('"""{"foo":"bar"}"""')
54
+ assert_equal '{"foo":"bar"}', tokens[0].value
35
55
  end
36
56
  end
37
57
 
@@ -62,5 +82,54 @@ describe GraphQL::Language::Lexer do
62
82
  rparen_token = tokens[6]
63
83
  assert_equal '(RPAREN ")" [1:10])', rparen_token.inspect
64
84
  end
85
+
86
+ it "counts block string line properly" do
87
+ str = <<-GRAPHQL
88
+ """
89
+ Here is a
90
+ multiline description
91
+ """
92
+ type Query {
93
+ a: B
94
+ }
95
+
96
+ "Here's another description"
97
+
98
+ type B {
99
+ a: B
100
+ }
101
+
102
+ """
103
+ And another
104
+ multiline description
105
+ """
106
+
107
+
108
+ type C {
109
+ a: B
110
+ }
111
+ GRAPHQL
112
+
113
+ tokens = subject.tokenize(str)
114
+
115
+ string_tok, type_keyword_tok, query_name_tok,
116
+ _curly, _ident, _colon, _ident, _curly,
117
+ string_tok_2, type_keyword_tok_2, b_name_tok,
118
+ _curly, _ident, _colon, _ident, _curly,
119
+ string_tok_3, type_keyword_tok_3, c_name_tok = tokens
120
+
121
+ assert_equal 1, string_tok.line
122
+ assert_equal 5, type_keyword_tok.line
123
+ assert_equal 5, query_name_tok.line
124
+
125
+ # Make sure it handles the empty spaces, too
126
+ assert_equal 9, string_tok_2.line
127
+ assert_equal 11, type_keyword_tok_2.line
128
+ assert_equal 11, b_name_tok.line
129
+
130
+ assert_equal 15, string_tok_3.line
131
+ assert_equal 21, type_keyword_tok_3.line
132
+ assert_equal 21, c_name_tok.line
133
+ end
65
134
  end
66
135
  end
@@ -44,4 +44,24 @@ type Query {
44
44
  assert_equal expected.chomp, document.to_query_string(printer: custom_printer_class.new)
45
45
  end
46
46
  end
47
+
48
+ describe "#dup" do
49
+ it "works with adding selections" do
50
+ f = GraphQL::Language::Nodes::Field.new(name: "f")
51
+ # Calling `.children` may populate an internal cache
52
+ assert_equal "f", f.to_query_string, "the original is unchanged"
53
+ assert_equal 0, f.children.size
54
+ assert_equal 0, f.selections.size
55
+
56
+ f2 = f.merge(selections: [GraphQL::Language::Nodes::Field.new(name: "__typename")])
57
+
58
+ assert_equal "f", f.to_query_string, "the original is unchanged"
59
+ assert_equal 0, f.children.size
60
+ assert_equal 0, f.selections.size
61
+
62
+ assert_equal "f {\n __typename\n}", f2.to_query_string, "the duplicate is updated"
63
+ assert_equal 1, f2.children.size
64
+ assert_equal 1, f2.selections.size
65
+ end
66
+ end
47
67
  end
@@ -112,7 +112,9 @@ describe GraphQL::Language::Printer do
112
112
  mutation: MutationType
113
113
  }
114
114
 
115
- # Union description
115
+ """
116
+ Union description
117
+ """
116
118
  union AnnotatedUnion @onUnion = A | B
117
119
 
118
120
  type Foo implements Bar & AnnotatedInterface {
@@ -125,7 +127,9 @@ describe GraphQL::Language::Printer do
125
127
  seven(argument: String = null): Type
126
128
  }
127
129
 
128
- # Scalar description
130
+ """
131
+ Scalar description
132
+ """
129
133
  scalar CustomScalar
130
134
 
131
135
  type AnnotatedObject implements Bar @onObject(arg: "value") {
@@ -137,9 +141,13 @@ describe GraphQL::Language::Printer do
137
141
  four(argument: String = "string"): String
138
142
  }
139
143
 
140
- # Enum description
144
+ """
145
+ Enum description
146
+ """
141
147
  enum Site {
142
- # Enum value description
148
+ """
149
+ Enum value description
150
+ """
143
151
  DESKTOP
144
152
  MOBILE
145
153
  }
@@ -150,7 +158,9 @@ describe GraphQL::Language::Printer do
150
158
 
151
159
  union Feed = Story | Article | Advert
152
160
 
153
- # Input description
161
+ """
162
+ Input description
163
+ """
154
164
  input InputType {
155
165
  key: String!
156
166
  answer: Int = 42
@@ -160,7 +170,9 @@ describe GraphQL::Language::Printer do
160
170
 
161
171
  scalar CustomScalar
162
172
 
163
- # Directive description
173
+ """
174
+ Directive description
175
+ """
164
176
  directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
165
177
 
166
178
  scalar AnnotatedScalar @onScalar
@@ -16,10 +16,11 @@ describe GraphQL::Language::Visitor do
16
16
 
17
17
  fragment cheeseFields on Cheese { flavor }
18
18
  ")}
19
- let(:counts) { {fields_entered: 0, arguments_entered: 0, arguments_left: 0, argument_names: []} }
19
+ let(:hooks_counts) { {fields_entered: 0, arguments_entered: 0, arguments_left: 0, argument_names: []} }
20
20
 
21
- let(:visitor) do
21
+ let(:hooks_visitor) do
22
22
  v = GraphQL::Language::Visitor.new(document)
23
+ counts = hooks_counts
23
24
  v[GraphQL::Language::Nodes::Field] << ->(node, parent) { counts[:fields_entered] += 1 }
24
25
  # two ways to set up enter hooks:
25
26
  v[GraphQL::Language::Nodes::Argument] << ->(node, parent) { counts[:argument_names] << node.name }
@@ -30,14 +31,43 @@ describe GraphQL::Language::Visitor do
30
31
  v
31
32
  end
32
33
 
33
- it "calls hooks during a depth-first tree traversal" do
34
- assert_equal(2, visitor[GraphQL::Language::Nodes::Argument].enter.length)
35
- visitor.visit
36
- assert_equal(6, counts[:fields_entered])
37
- assert_equal(2, counts[:arguments_entered])
38
- assert_equal(2, counts[:arguments_left])
39
- assert_equal(["id", "first"], counts[:argument_names])
40
- assert(counts[:finished])
34
+ class VisitorSpecVisitor < GraphQL::Language::Visitor
35
+ attr_reader :counts
36
+ def initialize(document)
37
+ @counts = {fields_entered: 0, arguments_entered: 0, arguments_left: 0, argument_names: []}
38
+ super
39
+ end
40
+
41
+ def on_field(node, parent)
42
+ counts[:fields_entered] += 1
43
+ super(node, parent)
44
+ end
45
+
46
+ def on_argument(node, parent)
47
+ counts[:argument_names] << node.name
48
+ counts[:arguments_entered] += 1
49
+ super
50
+ ensure
51
+ counts[:arguments_left] += 1
52
+ end
53
+
54
+ def on_document(node, parent)
55
+ counts[:finished] = true
56
+ super
57
+ end
58
+ end
59
+
60
+ class SkippingVisitor < VisitorSpecVisitor
61
+ def on_document(_n, _p)
62
+ SKIP
63
+ end
64
+ end
65
+
66
+ let(:class_based_visitor) { VisitorSpecVisitor.new(document) }
67
+ let(:class_based_counts) { class_based_visitor.counts }
68
+
69
+ it "has an array of hooks" do
70
+ assert_equal(2, hooks_visitor[GraphQL::Language::Nodes::Argument].enter.length)
41
71
  end
42
72
 
43
73
  it "can visit a document with directive definitions" do
@@ -65,11 +95,30 @@ describe GraphQL::Language::Visitor do
65
95
  assert_equal 10, directive_locations.length
66
96
  end
67
97
 
68
- describe "Visitor::SKIP" do
69
- it "skips the rest of the node" do
70
- visitor[GraphQL::Language::Nodes::Document] << ->(node, parent) { GraphQL::Language::Visitor::SKIP }
98
+ [:hooks, :class_based].each do |visitor_type|
99
+ it "#{visitor_type} visitor calls hooks during a depth-first tree traversal" do
100
+ visitor = public_send("#{visitor_type}_visitor")
71
101
  visitor.visit
72
- assert_equal(0, counts[:fields_entered])
102
+ counts = public_send("#{visitor_type}_counts")
103
+ assert_equal(6, counts[:fields_entered])
104
+ assert_equal(2, counts[:arguments_entered])
105
+ assert_equal(2, counts[:arguments_left])
106
+ assert_equal(["id", "first"], counts[:argument_names])
107
+ assert(counts[:finished])
108
+ end
109
+
110
+ describe "Visitor::SKIP" do
111
+ let(:class_based_visitor) { SkippingVisitor.new(document) }
112
+
113
+ it "#{visitor_type} visitor skips the rest of the node" do
114
+ visitor = public_send("#{visitor_type}_visitor")
115
+ if visitor_type == :hooks
116
+ visitor[GraphQL::Language::Nodes::Document] << ->(node, parent) { GraphQL::Language::Visitor::SKIP }
117
+ end
118
+ visitor.visit
119
+ counts = public_send("#{visitor_type}_counts")
120
+ assert_equal(0, counts[:fields_entered])
121
+ end
73
122
  end
74
123
  end
75
124
 
@@ -91,4 +140,261 @@ describe GraphQL::Language::Visitor do
91
140
 
92
141
  assert visited_directive
93
142
  end
143
+
144
+ describe "AST modification" do
145
+ class ModificationTestVisitor < GraphQL::Language::Visitor
146
+ def on_field(node, parent)
147
+ if node.name == "c"
148
+ new_node = node.merge(name: "renamedC")
149
+ super(new_node, parent)
150
+ elsif node.name == "addFields"
151
+ new_node = node.merge_selection(name: "addedChild")
152
+ super(new_node, parent)
153
+ elsif node.name == "anotherAddition"
154
+ new_node = node
155
+ .merge_argument(name: "addedArgument", value: 1)
156
+ .merge_directive(name: "doStuff")
157
+ super(new_node, parent)
158
+ else
159
+ super
160
+ end
161
+ end
162
+
163
+ def on_argument(node, parent)
164
+ if node.name == "deleteMe"
165
+ super(DELETE_NODE, parent)
166
+ else
167
+ super
168
+ end
169
+ end
170
+
171
+ def on_input_object(node, parent)
172
+ if node.arguments.map(&:name).sort == ["delete", "me"]
173
+ super(DELETE_NODE, parent)
174
+ else
175
+ super
176
+ end
177
+ end
178
+
179
+ def on_directive(node, parent)
180
+ if node.name == "doStuff"
181
+ new_node = node.merge_argument(name: "addedArgument2", value: 2)
182
+ super(new_node, parent)
183
+ else
184
+ super
185
+ end
186
+ end
187
+
188
+ def on_inline_fragment(node, parent)
189
+ if node.selections.map(&:name) == ["renameFragmentField", "spread"]
190
+ _field, spread = node.selections
191
+ new_node = node.merge(selections: [GraphQL::Language::Nodes::Field.new(name: "renamed"), spread])
192
+ super(new_node, parent)
193
+ else
194
+ super(node, parent)
195
+ end
196
+ end
197
+
198
+ def on_fragment_spread(node, parent)
199
+ if node.name == "spread"
200
+ new_node = node.merge(name: "renamedSpread")
201
+ super(new_node, parent)
202
+ else
203
+ super(node, parent)
204
+ end
205
+ end
206
+
207
+ def on_object_type_definition(node, parent)
208
+ if node.name == "Rename"
209
+ new_node = node.merge(name: "WasRenamed")
210
+ super(new_node, parent)
211
+ else
212
+ super(node, parent)
213
+ end
214
+ end
215
+
216
+ def on_field_definition(node, parent)
217
+ if node.name == "renameThis"
218
+ new_node = node.merge(name: "wasRenamed")
219
+ super(new_node, parent)
220
+ else
221
+ super
222
+ end
223
+ end
224
+
225
+ def on_input_value_definition(node, parent)
226
+ if node.name == "renameThisArg"
227
+ new_node = node.merge(name: "argWasRenamed")
228
+ super(new_node, parent)
229
+ else
230
+ super
231
+ end
232
+ end
233
+ end
234
+
235
+ def get_result(query_str)
236
+ document = GraphQL.parse(query_str)
237
+ visitor = ModificationTestVisitor.new(document)
238
+ visitor.visit
239
+ return document, visitor.result
240
+ end
241
+
242
+ it "returns a new AST with modifications applied" do
243
+ query = <<-GRAPHQL.chop
244
+ query {
245
+ a(a1: 1) {
246
+ b(b2: 2) {
247
+ c(c3: 3)
248
+ }
249
+ }
250
+ d(d4: 4)
251
+ }
252
+ GRAPHQL
253
+ document, new_document = get_result(query)
254
+ refute_equal document, new_document
255
+ expected_result = <<-GRAPHQL.chop
256
+ query {
257
+ a(a1: 1) {
258
+ b(b2: 2) {
259
+ renamedC(c3: 3)
260
+ }
261
+ }
262
+ d(d4: 4)
263
+ }
264
+ GRAPHQL
265
+ assert_equal expected_result, new_document.to_query_string, "the result has changes"
266
+ assert_equal query, document.to_query_string, "the original is unchanged"
267
+
268
+ # This is testing the implementation: nodes which aren't affected by modification
269
+ # should be shared between the two trees
270
+ orig_c3_argument = document.definitions.first.selections.first.selections.first.selections.first.arguments.first
271
+ copy_c3_argument = new_document.definitions.first.selections.first.selections.first.selections.first.arguments.first
272
+ assert_equal "c3", orig_c3_argument.name
273
+ assert orig_c3_argument.equal?(copy_c3_argument), "Child nodes are persisted"
274
+
275
+ orig_d_field = document.definitions.first.selections[1]
276
+ copy_d_field = new_document.definitions.first.selections[1]
277
+ assert_equal "d", orig_d_field.name
278
+ assert orig_d_field.equal?(copy_d_field), "Sibling nodes are persisted"
279
+
280
+ orig_b_field = document.definitions.first.selections.first.selections.first
281
+ copy_b_field = new_document.definitions.first.selections.first.selections.first
282
+ assert_equal "b", orig_b_field.name
283
+ refute orig_b_field.equal?(copy_b_field), "Parents with modified children are copied"
284
+ end
285
+
286
+ it "deletes nodes with DELETE_NODE" do
287
+ before_query = <<-GRAPHQL.chop
288
+ query {
289
+ f1 {
290
+ f2(deleteMe: 1) {
291
+ f3(c1: {deleteMe: {c2: 2}})
292
+ f4(c2: [{keepMe: 1}, {deleteMe: 2}, {keepMe: 3}])
293
+ }
294
+ }
295
+ }
296
+ GRAPHQL
297
+
298
+ after_query = <<-GRAPHQL.chop
299
+ query {
300
+ f1 {
301
+ f2 {
302
+ f3(c1: {})
303
+ f4(c2: [{keepMe: 1}, {}, {keepMe: 3}])
304
+ }
305
+ }
306
+ }
307
+ GRAPHQL
308
+
309
+ document, new_document = get_result(before_query)
310
+ assert_equal before_query, document.to_query_string
311
+ assert_equal after_query, new_document.to_query_string
312
+ end
313
+
314
+ it "Deletes from lists" do
315
+ before_query = <<-GRAPHQL.chop
316
+ query {
317
+ f1(arg1: [{a: 1}, {delete: 1, me: 2}, {b: 2}])
318
+ }
319
+ GRAPHQL
320
+
321
+ after_query = <<-GRAPHQL.chop
322
+ query {
323
+ f1(arg1: [{a: 1}, {b: 2}])
324
+ }
325
+ GRAPHQL
326
+
327
+ document, new_document = get_result(before_query)
328
+ assert_equal before_query, document.to_query_string
329
+ assert_equal after_query, new_document.to_query_string
330
+ end
331
+
332
+ it "can add children" do
333
+ before_query = <<-GRAPHQL.chop
334
+ query {
335
+ addFields
336
+ anotherAddition
337
+ }
338
+ GRAPHQL
339
+
340
+ after_query = <<-GRAPHQL.chop
341
+ query {
342
+ addFields {
343
+ addedChild
344
+ }
345
+ anotherAddition(addedArgument: 1) @doStuff(addedArgument2: 2)
346
+ }
347
+ GRAPHQL
348
+
349
+ document, new_document = get_result(before_query)
350
+ assert_equal before_query, document.to_query_string
351
+ assert_equal after_query, new_document.to_query_string
352
+ end
353
+
354
+ it "can modify inline fragments" do
355
+ before_query = <<-GRAPHQL.chop
356
+ query {
357
+ ... on Query {
358
+ renameFragmentField
359
+ ...spread
360
+ }
361
+ }
362
+ GRAPHQL
363
+
364
+ after_query = <<-GRAPHQL.chop
365
+ query {
366
+ ... on Query {
367
+ renamed
368
+ ...renamedSpread
369
+ }
370
+ }
371
+ GRAPHQL
372
+
373
+ document, new_document = get_result(before_query)
374
+ assert_equal before_query, document.to_query_string
375
+ assert_equal after_query, new_document.to_query_string
376
+ end
377
+
378
+ it "works with SDL" do
379
+ before_query = <<-GRAPHQL.chop
380
+ type Rename @doStuff {
381
+ f: Int
382
+ renameThis: String
383
+ f2(renameThisArg: Boolean): Boolean
384
+ }
385
+ GRAPHQL
386
+
387
+ after_query = <<-GRAPHQL.chop
388
+ type WasRenamed @doStuff(addedArgument2: 2) {
389
+ f: Int
390
+ wasRenamed: String
391
+ f2(argWasRenamed: Boolean): Boolean
392
+ }
393
+ GRAPHQL
394
+
395
+ document, new_document = get_result(before_query)
396
+ assert_equal before_query, document.to_query_string
397
+ assert_equal after_query, new_document.to_query_string
398
+ end
399
+ end
94
400
  end
@@ -39,7 +39,7 @@ describe GraphQL::NonNullType do
39
39
  query_string = %|{ cow { name cantBeNullButIs } }|
40
40
  err = assert_raises(GraphQL::InvalidNullError) { raise_schema.execute(query_string) }
41
41
  assert_equal("Cannot return null for non-nullable field Cow.cantBeNullButIs", err.message)
42
- assert_equal("Cow", err.parent_type.name)
42
+ assert_equal("Cow", err.parent_type.graphql_name)
43
43
  assert_equal("cantBeNullButIs", err.field.name)
44
44
  assert_equal(nil, err.value)
45
45
  end