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
@@ -48,6 +48,47 @@ describe GraphQL::Query::Variables do
48
48
  end
49
49
  end
50
50
 
51
+ describe "symbol keys" do
52
+ let(:query_string) { <<-GRAPHQL
53
+ query testVariables(
54
+ $dairy_product_1: DairyProductInput!
55
+ $dairy_product_2: DairyProductInput!
56
+ ) {
57
+ __typename
58
+ }
59
+ GRAPHQL
60
+ }
61
+
62
+ let(:provided_variables) {
63
+ {
64
+ dairy_product_1: { source: "COW", fatContent: 0.99 },
65
+ "dairy_product_2" => { source: "DONKEY", "fatContent": 0.89 },
66
+ }
67
+ }
68
+
69
+ it "checks for string matches" do
70
+ # These get merged into all the values above
71
+ default_values = {
72
+ "originDairy"=>"Sugar Hollow Dairy",
73
+ "organic"=>false,
74
+ "order_by"=>{"direction"=>"ASC"}
75
+ }
76
+
77
+ expected_input_1 = {
78
+ "source" => 1,
79
+ "fatContent" => 0.99,
80
+ }.merge(default_values)
81
+
82
+ assert_equal(expected_input_1, variables["dairy_product_1"].to_h)
83
+
84
+ expected_input_2 = {
85
+ "source" => :donkey,
86
+ "fatContent" => 0.89,
87
+ }.merge(default_values)
88
+ assert_equal(expected_input_2, variables["dairy_product_2"].to_h)
89
+ end
90
+ end
91
+
51
92
  describe "validating input objects" do
52
93
  let(:query_string) {%|
53
94
  query searchMyDairy (
@@ -111,7 +152,7 @@ describe GraphQL::Query::Variables do
111
152
  let(:provided_variables) { { "ids" => [nil] } }
112
153
  it "returns an error" do
113
154
  assert_equal 1, result["errors"].length
114
- assert_equal nil, result["data"]
155
+ assert_nil result["data"]
115
156
  end
116
157
  end
117
158
  end
@@ -85,7 +85,7 @@ describe GraphQL::Query do
85
85
  operation_name: operation_name,
86
86
  max_depth: max_depth,
87
87
  )
88
- query.query_string = '{ __type(name: "Cheese") { name } }'
88
+ query.query_string = '{ __type(name: """Cheese""") { name } }'
89
89
  assert_equal "Cheese", query.result["data"] ["__type"]["name"]
90
90
  end
91
91
  end
@@ -111,7 +111,7 @@ describe GraphQL::Query do
111
111
  }
112
112
 
113
113
  it "returns nil" do
114
- assert_equal nil, query.operation_name
114
+ assert_nil query.operation_name
115
115
  end
116
116
  end
117
117
 
@@ -148,7 +148,7 @@ describe GraphQL::Query do
148
148
  }
149
149
 
150
150
  it "returns the inferred operation name" do
151
- assert_equal nil, query.selected_operation_name
151
+ assert_nil query.selected_operation_name
152
152
  end
153
153
  end
154
154
  end
@@ -253,6 +253,32 @@ describe GraphQL::Query do
253
253
  assert_equal [nil], Instrumenter::ERROR_LOG
254
254
  end
255
255
  end
256
+
257
+ describe "when an error propagated through execution" do
258
+ module ExtensionsInstrumenter
259
+ LOG = []
260
+ def self.before_query(q); end;
261
+
262
+ def self.after_query(q)
263
+ q.result["extensions"] = { "a" => 1 }
264
+ LOG << :ok
265
+ end
266
+ end
267
+
268
+ let(:schema) {
269
+ Dummy::Schema.redefine {
270
+ instrument(:query, ExtensionsInstrumenter)
271
+ }
272
+ }
273
+
274
+ it "can add to extensions" do
275
+ ExtensionsInstrumenter::LOG.clear
276
+ assert_raises(RuntimeError) do
277
+ schema.execute "{ error }"
278
+ end
279
+ assert_equal [:ok], ExtensionsInstrumenter::LOG
280
+ end
281
+ end
256
282
  end
257
283
 
258
284
  it "uses root_value as the object for the root type" do
