graphql 1.7.6 → 1.8.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 (289) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/function_generator.rb +1 -1
  3. data/lib/generators/graphql/install_generator.rb +14 -8
  4. data/lib/generators/graphql/loader_generator.rb +1 -1
  5. data/lib/generators/graphql/mutation_generator.rb +6 -1
  6. data/lib/generators/graphql/templates/function.erb +2 -2
  7. data/lib/generators/graphql/templates/loader.erb +2 -2
  8. data/lib/generators/graphql/templates/schema.erb +1 -1
  9. data/lib/graphql/argument.rb +25 -19
  10. data/lib/graphql/backtrace/tracer.rb +16 -22
  11. data/lib/graphql/backtrace.rb +1 -1
  12. data/lib/graphql/backwards_compatibility.rb +2 -3
  13. data/lib/graphql/base_type.rb +31 -31
  14. data/lib/graphql/compatibility/query_parser_specification/parse_error_specification.rb +14 -0
  15. data/lib/graphql/compatibility/query_parser_specification.rb +117 -0
  16. data/lib/graphql/define/assign_object_field.rb +5 -12
  17. data/lib/graphql/deprecated_dsl.rb +42 -0
  18. data/lib/graphql/directive.rb +1 -0
  19. data/lib/graphql/enum_type.rb +3 -1
  20. data/lib/graphql/execution/execute.rb +21 -13
  21. data/lib/graphql/execution/instrumentation.rb +82 -0
  22. data/lib/graphql/execution/lazy/lazy_method_map.rb +1 -1
  23. data/lib/graphql/execution/lazy/resolve.rb +1 -3
  24. data/lib/graphql/execution/multiplex.rb +12 -29
  25. data/lib/graphql/execution.rb +1 -0
  26. data/lib/graphql/field.rb +21 -4
  27. data/lib/graphql/function.rb +14 -0
  28. data/lib/graphql/input_object_type.rb +3 -1
  29. data/lib/graphql/interface_type.rb +5 -3
  30. data/lib/graphql/internal_representation/node.rb +26 -14
  31. data/lib/graphql/internal_representation/visit.rb +3 -6
  32. data/lib/graphql/introspection/base_object.rb +16 -0
  33. data/lib/graphql/introspection/directive_location_enum.rb +11 -7
  34. data/lib/graphql/introspection/directive_type.rb +23 -16
  35. data/lib/graphql/introspection/dynamic_fields.rb +11 -0
  36. data/lib/graphql/introspection/entry_points.rb +29 -0
  37. data/lib/graphql/introspection/enum_value_type.rb +16 -11
  38. data/lib/graphql/introspection/field_type.rb +21 -12
  39. data/lib/graphql/introspection/input_value_type.rb +26 -23
  40. data/lib/graphql/introspection/schema_field.rb +7 -2
  41. data/lib/graphql/introspection/schema_type.rb +36 -22
  42. data/lib/graphql/introspection/type_by_name_field.rb +10 -2
  43. data/lib/graphql/introspection/type_kind_enum.rb +10 -6
  44. data/lib/graphql/introspection/type_type.rb +85 -23
  45. data/lib/graphql/introspection/typename_field.rb +1 -0
  46. data/lib/graphql/introspection.rb +3 -10
  47. data/lib/graphql/language/block_string.rb +47 -0
  48. data/lib/graphql/language/document_from_schema_definition.rb +280 -0
  49. data/lib/graphql/language/generation.rb +3 -182
  50. data/lib/graphql/language/lexer.rb +144 -69
  51. data/lib/graphql/language/lexer.rl +15 -4
  52. data/lib/graphql/language/nodes.rb +141 -78
  53. data/lib/graphql/language/parser.rb +677 -630
  54. data/lib/graphql/language/parser.y +18 -12
  55. data/lib/graphql/language/printer.rb +361 -0
  56. data/lib/graphql/language/token.rb +10 -3
  57. data/lib/graphql/language.rb +3 -0
  58. data/lib/graphql/non_null_type.rb +1 -1
  59. data/lib/graphql/object_type.rb +1 -6
  60. data/lib/graphql/query/arguments.rb +63 -32
  61. data/lib/graphql/query/context.rb +32 -2
  62. data/lib/graphql/query/literal_input.rb +4 -1
  63. data/lib/graphql/query/null_context.rb +1 -1
  64. data/lib/graphql/query/result.rb +1 -1
  65. data/lib/graphql/query/variables.rb +21 -3
  66. data/lib/graphql/query.rb +19 -6
  67. data/lib/graphql/railtie.rb +109 -0
  68. data/lib/graphql/relay/connection_resolve.rb +3 -0
  69. data/lib/graphql/relay/connection_type.rb +5 -3
  70. data/lib/graphql/relay/edge_type.rb +2 -1
  71. data/lib/graphql/relay/global_id_resolve.rb +5 -1
  72. data/lib/graphql/relay/mongo_relation_connection.rb +40 -0
  73. data/lib/graphql/relay/mutation/instrumentation.rb +1 -1
  74. data/lib/graphql/relay/mutation/resolve.rb +5 -1
  75. data/lib/graphql/relay/relation_connection.rb +14 -19
  76. data/lib/graphql/relay/type_extensions.rb +30 -0
  77. data/lib/graphql/relay.rb +2 -0
  78. data/lib/graphql/scalar_type.rb +14 -2
  79. data/lib/graphql/schema/argument.rb +92 -0
  80. data/lib/graphql/schema/build_from_definition.rb +64 -18
  81. data/lib/graphql/schema/enum.rb +85 -0
  82. data/lib/graphql/schema/enum_value.rb +74 -0
  83. data/lib/graphql/schema/field.rb +372 -0
  84. data/lib/graphql/schema/finder.rb +153 -0
  85. data/lib/graphql/schema/input_object.rb +87 -0
  86. data/lib/graphql/schema/interface.rb +105 -0
  87. data/lib/graphql/schema/introspection_system.rb +93 -0
  88. data/lib/graphql/schema/late_bound_type.rb +32 -0
  89. data/lib/graphql/schema/list.rb +32 -0
  90. data/lib/graphql/schema/loader.rb +2 -2
  91. data/lib/graphql/schema/member/accepts_definition.rb +152 -0
  92. data/lib/graphql/schema/member/base_dsl_methods.rb +100 -0
  93. data/lib/graphql/schema/member/build_type.rb +137 -0
  94. data/lib/graphql/schema/member/cached_graphql_definition.rb +26 -0
  95. data/lib/graphql/schema/member/graphql_type_names.rb +21 -0
  96. data/lib/graphql/schema/member/has_arguments.rb +50 -0
  97. data/lib/graphql/schema/member/has_fields.rb +130 -0
  98. data/lib/graphql/schema/member/instrumentation.rb +115 -0
  99. data/lib/graphql/schema/member/type_system_helpers.rb +34 -0
  100. data/lib/graphql/schema/member.rb +28 -0
  101. data/lib/graphql/schema/middleware_chain.rb +5 -1
  102. data/lib/graphql/schema/mutation.rb +138 -0
  103. data/lib/graphql/schema/non_null.rb +38 -0
  104. data/lib/graphql/schema/object.rb +81 -0
  105. data/lib/graphql/schema/printer.rb +33 -266
  106. data/lib/graphql/schema/relay_classic_mutation.rb +87 -0
  107. data/lib/graphql/schema/rescue_middleware.rb +8 -7
  108. data/lib/graphql/schema/resolver.rb +122 -0
  109. data/lib/graphql/schema/scalar.rb +35 -0
  110. data/lib/graphql/schema/traversal.rb +102 -22
  111. data/lib/graphql/schema/union.rb +36 -0
  112. data/lib/graphql/schema/validation.rb +3 -2
  113. data/lib/graphql/schema.rb +381 -12
  114. data/lib/graphql/static_validation/definition_dependencies.rb +1 -1
  115. data/lib/graphql/static_validation/literal_validator.rb +16 -4
  116. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +6 -6
  117. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +5 -1
  118. data/lib/graphql/static_validation/rules/fields_will_merge.rb +15 -8
  119. data/lib/graphql/static_validation/rules/variables_are_used_and_defined.rb +11 -1
  120. data/lib/graphql/static_validation/validation_context.rb +1 -1
  121. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +7 -5
  122. data/lib/graphql/subscriptions/instrumentation.rb +5 -1
  123. data/lib/graphql/subscriptions/serialize.rb +2 -0
  124. data/lib/graphql/subscriptions.rb +90 -16
  125. data/lib/graphql/tracing/data_dog_tracing.rb +49 -0
  126. data/lib/graphql/tracing/new_relic_tracing.rb +26 -0
  127. data/lib/graphql/tracing/platform_tracing.rb +20 -7
  128. data/lib/graphql/tracing/scout_tracing.rb +2 -2
  129. data/lib/graphql/tracing.rb +1 -0
  130. data/lib/graphql/unresolved_type_error.rb +3 -2
  131. data/lib/graphql/upgrader/member.rb +894 -0
  132. data/lib/graphql/upgrader/schema.rb +37 -0
  133. data/lib/graphql/version.rb +1 -1
  134. data/lib/graphql.rb +5 -25
  135. data/readme.md +2 -2
  136. data/spec/dummy/app/channels/graphql_channel.rb +23 -2
  137. data/spec/dummy/log/development.log +239 -0
  138. data/spec/dummy/log/test.log +410 -0
  139. data/spec/dummy/test/system/action_cable_subscription_test.rb +4 -0
  140. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-x/-xYZjAnuuzgR79fcznLTQtSdh6AARxu8FcQ_J6p7L3U.cache +0 -0
  141. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/13/13HiV12xyoQvT-1L39ZzLwMZxjyaGMiENmfw7f-QTIc.cache +0 -0
  142. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3W/3Wtf5pCWdqq0AB-iB0Y9uUNrTkruRxIEf1XFn_BETU0.cache +1 -0
  143. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/5i/5iguGafb4hOn8262Kn8Q37ogNN9MxxQKGKNzHAzUcvI.cache +1 -0
  144. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8m/8mj2T6yy847Mc2Z7k3Xzh8O91hhVJt3NrPe8ASNDlIA.cache +1 -0
  145. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/DT/DTQyMpr4ABZYQetsdRJ5A7S4jf1r3ie4FGOR7GZBNSs.cache +3 -0
  146. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Dq/DqJ5_yJPrP5iLlOQyTQsjAVI5FE5LCVDkED0f7GgsSo.cache +3 -0
  147. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/F8/F8MUNRzORGFgr329fNM0xLaoWCXdv3BIalT7dsvLfjs.cache +0 -0
  148. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/KB/KB07ZaKNC5uXJ7TjLi-WqnY6g7dq8wWp_8N3HNjBNxg.cache +0 -0
  149. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Rw/RwDuCV-XpnCtjNkvhpJfBuxXMk0b5AD3L9eR6M-wcy0.cache +3 -0
  150. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/UL/ULdjhhb0bRuqmaG7XSZlFYzGYCXTDnqZuJBTWRlzqgw.cache +0 -0
  151. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Up/UpPNgh0yYoUsyMDh5zWqe_U6qJIyTC6-dxMMAs1vvlM.cache +1 -0
  152. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Wg/Wguh-szFGTI1gaL6npYwPekMXflugRei7F_mOyRucXg.cache +0 -0
  153. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/X-/X-khLYMA9mqFRPg3zAi86mREDxpKl4bdKYp3uF6WHos.cache +0 -0
  154. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/bi/BIkdhfxsezxM4q-HZ4oCNTq97WEJTigcq0tpX2cDvbY.cache +0 -0
  155. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ff/FfxmA4CMHQZT7exx0G7NS1Wpcnny0vzp-Jhc2H36bp8.cache +1 -0
  156. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gE/gEiiG4GZNy_djEjK2pHm_NgA-gyhLZhdQvo0Yt96GqE.cache +0 -0
  157. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gn/gnA9ZSqpjccNL2m8pe_jBvY6SinXlCzXDWyop83Od8s.cache +1 -0
  158. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/lO/lOAan3cMwCE_Hli6gsDML88xFNfn0nxPmvrSkW7eEOw.cache +1 -0
  159. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m1/M1pv8MJEPLXGLvS8QxVh3DSO9cI4mRt5FHFWdrvUj6o.cache +2 -0
  160. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m7/m77qH7ZqH0_0SmwJbiKGDd-aLau1Dav847DC6ge46zY.cache +1 -0
  161. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sj/sjRjnjRB37lH2vrgtkdJ8Cz84__IJ978IuKTM7HcztI.cache +0 -0
  162. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/um/um1JrirR4hJhK-1rE-HywlyCi5ibgxHVrReiujZBWJM.cache +1 -0
  163. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v4/v4fwVytD7ITcE0_GDbslZEYud8a5Okm85fV1o7SDl6g.cache +0 -0
  164. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v_/v_0PAQt0iipQjFP5zjgkkk9Stnpf4VzvnMv67d1Keuw.cache +1 -0
  165. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wd/wdT9U4MKxe1PyqNjVuCKMpCl3dxGCIRJIlwUTfh2DQU.cache +1 -0
  166. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xI/xIaxut_fEIhKBDqljTNwYaADK9kj3gG0ESrfHs-5_og.cache +3 -0
  167. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/y0/y0SJOqIx2fn1SKqOkAihsQow0trRJrSIyAswufVuoA8.cache +0 -0
  168. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zg/zgpzeaX-KZErHyGJ1aBH3ZusweNXMneVZule88XsIJI.cache +1 -0
  169. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zy/zYFltDy-8VC-uKq2BVEiJJyYXNFvVzAKuMlR3ZIYZsk.cache +0 -0
  170. data/spec/dummy/tmp/screenshots/failures_test_it_handles_subscriptions.png +0 -0
  171. data/spec/fixtures/upgrader/account.original.rb +19 -0
  172. data/spec/fixtures/upgrader/account.transformed.rb +20 -0
  173. data/spec/fixtures/upgrader/blame_range.original.rb +43 -0
  174. data/spec/fixtures/upgrader/blame_range.transformed.rb +30 -0
  175. data/spec/fixtures/upgrader/date_time.original.rb +24 -0
  176. data/spec/fixtures/upgrader/date_time.transformed.rb +23 -0
  177. data/spec/fixtures/upgrader/delete_project.original.rb +28 -0
  178. data/spec/fixtures/upgrader/delete_project.transformed.rb +27 -0
  179. data/spec/fixtures/upgrader/gist_order_field.original.rb +14 -0
  180. data/spec/fixtures/upgrader/gist_order_field.transformed.rb +13 -0
  181. data/spec/fixtures/upgrader/increment_count.original.rb +59 -0
  182. data/spec/fixtures/upgrader/increment_count.transformed.rb +50 -0
  183. data/spec/fixtures/upgrader/photo.original.rb +10 -0
  184. data/spec/fixtures/upgrader/photo.transformed.rb +12 -0
  185. data/spec/fixtures/upgrader/release_order.original.rb +15 -0
  186. data/spec/fixtures/upgrader/release_order.transformed.rb +14 -0
  187. data/spec/fixtures/upgrader/starrable.original.rb +49 -0
  188. data/spec/fixtures/upgrader/starrable.transformed.rb +46 -0
  189. data/spec/fixtures/upgrader/subscribable.original.rb +55 -0
  190. data/spec/fixtures/upgrader/subscribable.transformed.rb +51 -0
  191. data/spec/fixtures/upgrader/type_x.original.rb +65 -0
  192. data/spec/fixtures/upgrader/type_x.transformed.rb +56 -0
  193. data/spec/generators/graphql/function_generator_spec.rb +26 -0
  194. data/spec/generators/graphql/install_generator_spec.rb +1 -1
  195. data/spec/generators/graphql/loader_generator_spec.rb +24 -0
  196. data/spec/graphql/analysis/max_query_complexity_spec.rb +3 -3
  197. data/spec/graphql/analysis/max_query_depth_spec.rb +3 -3
  198. data/spec/graphql/argument_spec.rb +21 -0
  199. data/spec/graphql/backtrace_spec.rb +10 -0
  200. data/spec/graphql/base_type_spec.rb +42 -0
  201. data/spec/graphql/boolean_type_spec.rb +3 -3
  202. data/spec/graphql/directive_spec.rb +3 -1
  203. data/spec/graphql/enum_type_spec.rb +18 -5
  204. data/spec/graphql/execution/execute_spec.rb +4 -4
  205. data/spec/graphql/execution/instrumentation_spec.rb +165 -0
  206. data/spec/graphql/execution/multiplex_spec.rb +2 -2
  207. data/spec/graphql/execution_error_spec.rb +18 -0
  208. data/spec/graphql/float_type_spec.rb +2 -2
  209. data/spec/graphql/id_type_spec.rb +1 -1
  210. data/spec/graphql/input_object_type_spec.rb +15 -2
  211. data/spec/graphql/int_type_spec.rb +2 -2
  212. data/spec/graphql/interface_type_spec.rb +12 -0
  213. data/spec/graphql/internal_representation/rewrite_spec.rb +2 -2
  214. data/spec/graphql/introspection/schema_type_spec.rb +2 -0
  215. data/spec/graphql/language/block_string_spec.rb +70 -0
  216. data/spec/graphql/language/document_from_schema_definition_spec.rb +770 -0
  217. data/spec/graphql/language/generation_spec.rb +21 -186
  218. data/spec/graphql/language/lexer_spec.rb +21 -1
  219. data/spec/graphql/language/nodes_spec.rb +21 -12
  220. data/spec/graphql/language/parser_spec.rb +1 -1
  221. data/spec/graphql/language/printer_spec.rb +203 -0
  222. data/spec/graphql/object_type_spec.rb +22 -0
  223. data/spec/graphql/query/arguments_spec.rb +25 -15
  224. data/spec/graphql/query/context_spec.rb +18 -0
  225. data/spec/graphql/query/executor_spec.rb +2 -1
  226. data/spec/graphql/query/serial_execution/value_resolution_spec.rb +2 -8
  227. data/spec/graphql/query/variables_spec.rb +42 -1
  228. data/spec/graphql/query_spec.rb +31 -5
  229. data/spec/graphql/rake_task_spec.rb +3 -1
  230. data/spec/graphql/relay/base_connection_spec.rb +1 -1
  231. data/spec/graphql/relay/connection_instrumentation_spec.rb +2 -2
  232. data/spec/graphql/relay/connection_resolve_spec.rb +1 -1
  233. data/spec/graphql/relay/connection_type_spec.rb +1 -1
  234. data/spec/graphql/relay/mongo_relation_connection_spec.rb +474 -0
  235. data/spec/graphql/relay/mutation_spec.rb +9 -7
  236. data/spec/graphql/relay/range_add_spec.rb +5 -1
  237. data/spec/graphql/relay/relation_connection_spec.rb +65 -1
  238. data/spec/graphql/schema/argument_spec.rb +87 -0
  239. data/spec/graphql/schema/build_from_definition_spec.rb +89 -5
  240. data/spec/graphql/schema/enum_spec.rb +74 -0
  241. data/spec/graphql/schema/field_spec.rb +225 -0
  242. data/spec/graphql/schema/finder_spec.rb +135 -0
  243. data/spec/graphql/schema/input_object_spec.rb +111 -0
  244. data/spec/graphql/schema/instrumentation_spec.rb +40 -0
  245. data/spec/graphql/schema/interface_spec.rb +185 -0
  246. data/spec/graphql/schema/introspection_system_spec.rb +39 -0
  247. data/spec/graphql/schema/member/accepts_definition_spec.rb +111 -0
  248. data/spec/graphql/schema/member/build_type_spec.rb +17 -0
  249. data/spec/graphql/schema/member/has_fields_spec.rb +129 -0
  250. data/spec/graphql/schema/member/type_system_helpers_spec.rb +63 -0
  251. data/spec/graphql/schema/mutation_spec.rb +148 -0
  252. data/spec/graphql/schema/object_spec.rb +175 -0
  253. data/spec/graphql/schema/printer_spec.rb +111 -15
  254. data/spec/graphql/schema/relay_classic_mutation_spec.rb +38 -0
  255. data/spec/graphql/schema/rescue_middleware_spec.rb +11 -0
  256. data/spec/graphql/schema/resolver_spec.rb +131 -0
  257. data/spec/graphql/schema/scalar_spec.rb +95 -0
  258. data/spec/graphql/schema/traversal_spec.rb +31 -0
  259. data/spec/graphql/schema/union_spec.rb +65 -0
  260. data/spec/graphql/schema/validation_spec.rb +1 -1
  261. data/spec/graphql/schema/warden_spec.rb +11 -11
  262. data/spec/graphql/schema_spec.rb +55 -12
  263. data/spec/graphql/static_validation/rules/fields_have_appropriate_selections_spec.rb +10 -2
  264. data/spec/graphql/static_validation/rules/fields_will_merge_spec.rb +2 -2
  265. data/spec/graphql/string_type_spec.rb +3 -3
  266. data/spec/graphql/subscriptions_spec.rb +273 -184
  267. data/spec/graphql/tracing/active_support_notifications_tracing_spec.rb +1 -1
  268. data/spec/graphql/tracing/new_relic_tracing_spec.rb +47 -0
  269. data/spec/graphql/tracing/platform_tracing_spec.rb +60 -1
  270. data/spec/graphql/union_type_spec.rb +1 -1
  271. data/spec/graphql/upgrader/member_spec.rb +516 -0
  272. data/spec/graphql/upgrader/schema_spec.rb +82 -0
  273. data/spec/spec_helper.rb +8 -0
  274. data/spec/support/dummy/schema.rb +53 -24
  275. data/spec/support/jazz.rb +544 -0
  276. data/spec/support/lazy_helpers.rb +21 -23
  277. data/spec/support/new_relic.rb +24 -0
  278. data/spec/support/star_trek/data.rb +109 -0
  279. data/spec/support/star_trek/schema.rb +388 -0
  280. data/spec/support/star_wars/data.rb +6 -7
  281. data/spec/support/star_wars/schema.rb +127 -171
  282. metadata +233 -11
  283. data/lib/graphql/introspection/arguments_field.rb +0 -7
  284. data/lib/graphql/introspection/enum_values_field.rb +0 -18
  285. data/lib/graphql/introspection/fields_field.rb +0 -13
  286. data/lib/graphql/introspection/input_fields_field.rb +0 -12
  287. data/lib/graphql/introspection/interfaces_field.rb +0 -11
  288. data/lib/graphql/introspection/of_type_field.rb +0 -6
  289. data/lib/graphql/introspection/possible_types_field.rb +0 -11
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
3
+
4
+ describe GraphQL::Schema::Member::HasFields do
5
+ module SuperTest
6
+ class BaseObject < GraphQL::Schema::Object
7
+ end
8
+
9
+ module BaseInterface
10
+ include GraphQL::Schema::Interface
11
+ end
12
+
13
+ module InterfaceWithFloatField
14
+ include BaseInterface
15
+ field :float, Float, null: false
16
+ def float
17
+ # This should call the default implementation
18
+ super * 0.5
19
+ end
20
+ end
21
+
22
+ module SubInterfaceWithFloatField
23
+ include InterfaceWithFloatField
24
+ def float
25
+ # This should call `InterfaceWithFloatField#float`
26
+ super * 0.1
27
+ end
28
+ end
29
+
30
+ class ObjectWithFloatField < BaseObject
31
+ implements InterfaceWithFloatField
32
+ end
33
+
34
+ class ObjectWithSubFloatField < BaseObject
35
+ implements SubInterfaceWithFloatField
36
+ end
37
+
38
+ module InterfaceWithStringField
39
+ include BaseInterface
40
+ field :string, String, null: false
41
+ def string
42
+ # Return a literal value to ensure this method was called
43
+ "here's a string"
44
+ end
45
+ end
46
+
47
+ class ObjectWithStringField < BaseObject
48
+ implements InterfaceWithStringField
49
+ def string
50
+ # This should call to `InterfaceWithStringField#string`
51
+ super.upcase
52
+ end
53
+ end
54
+
55
+ class SubObjectWithStringField < ObjectWithStringField
56
+ def string
57
+ # This should call to `ObjectWithStringField#string`
58
+ super.reverse
59
+ end
60
+ end
61
+
62
+ class SubSubObjectWithStringField < SubObjectWithStringField
63
+ field :string, String, null: false
64
+ end
65
+
66
+ class Query < BaseObject
67
+ field :int, Integer, null: false
68
+ def int
69
+ # This should call default resolution
70
+ super * 2
71
+ end
72
+
73
+ field :string1, ObjectWithStringField, null: false, method: :object
74
+ field :string2, SubObjectWithStringField, null: false, method: :object
75
+ field :string3, SubSubObjectWithStringField, null: false, method: :object
76
+ field :float1, ObjectWithFloatField, null: false, method: :object
77
+ field :float2, ObjectWithSubFloatField, null: false, method: :object
78
+ end
79
+
80
+ class Schema < GraphQL::Schema
81
+ query(Query)
82
+ end
83
+ end
84
+
85
+ describe "Calling super in field methods" do
86
+ # Test that calling `super` in field methods "works", which means:
87
+ # - If there is a super method in the user-created hierarchy (either a class or module), it is called
88
+ # This is tested by putting random transformations in method bodies,
89
+ # then asserting that they are called.
90
+ # - If there's no user-defined super method, it calls the built-in default behavior
91
+ # This is tested by putting values in the `root_value` hash.
92
+ # The default behavior is to fetch hash values by key, so we assert that
93
+ # those values are subject to the specified transformations.
94
+
95
+ describe "Object methods" do
96
+ it "may call super to default implementation" do
97
+ res = SuperTest::Schema.execute("{ int }", root_value: { int: 4 })
98
+ assert_equal 8, res["data"]["int"]
99
+ end
100
+
101
+ it "may call super to interface method" do
102
+ res = SuperTest::Schema.execute(" { string1 { string } }", root_value: {})
103
+ assert_equal "HERE'S A STRING", res["data"]["string1"]["string"]
104
+ end
105
+
106
+ it "may call super to superclass method" do
107
+ res = SuperTest::Schema.execute(" { string2 { string } }", root_value: {})
108
+ assert_equal "GNIRTS A S'EREH", res["data"]["string2"]["string"]
109
+ end
110
+
111
+ it "can get a super method from a newly-added field" do
112
+ res = SuperTest::Schema.execute(" { string3 { string } }", root_value: {})
113
+ assert_equal "GNIRTS A S'EREH", res["data"]["string3"]["string"]
114
+ end
115
+ end
116
+
117
+ describe "Interface methods" do
118
+ it "may call super to interface method" do
119
+ res = SuperTest::Schema.execute(" { float1 { float } }", root_value: { float: 6.0 })
120
+ assert_equal 3.0, res["data"]["float1"]["float"]
121
+ end
122
+
123
+ it "may call super to superclass method" do
124
+ res = SuperTest::Schema.execute(" { float2 { float } }", root_value: { float: 6.0 })
125
+ assert_in_delta 0.001, 0.3, res["data"]["float2"]["float"]
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
3
+
4
+ describe GraphQL::Schema::Member::TypeSystemHelpers do
5
+ let(:object) {
6
+ Class.new(GraphQL::Schema::Object) do
7
+ graphql_name "Thing"
8
+
9
+ field :int, Integer, null: true
10
+ field :int2, Integer, null: false
11
+ field :int_list, [Integer], null: true
12
+ field :int_list2, [Integer], null: false
13
+ end
14
+ }
15
+
16
+ let(:int_field) { object.fields["int"] }
17
+ let(:int2_field) { object.fields["int2"] }
18
+ let(:int_list_field) { object.fields["intList"] }
19
+ let(:int_list2_field) { object.fields["intList2"] }
20
+
21
+ describe "#list?" do
22
+ it "is true for lists, including non-null lists, otherwise false" do
23
+ assert int_list_field.type.list?
24
+ assert int_list2_field.type.list?
25
+ refute int_field.type.list?
26
+ refute int2_field.type.list?
27
+ end
28
+ end
29
+
30
+ describe "#non_null?" do
31
+ it "is true for required types" do
32
+ assert int2_field.type.non_null?
33
+ assert int_list2_field.type.non_null?
34
+ refute int_field.type.non_null?
35
+ refute int_list_field.type.non_null?
36
+ end
37
+ end
38
+
39
+ describe "#kind" do
40
+ let(:pairs) {{
41
+ GraphQL::Schema::Object => "OBJECT",
42
+ GraphQL::Schema::Union => "UNION",
43
+ GraphQL::Schema::Interface => "INTERFACE",
44
+ GraphQL::Schema::Enum => "ENUM",
45
+ GraphQL::Schema::InputObject => "INPUT_OBJECT",
46
+ GraphQL::Schema::Scalar => "SCALAR",
47
+ }}
48
+ it "returns the TypeKind instance" do
49
+ pairs.each do |type_class, type_kind_name|
50
+ type = if type_class.is_a?(Class)
51
+ Class.new(type_class)
52
+ else
53
+ Module.new { include(type_class) }
54
+ end
55
+
56
+ assert_equal type_kind_name, type.kind.name
57
+ end
58
+
59
+ assert_equal "LIST", GraphQL::Schema::Object.to_list_type.kind.name
60
+ assert_equal "NON_NULL", GraphQL::Schema::Object.to_non_null_type.kind.name
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
3
+
4
+ # Make sure that `!` has no effect
5
+ using GraphQL::DeprecatedDSL
6
+
7
+ describe GraphQL::Schema::Mutation do
8
+ let(:mutation) { Jazz::AddInstrument }
9
+ after do
10
+ Jazz::Models.reset
11
+ end
12
+
13
+ it "Doesn't override !" do
14
+ assert_equal false, !mutation
15
+ end
16
+
17
+ describe "definition" do
18
+ it "passes along description" do
19
+ assert_equal "Register a new musical instrument in the database", mutation.field_options[:description]
20
+ assert_equal "Autogenerated return type of AddInstrument", mutation.payload_type.description
21
+ end
22
+ end
23
+
24
+ describe "argument prepare" do
25
+ it "calls methods on the mutation, uses `as:`" do
26
+ query_str = 'mutation { prepareInput(input: 4) }'
27
+ res = Jazz::Schema.execute(query_str)
28
+ assert_equal 16, res["data"]["prepareInput"], "It's squared by the prepare method"
29
+ end
30
+ end
31
+
32
+ describe "a derived field" do
33
+ it "has a reference to the mutation" do
34
+ f = GraphQL::Schema::Field.from_options(name: "x", **mutation.field_options)
35
+ assert_equal mutation, f.mutation
36
+
37
+ # Make sure it's also present in the schema
38
+ f2 = Jazz::Schema.find("Mutation.addInstrument")
39
+ assert_equal mutation, f2.mutation
40
+ end
41
+ end
42
+
43
+ describe ".payload_type" do
44
+ it "has a reference to the mutation" do
45
+ assert_equal mutation, mutation.payload_type.mutation
46
+ end
47
+ end
48
+
49
+ describe ".field" do
50
+ it "raises a nice error when called without args" do
51
+ err = assert_raises(ArgumentError) { mutation.field }
52
+ assert_includes err.message, "Use `mutation: Jazz::AddInstrument` to attach this mutation instead."
53
+ end
54
+ end
55
+
56
+ describe ".object_class" do
57
+ it "can override & inherit the parent class" do
58
+ obj_class = Class.new(GraphQL::Schema::Object)
59
+ mutation_class = Class.new(GraphQL::Schema::Mutation) do
60
+ object_class(obj_class)
61
+ end
62
+ mutation_subclass = Class.new(mutation_class)
63
+
64
+ assert_equal(GraphQL::Schema::Object, GraphQL::Schema::Mutation.object_class)
65
+ assert_equal(obj_class, mutation_class.object_class)
66
+ assert_equal(obj_class, mutation_subclass.object_class) end
67
+ end
68
+
69
+ describe ".argument_class" do
70
+ it "can override & inherit the parent class" do
71
+ arg_class = Class.new(GraphQL::Schema::Argument)
72
+ mutation_class = Class.new(GraphQL::Schema::Mutation) do
73
+ argument_class(arg_class)
74
+ end
75
+
76
+ mutation_subclass = Class.new(mutation_class)
77
+
78
+ assert_equal(GraphQL::Schema::Argument, GraphQL::Schema::Mutation.argument_class)
79
+ assert_equal(arg_class, mutation_class.argument_class)
80
+ assert_equal(arg_class, mutation_subclass.argument_class)
81
+ end
82
+ end
83
+
84
+ describe "evaluation" do
85
+ it "runs mutations" do
86
+ query_str = <<-GRAPHQL
87
+ mutation {
88
+ addInstrument(name: "Trombone", family: BRASS) {
89
+ instrument {
90
+ name
91
+ family
92
+ }
93
+ entries {
94
+ name
95
+ }
96
+ ee
97
+ }
98
+ }
99
+ GRAPHQL
100
+
101
+ response = Jazz::Schema.execute(query_str)
102
+ assert_equal "Trombone", response["data"]["addInstrument"]["instrument"]["name"]
103
+ assert_equal "BRASS", response["data"]["addInstrument"]["instrument"]["family"]
104
+ assert_equal "GraphQL::Query::Context::ExecutionErrors", response["data"]["addInstrument"]["ee"]
105
+ assert_equal 7, response["data"]["addInstrument"]["entries"].size
106
+ end
107
+ end
108
+
109
+ describe ".null" do
110
+ it "overrides whether or not the field can be null" do
111
+ non_nullable_mutation_class = Class.new(GraphQL::Schema::Mutation) do
112
+ graphql_name "Thing1"
113
+ null(false)
114
+ end
115
+
116
+ nullable_mutation_class = Class.new(GraphQL::Schema::Mutation) do
117
+ graphql_name "Thing2"
118
+ null(true)
119
+ end
120
+
121
+ default_mutation_class = Class.new(GraphQL::Schema::Mutation) do
122
+ graphql_name "Thing3"
123
+ end
124
+
125
+ assert default_mutation_class.field_options[:null]
126
+ assert nullable_mutation_class.field_options[:null]
127
+ refute non_nullable_mutation_class.field_options[:null]
128
+ end
129
+
130
+ it "should inherit and override in subclasses" do
131
+ base_mutation = Class.new(GraphQL::Schema::Mutation) do
132
+ null(false)
133
+ end
134
+
135
+ inheriting_mutation = Class.new(base_mutation) do
136
+ graphql_name "Thing"
137
+ end
138
+
139
+ override_mutation = Class.new(base_mutation) do
140
+ graphql_name "Thing2"
141
+ null(true)
142
+ end
143
+
144
+ assert_equal false, inheriting_mutation.field_options[:null]
145
+ assert override_mutation.field_options[:null]
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
3
+
4
+ describe GraphQL::Schema::Object do
5
+ describe "class attributes" do
6
+ let(:object_class) { Jazz::Ensemble }
7
+ it "tells type data" do
8
+ assert_equal "Ensemble", object_class.graphql_name
9
+ assert_equal "A group of musicians playing together", object_class.description
10
+ assert_equal 6, object_class.fields.size
11
+ assert_equal 3, object_class.interfaces.size
12
+ # Compatibility methods are delegated to the underlying BaseType
13
+ assert object_class.respond_to?(:connection_type)
14
+ end
15
+
16
+ it "inherits fields and interfaces" do
17
+ new_object_class = Class.new(object_class) do
18
+ field :newField, String, null: true
19
+ field :name, String, description: "The new description", null: true
20
+ end
21
+
22
+ # one more than the parent class
23
+ assert_equal 7, new_object_class.fields.size
24
+ # inherited interfaces are present
25
+ assert_equal 3, new_object_class.interfaces.size
26
+ # The new field is present
27
+ assert new_object_class.fields.key?("newField")
28
+ # The overridden field is present:
29
+ name_field = new_object_class.fields["name"]
30
+ assert_equal "The new description", name_field.description
31
+ end
32
+
33
+ it "inherits name and description" do
34
+ # Manually assign a name since `.name` isn't populated for dynamic classes
35
+ new_subclass_1 = Class.new(object_class) do
36
+ graphql_name "NewSubclass"
37
+ end
38
+ new_subclass_2 = Class.new(new_subclass_1)
39
+ assert_equal "NewSubclass", new_subclass_1.graphql_name
40
+ assert_equal "NewSubclass", new_subclass_2.graphql_name
41
+ assert_equal object_class.description, new_subclass_2.description
42
+ end
43
+
44
+ it "should take Ruby name (without Type suffix) as default graphql name" do
45
+ TestingClassType = Class.new(GraphQL::Schema::Object)
46
+ assert_equal "TestingClass", TestingClassType.graphql_name
47
+ end
48
+
49
+ it "raise on anonymous class without declared graphql name" do
50
+ anonymous_class = Class.new(GraphQL::Schema::Object)
51
+ assert_raises NotImplementedError do
52
+ anonymous_class.graphql_name
53
+ end
54
+ end
55
+ end
56
+
57
+ describe "wrapping a Hash" do
58
+ it "automatically looks up symbol and string keys" do
59
+ query_str = <<-GRAPHQL
60
+ {
61
+ hashyEnsemble {
62
+ musicians { name }
63
+ formedAt
64
+ }
65
+ }
66
+ GRAPHQL
67
+ res = Jazz::Schema.execute(query_str)
68
+ ensemble = res["data"]["hashyEnsemble"]
69
+ assert_equal ["Jerry Garcia"], ensemble["musicians"].map { |m| m["name"] }
70
+ assert_equal "May 5, 1965", ensemble["formedAt"]
71
+ end
72
+
73
+ it "works with strings and symbols" do
74
+ query_str = <<-GRAPHQL
75
+ {
76
+ hashByString { falsey }
77
+ hashBySym { falsey }
78
+ }
79
+ GRAPHQL
80
+ res = Jazz::Schema.execute(query_str)
81
+ assert_equal false, res["data"]["hashByString"]["falsey"]
82
+ assert_equal false, res["data"]["hashBySym"]["falsey"]
83
+ end
84
+ end
85
+
86
+ describe ".to_graphql_type" do
87
+ let(:obj_type) { Jazz::Ensemble.to_graphql }
88
+ it "returns a matching GraphQL::ObjectType" do
89
+ assert_equal "Ensemble", obj_type.name
90
+ assert_equal "A group of musicians playing together", obj_type.description
91
+ assert_equal 6, obj_type.all_fields.size
92
+
93
+ name_field = obj_type.all_fields[2]
94
+ assert_equal "name", name_field.name
95
+ assert_equal GraphQL::STRING_TYPE.to_non_null_type, name_field.type
96
+ assert_equal nil, name_field.description
97
+ end
98
+
99
+ it "has a custom implementation" do
100
+ assert_equal obj_type.metadata[:config], :configged
101
+ end
102
+
103
+ it "uses the custom field class" do
104
+ query_str = <<-GRAPHQL
105
+ {
106
+ ensembles { upcaseName }
107
+ }
108
+ GRAPHQL
109
+
110
+ res = Jazz::Schema.execute(query_str)
111
+ assert_equal ["BELA FLECK AND THE FLECKTONES", "ROBERT GLASPER EXPERIMENT"], res["data"]["ensembles"].map { |e| e["upcaseName"] }
112
+ end
113
+ end
114
+
115
+
116
+ describe "in queries" do
117
+ after {
118
+ Jazz::Models.reset
119
+ }
120
+
121
+ it "returns data" do
122
+ query_str = <<-GRAPHQL
123
+ {
124
+ ensembles { name }
125
+ instruments { name }
126
+ }
127
+ GRAPHQL
128
+ res = Jazz::Schema.execute(query_str)
129
+ expected_ensembles = [
130
+ {"name" => "Bela Fleck and the Flecktones"},
131
+ {"name" => "ROBERT GLASPER Experiment"},
132
+ ]
133
+ assert_equal expected_ensembles, res["data"]["ensembles"]
134
+ assert_equal({"name" => "Banjo"}, res["data"]["instruments"].first)
135
+ end
136
+
137
+ it "does mutations" do
138
+ mutation_str = <<-GRAPHQL
139
+ mutation AddEnsemble($name: String!) {
140
+ addEnsemble(input: { name: $name }) {
141
+ id
142
+ }
143
+ }
144
+ GRAPHQL
145
+
146
+ query_str = <<-GRAPHQL
147
+ query($id: ID!) {
148
+ find(id: $id) {
149
+ ... on Ensemble {
150
+ name
151
+ }
152
+ }
153
+ }
154
+ GRAPHQL
155
+
156
+ res = Jazz::Schema.execute(mutation_str, variables: { name: "Miles Davis Quartet" })
157
+ new_id = res["data"]["addEnsemble"]["id"]
158
+
159
+ res2 = Jazz::Schema.execute(query_str, variables: { id: new_id })
160
+ assert_equal "Miles Davis Quartet", res2["data"]["find"]["name"]
161
+ end
162
+
163
+ it "initializes root wrappers once" do
164
+ query_str = " { oid1: objectId oid2: objectId }"
165
+ res = Jazz::Schema.execute(query_str)
166
+ assert_equal res["data"]["oid1"], res["data"]["oid2"]
167
+ end
168
+
169
+ it "skips fields properly" do
170
+ query_str = "{ find(id: \"MagicalSkipId\") { __typename } }"
171
+ res = Jazz::Schema.execute(query_str)
172
+ assert_equal({"data" => nil }, res.to_h)
173
+ end
174
+ end
175
+ end