@@ -532,7 +558,7 @@ describe GraphQL::Query do
532
558
 
533
559
  it "overrides the schema's max_depth" do
534
560
  assert result["data"].key?("cheese")
535
- assert_equal nil, result["errors"]
561
+ assert_nil result["errors"]
536
562
  end
537
563
  end
538
564
  end
@@ -699,7 +725,7 @@ describe GraphQL::Query do
699
725
 
700
726
  it "returns nil when there is no selected operation" do
701
727
  query = GraphQL::Query.new(schema, '# Only a comment')
702
- assert_equal nil, query.irep_selection
728
+ assert_nil query.irep_selection
703
729
  end
704
730
  end
705
731
 
@@ -34,7 +34,9 @@ describe GraphQL::RakeTask do
34
34
  end
35
35
  dumped_json = File.read("./schema.json")
36
36
  expected_json = JSON.pretty_generate(RakeTaskSchema.execute(GraphQL::Introspection::INTROSPECTION_QUERY))
37
- assert_equal(expected_json, dumped_json)
37
+
38
+ # Test that that JSON is logically equivalent, not serialized the same
39
+ assert_equal(JSON.parse(expected_json), JSON.parse(dumped_json))
38
40
 
39
41
  dumped_idl = File.read("./schema.graphql")
40
42
  expected_idl = rake_task_schema_defn.chomp
@@ -38,7 +38,7 @@ describe GraphQL::Relay::BaseConnection do
38
38
  first: nil,
39
39
  }
40
40
  conn = GraphQL::Relay::BaseConnection.new([], args, context: context)
41
- assert_equal nil, conn.first
41
+ assert_nil conn.first
42
42
  end
43
43
  end
44
44
 
@@ -12,7 +12,7 @@ describe GraphQL::Relay::ConnectionInstrumentation do
12
12
  end
13
13
 
14
14
  it "keeps a reference to the function" do
15
- conn_field = StarWars::Faction.fields["shipsWithMaxPageSize"]
15
+ conn_field = StarWars::Faction.graphql_definition.fields["shipsWithMaxPageSize"]
16
16
  assert_instance_of StarWars::ShipsWithMaxPageSize, conn_field.function
17
17
  end
18
18
 
@@ -77,7 +77,7 @@ describe GraphQL::Relay::ConnectionInstrumentation do
77
77
  # Before the object is wrapped in a connection, the instrumentation sees `Array`
78
78
  assert_equal ["StarWars::FactionRecord", "Array", "GraphQL::Relay::ArrayConnection"], ctx[:before_built_ins]
79
79
  # After the object is wrapped in a connection, it sees the connection object
80
- assert_equal ["StarWars::FactionRecord", "GraphQL::Relay::ArrayConnection", "GraphQL::Relay::ArrayConnection"], ctx[:after_built_ins]
80
+ assert_equal ["StarWars::Faction", "GraphQL::Relay::ArrayConnection", "GraphQL::Relay::ArrayConnection"], ctx[:after_built_ins]
81
81
  end
82
82
  end
83
83
  end
@@ -57,7 +57,7 @@ describe GraphQL::Relay::ConnectionResolve do
57
57
  it "becomes null" do
58
58
  result = star_wars_query(query_string, { "name" => "null" })
59
59
  conn = result["data"]["rebels"]["ships"]
60
- assert_equal nil, conn
60
+ assert_nil conn
61
61
  end
62
62
  end
63
63
  end
@@ -73,7 +73,7 @@ describe GraphQL::Relay::ConnectionType do
73
73
 
74
74
  it "nullifies the parent and adds an error" do
75
75
  result = star_wars_query(query_string)
76
- assert_equal nil, result["data"]["basesWithNullName"]["edges"][0]["node"]
76
+ assert_nil result["data"]["basesWithNullName"]["edges"][0]["node"]
77
77
  assert_equal "Boom!", result["errors"][0]["message"]
78
78
  end
79
79
  end
@@ -0,0 +1,474 @@
1
+ # frozen_string_literal: true
2
+ require 'spec_helper'
3
+
4
+ describe GraphQL::Relay::RelationConnection do
5
+ def get_names(result)
6
+ ships = result["data"]["federation"]["bases"]["edges"]
7
+ ships.map { |e| e["node"]["name"] }
8
+ end
9
+
10
+ def get_page_info(result)
11
+ result["data"]["federation"]["bases"]["pageInfo"]
12
+ end
13
+
14
+ def get_first_cursor(result)
15
+ result["data"]["federation"]["bases"]["edges"].first["cursor"]
16
+ end
17
+
18
+ def get_last_cursor(result)
19
+ result["data"]["federation"]["bases"]["edges"].last["cursor"]
20
+ end
21
+
22
+ describe "results" do
23
+ let(:query_string) {%|
24
+ query getShips($first: Int, $after: String, $last: Int, $before: String, $nameIncludes: String){
25
+ federation {
26
+ bases(first: $first, after: $after, last: $last, before: $before, nameIncludes: $nameIncludes) {
27
+ ... basesConnection
28
+ }
29
+ }
30
+ }
31
+
32
+ fragment basesConnection on BasesConnectionWithTotalCount {
33
+ totalCount,
34
+ edges {
35
+ cursor
36
+ node {
37
+ name
38
+ }
39
+ },
40
+ pageInfo {
41
+ hasNextPage
42
+ hasPreviousPage
43
+ startCursor
44
+ endCursor
45
+ }
46
+ }
47
+ |}
48
+
49
+ it 'limits the result' do
50
+ result = star_trek_query(query_string, "first" => 2)
51
+ assert_equal(2, get_names(result).length)
52
+ assert_equal(true, get_page_info(result)["hasNextPage"])
53
+ assert_equal(false, get_page_info(result)["hasPreviousPage"])
54
+ assert_equal("MQ==", get_page_info(result)["startCursor"])
55
+ assert_equal("Mg==", get_page_info(result)["endCursor"])
56
+ assert_equal("MQ==", get_first_cursor(result))
57
+ assert_equal("Mg==", get_last_cursor(result))
58
+
59
+ result = star_trek_query(query_string, "first" => 3)
60
+ assert_equal(3, get_names(result).length)
61
+ assert_equal(false, get_page_info(result)["hasNextPage"])
62
+ assert_equal(false, get_page_info(result)["hasPreviousPage"])
63
+ assert_equal("MQ==", get_page_info(result)["startCursor"])
64
+ assert_equal("Mw==", get_page_info(result)["endCursor"])
65
+ assert_equal("MQ==", get_first_cursor(result))
66
+ assert_equal("Mw==", get_last_cursor(result))
67
+ end
68
+
69
+ it 'provides custom fields on the connection type' do
70
+ result = star_trek_query(query_string, "first" => 2)
71
+ assert_equal(
72
+ StarTrek::Base.where(faction_id: 1).count,
73
+ result["data"]["federation"]["bases"]["totalCount"]
74
+ )
75
+ end
76
+
77
+ it "provides bidirectional_pagination" do
78
+ result = star_trek_query(query_string, "first" => 1)
79
+ last_cursor = get_last_cursor(result)
80
+
81
+ result = star_trek_query(query_string, "first" => 1, "after" => last_cursor)
82
+ assert_equal true, get_page_info(result)["hasNextPage"]
83
+ assert_equal false, get_page_info(result)["hasPreviousPage"]
84
+
85
+ result = with_bidirectional_pagination {
86
+ star_trek_query(query_string, "first" => 1, "after" => last_cursor)
87
+ }
88
+ assert_equal true, get_page_info(result)["hasNextPage"]
89
+ assert_equal true, get_page_info(result)["hasPreviousPage"]
90
+
91
+ last_cursor = get_last_cursor(result)
92
+ result = with_bidirectional_pagination {
93
+ star_trek_query(query_string, "last" => 1, "before" => last_cursor)
94
+ }
95
+ assert_equal true, get_page_info(result)["hasNextPage"]
96
+ assert_equal false, get_page_info(result)["hasPreviousPage"]
97
+
98
+ result = star_trek_query(query_string, "first" => 100)
99
+ last_cursor = get_last_cursor(result)
100
+
101
+ result = star_trek_query(query_string, "last" => 1, "before" => last_cursor)
102
+ assert_equal false, get_page_info(result)["hasNextPage"]
103
+ assert_equal true, get_page_info(result)["hasPreviousPage"]
104
+
105
+ result = with_bidirectional_pagination {
106
+ star_trek_query(query_string, "last" => 1, "before" => last_cursor)
107
+ }
108
+ assert_equal true, get_page_info(result)["hasNextPage"]
109
+ assert_equal true, get_page_info(result)["hasPreviousPage"]
110
+ end
111
+
112
+ it 'slices the result' do
113
+ result = star_trek_query(query_string, "first" => 2)
114
+ assert_equal(["Deep Space Station K-7", "Regula I"], get_names(result))
115
+
116
+ # After the last result, find the next 2:
117
+ last_cursor = get_last_cursor(result)
118
+
119
+ result = star_trek_query(query_string, "after" => last_cursor, "first" => 2)
120
+ assert_equal(["Deep Space Nine"], get_names(result))
121
+
122
+ last_cursor = get_last_cursor(result)
123
+
124
+ result = star_trek_query(query_string, "before" => last_cursor, "last" => 1)
125
+ assert_equal(["Regula I"], get_names(result))
126
+
127
+ result = star_trek_query(query_string, "before" => last_cursor, "last" => 2)
128
+ assert_equal(["Deep Space Station K-7", "Regula I"], get_names(result))
129
+
130
+ result = star_trek_query(query_string, "before" => last_cursor, "last" => 10)
131
+ assert_equal(["Deep Space Station K-7", "Regula I"], get_names(result))
132
+
133
+ result = star_trek_query(query_string, "last" => 2)
134
+ assert_equal(["Regula I", "Deep Space Nine"], get_names(result))
135
+
136
+ result = star_trek_query(query_string, "last" => 10)
137
+ assert_equal(["Deep Space Station K-7", "Regula I", "Deep Space Nine"], get_names(result))
138
+ assert_equal(false, result["data"]["federation"]["bases"]["pageInfo"]["hasNextPage"])
139
+ assert_equal(false, result["data"]["federation"]["bases"]["pageInfo"]["hasPreviousPage"])
140
+ end
141
+
142
+ it 'works with before and after specified together' do
143
+ result = star_trek_query(query_string, "first" => 2)
144
+ assert_equal(["Deep Space Station K-7", "Regula I"], get_names(result))
145
+
146
+ first_cursor = get_last_cursor(result)
147
+
148
+ # There is no records between before and after if they point to the same cursor
149
+ result = star_trek_query(query_string, "before" => first_cursor, "after" => first_cursor, "last" => 2)
150
+ assert_equal([], get_names(result))
151
+
152
+ result = star_trek_query(query_string, "after" => first_cursor, "first" => 2)
153
+ assert_equal(["Deep Space Nine"], get_names(result))
154
+
155
+ second_cursor = get_last_cursor(result)
156
+
157
+ result = star_trek_query(query_string, "after" => first_cursor, "before" => second_cursor, "first" => 3)
158
+ assert_equal([], get_names(result)) # TODO: test fails. fixme
159
+ end
160
+
161
+ it 'handles cursors above the bounds of the array' do
162
+ overreaching_cursor = Base64.strict_encode64("100")
163
+ result = star_trek_query(query_string, "after" => overreaching_cursor, "first" => 2)
164
+ assert_equal([], get_names(result))
165
+ end
166
+
167
+ it 'handles cursors below the bounds of the array' do
168
+ underreaching_cursor = Base64.strict_encode64("1")
169
+ result = star_trek_query(query_string, "before" => underreaching_cursor, "first" => 2)
170
+ assert_equal([], get_names(result))
171
+ end
172
+
173
+
174
+ it 'handles grouped connections with only last argument' do
175
+ grouped_conn_query = <<-GRAPHQL
176
+ query {
177
+ newestBasesGroupedByFaction(last: 2) {
178
+ edges {
179
+ node {
180
+ name
181
+ }
182
+ }
183
+ }
184
+ }
185
+ GRAPHQL
186
+
187
+ result = star_trek_query(grouped_conn_query)
188
+ names = result['data']['newestBasesGroupedByFaction']['edges'].map { |edge| edge['node']['name'] }
189
+ assert_equal(['Ganalda Space Station', 'Deep Space Nine'], names)
190
+ end
191
+
192
+ it "applies custom arguments" do
193
+ result = star_trek_query(query_string, "first" => 1, "nameIncludes" => "eep")
194
+ assert_equal(["Deep Space Station K-7"], get_names(result))
195
+
196
+ after = get_last_cursor(result)
197
+
198
+ result = star_trek_query(query_string, "first" => 2, "nameIncludes" => "eep", "after" => after )
199
+ assert_equal(["Deep Space Nine"], get_names(result))
200
+ before = get_last_cursor(result)
201
+
202
+ result = star_trek_query(query_string, "last" => 1, "nameIncludes" => "eep", "before" => before)
203
+ assert_equal(["Deep Space Station K-7"], get_names(result))
204
+ end
205
+
206
+ it 'works without first/last/after/before' do
207
+ result = star_trek_query(query_string)
208
+
209
+ assert_equal(3, result["data"]["federation"]["bases"]["edges"].length)
210
+ end
211
+
212
+ describe "applying max_page_size" do
213
+ let(:query_string) {%|
214
+ query getBases($first: Int, $after: String, $last: Int, $before: String){
215
+ federation {
216
+ bases: basesWithMaxLimitRelation(first: $first, after: $after, last: $last, before: $before) {
217
+ ... basesConnection
218
+ }
219
+ }
220
+ }
221
+
222
+ fragment basesConnection on BaseConnection {
223
+ edges {
224
+ cursor
225
+ node {
226
+ name
227
+ }
228
+ },
229
+ pageInfo {
230
+ hasNextPage
231
+ hasPreviousPage
232
+ startCursor
233
+ endCursor
234
+ }
235
+ }
236
+ |}
237
+
238
+ it "applies to queries by `first`" do
239
+ result = star_trek_query(query_string, "first" => 100)
240
+ assert_equal(2, result["data"]["federation"]["bases"]["edges"].size)
241
+ assert_equal(true, result["data"]["federation"]["bases"]["pageInfo"]["hasNextPage"])
242
+
243
+ # Max page size is applied _without_ `first`, also
244
+ result = star_trek_query(query_string)
245
+ assert_equal(2, result["data"]["federation"]["bases"]["edges"].size)
246
+ assert_equal(false, result["data"]["federation"]["bases"]["pageInfo"]["hasNextPage"], "hasNextPage is false when first is not specified")
247
+ end
248
+
249
+ it "applies to queries by `last`" do
250
+ second_to_last_two_names = ["Firebase P'ok", "Ganalda Space Station"]
251
+ first_and_second_names = ["Deep Space Station K-7", "Regula I"]
252
+
253
+ last_cursor = "Ng=="
254
+ result = star_trek_query(query_string, "last" => 100, "before" => last_cursor)
255
+ assert_equal(second_to_last_two_names, get_names(result))
256
+ assert_equal(true, result["data"]["federation"]["bases"]["pageInfo"]["hasPreviousPage"])
257
+
258
+ result = star_trek_query(query_string, "before" => last_cursor)
259
+ assert_equal(first_and_second_names, get_names(result))
260
+ assert_equal(false, result["data"]["federation"]["bases"]["pageInfo"]["hasPreviousPage"], "hasPreviousPage is false when last is not specified")
261
+
262
+ third_cursor = "Mw=="
263
+ result = star_trek_query(query_string, "last" => 100, "before" => third_cursor)
264
+ assert_equal(first_and_second_names, get_names(result))
265
+
266
+ result = star_trek_query(query_string, "before" => third_cursor)
267
+ assert_equal(first_and_second_names, get_names(result))
268
+ end
269
+ end
270
+
271
+ describe "applying default_max_page_size" do
272
+ let(:query_string) {%|
273
+ query getBases($first: Int, $after: String, $last: Int, $before: String){
274
+ federation {
275
+ bases: basesWithDefaultMaxLimitRelation(first: $first, after: $after, last: $last, before: $before) {
276
+ ... basesConnection
277
+ }
278
+ }
279
+ }
280
+
281
+ fragment basesConnection on BaseConnection {
282
+ edges {
283
+ cursor
284
+ node {
285
+ name
286
+ }
287
+ },
288
+ pageInfo {
289
+ hasNextPage
290
+ hasPreviousPage
291
+ startCursor
292
+ endCursor
293
+ }
294
+ }
295
+ |}
296
+
297
+ it "applies to queries by `first`" do
298
+ result = star_trek_query(query_string, "first" => 100)
299
+ assert_equal(3, result["data"]["federation"]["bases"]["edges"].size)
300
+ assert_equal(true, result["data"]["federation"]["bases"]["pageInfo"]["hasNextPage"])
301
+
302
+ # Max page size is applied _without_ `first`, also
303
+ result = star_trek_query(query_string)
304
+ assert_equal(3, result["data"]["federation"]["bases"]["edges"].size)
305
+ assert_equal(false, result["data"]["federation"]["bases"]["pageInfo"]["hasNextPage"], "hasNextPage is false when first is not specified")
306
+ end
307
+
308
+ it "applies to queries by `last`" do
309
+ second_to_last_three_names = ["Deep Space Nine", "Firebase P'ok", "Ganalda Space Station"]
310
+ first_second_and_third_names = ["Deep Space Station K-7", "Regula I", "Deep Space Nine"]
311
+
312
+ last_cursor = "Ng=="
313
+ result = star_trek_query(query_string, "last" => 100, "before" => last_cursor)
314
+ assert_equal(second_to_last_three_names, get_names(result))
315
+ assert_equal(true, result["data"]["federation"]["bases"]["pageInfo"]["hasPreviousPage"])
316
+
317
+ result = star_trek_query(query_string, "before" => last_cursor)
318
+ assert_equal(first_second_and_third_names, get_names(result))
319
+ assert_equal(false, result["data"]["federation"]["bases"]["pageInfo"]["hasPreviousPage"], "hasPreviousPage is false when last is not specified")
320
+
321
+ fourth_cursor = "NA=="
322
+ result = star_trek_query(query_string, "last" => 100, "before" => fourth_cursor)
323
+ assert_equal(first_second_and_third_names, get_names(result))
324
+
325
+ result = star_trek_query(query_string, "before" => fourth_cursor)
326
+ assert_equal(first_second_and_third_names, get_names(result))
327
+ end
328
+ end
329
+ end
330
+
331
+ describe "applying a max_page_size bigger than the results" do
332
+ let(:query_string) {%|
333
+ query getBases($first: Int, $after: String, $last: Int, $before: String){
334
+ federation {
335
+ bases: basesWithLargeMaxLimitRelation(first: $first, after: $after, last: $last, before: $before) {
336
+ ... basesConnection
337
+ }
338
+ }
339
+ }
340
+
341
+ fragment basesConnection on BaseConnection {
342
+ edges {
343
+ cursor
344
+ node {
345
+ name
346
+ }
347
+ },
348
+ pageInfo {
349
+ hasNextPage
350
+ hasPreviousPage
351
+ startCursor
352
+ endCursor
353
+ }
354
+ }
355
+ |}
356
+
357
+ it "applies to queries by `first`" do
358
+ result = star_trek_query(query_string, "first" => 100)
359
+ assert_equal(6, result["data"]["federation"]["bases"]["edges"].size)
360
+ assert_equal(false, result["data"]["federation"]["bases"]["pageInfo"]["hasNextPage"])
361
+
362
+ # Max page size is applied _without_ `first`, also
363
+ result = star_trek_query(query_string)
364
+ assert_equal(6, result["data"]["federation"]["bases"]["edges"].size)
365
+ assert_equal(false, result["data"]["federation"]["bases"]["pageInfo"]["hasNextPage"], "hasNextPage is false when first is not specified")
366
+ end
367
+
368
+ it "applies to queries by `last`" do
369
+ all_names = ["Deep Space Station K-7", "Regula I", "Deep Space Nine", "Firebase P'ok", "Ganalda Space Station", "Rh'Ihho Station"]
370
+
371
+ last_cursor = "Ng=="
372
+ result = star_trek_query(query_string, "last" => 100, "before" => last_cursor)
373
+ assert_equal(all_names[0..4], get_names(result))
374
+ assert_equal(false, result["data"]["federation"]["bases"]["pageInfo"]["hasPreviousPage"])
375
+
376
+ result = star_trek_query(query_string, "last" => 100)
377
+ assert_equal(all_names, get_names(result))
378
+ assert_equal(false, result["data"]["federation"]["bases"]["pageInfo"]["hasPreviousPage"])
379
+
380
+ result = star_trek_query(query_string, "before" => last_cursor)
381
+ assert_equal(all_names[0..4], get_names(result))
382
+ assert_equal(false, result["data"]["federation"]["bases"]["pageInfo"]["hasPreviousPage"], "hasPreviousPage is false when last is not specified")
383
+
384
+ fourth_cursor = "NA=="
385
+ result = star_trek_query(query_string, "last" => 100, "before" => fourth_cursor)
386
+ assert_equal(all_names[0..2], get_names(result))
387
+
388
+ result = star_trek_query(query_string, "before" => fourth_cursor)
389
+ assert_equal(all_names[0..2], get_names(result))
390
+ end
391
+ end
392
+
393
+ describe "without a block" do
394
+ let(:query_string) {%|
395
+ {
396
+ federation {
397
+ basesClone(first: 10) {
398
+ edges {
399
+ node {
400
+ name
401
+ }
402
+ }
403
+ }
404
+ }
405
+ }|}
406
+ it "uses default resolve" do
407
+ result = star_trek_query(query_string)
408
+ bases = result["data"]["federation"]["basesClone"]["edges"]
409
+ assert_equal(3, bases.length)
410
+ end
411
+ end
412
+
413
+ describe "custom ordering" do
414
+ let(:query_string) {%|
415
+ query getBases {
416
+ federation {
417
+ basesByName(first: 30) { ... basesFields }
418
+ bases(first: 30) { ... basesFields2 }
419
+ }
420
+ }
421
+ fragment basesFields on BaseConnection {
422
+ edges {
423
+ node {
424
+ name
425
+ }
426
+ }
427
+ }
428
+ fragment basesFields2 on BasesConnectionWithTotalCount {
429
+ edges {
430
+ node {
431
+ name
432
+ }
433
+ }
434
+ }
435
+ |}
436
+
437
+ def get_names(result, field_name)
438
+ bases = result["data"]["federation"][field_name]["edges"]
439
+ bases.map { |b| b["node"]["name"] }
440
+ end
441
+
442
+ it "applies the default value" do
443
+ result = star_trek_query(query_string)
444
+ bases_by_id = ["Deep Space Station K-7", "Regula I", "Deep Space Nine"]
445
+ bases_by_name = ["Deep Space Nine", "Deep Space Station K-7", "Regula I"]
446
+
447
+ assert_equal(bases_by_id, get_names(result, "bases"))
448
+ assert_equal(bases_by_name, get_names(result, "basesByName"))
449
+ end
450
+ end
451
+
452
+ describe "#cursor_from_node" do
453
+ let(:connection) { GraphQL::Relay::MongoRelationConnection.new(StarTrek::Base.where(faction_id: 1), {}) }
454
+
455
+ it "returns the cursor for a node in the connection" do
456
+ assert_equal "MQ==", connection.cursor_from_node(StarTrek::Base.all[0])
457
+ assert_equal "Mg==", connection.cursor_from_node(StarTrek::Base.all[1])
458
+ end
459
+
460
+ it "raises when the node isn't found" do
461
+ err = assert_raises(RuntimeError) {
462
+ connection.cursor_from_node(:not_found)
463
+ }
464
+ assert_includes err.message, "item not found"
465
+ end
466
+ end
467
+
468
+ it "is chosen for a relation" do
469
+ relation = StarTrek::Base.where(faction_id: 1)
470
+ assert relation.is_a?(Mongoid::Criteria)
471
+ connection = GraphQL::Relay::BaseConnection.connection_for_nodes(relation)
472
+ assert_equal GraphQL::Relay::MongoRelationConnection, connection
473
+ end
474
+ end