disco_app 0.12.7.pre.puma.pre.3 → 0.18.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (354) hide show
  1. checksums.yaml +5 -5
  2. data/Rakefile +1 -5
  3. data/app/assets/components/disco_app/forms/model-form.es6.jsx +2 -7
  4. data/app/assets/images/disco_app/.keep +0 -0
  5. data/app/assets/images/disco_app/logo.png +0 -0
  6. data/app/assets/javascripts/disco_app/components/custom/shop_row.js.jsx +2 -1
  7. data/app/assets/javascripts/disco_app/components/ui-kit/forms/base_form.es6.jsx +16 -44
  8. data/app/assets/javascripts/disco_app/components/ui-kit/forms/input-checkbox.es6.jsx +10 -5
  9. data/app/clients/disco_app/api_client.rb +25 -19
  10. data/app/clients/disco_app/graphql_client.rb +85 -0
  11. data/app/controllers/disco_app/admin/app_settings_controller.rb +2 -0
  12. data/app/controllers/disco_app/admin/application_controller.rb +3 -1
  13. data/app/controllers/disco_app/admin/concerns/app_settings_controller.rb +2 -1
  14. data/app/controllers/disco_app/admin/concerns/authenticated_controller.rb +5 -3
  15. data/app/controllers/disco_app/admin/concerns/plans_controller.rb +3 -2
  16. data/app/controllers/disco_app/admin/concerns/shops_controller.rb +1 -0
  17. data/app/controllers/disco_app/admin/concerns/sources_controller.rb +52 -0
  18. data/app/controllers/disco_app/admin/concerns/subscriptions_controller.rb +3 -2
  19. data/app/controllers/disco_app/admin/plans_controller.rb +2 -0
  20. data/app/controllers/disco_app/admin/resources/shops_controller.rb +2 -0
  21. data/app/controllers/disco_app/admin/shops_controller.rb +2 -0
  22. data/app/controllers/disco_app/admin/sources_controller.rb +5 -0
  23. data/app/controllers/disco_app/admin/subscriptions_controller.rb +2 -0
  24. data/app/controllers/disco_app/charges_controller.rb +12 -8
  25. data/app/controllers/disco_app/concerns/app_proxy_controller.rb +6 -6
  26. data/app/controllers/disco_app/concerns/authenticated_controller.rb +31 -23
  27. data/app/controllers/disco_app/concerns/carrier_request_controller.rb +22 -11
  28. data/app/controllers/disco_app/concerns/user_authenticated_controller.rb +18 -0
  29. data/app/controllers/disco_app/concerns/webhooks_controller.rb +49 -0
  30. data/app/controllers/disco_app/flow/actions_controller.rb +9 -0
  31. data/app/controllers/disco_app/flow/concerns/actions_controller.rb +23 -0
  32. data/app/controllers/disco_app/flow/concerns/trigger_usage_controller.rb +29 -0
  33. data/app/controllers/disco_app/flow/concerns/verifies_flow_payload.rb +39 -0
  34. data/app/controllers/disco_app/flow/trigger_usage_controller.rb +9 -0
  35. data/app/controllers/disco_app/frame_controller.rb +0 -1
  36. data/app/controllers/disco_app/install_controller.rb +3 -6
  37. data/app/controllers/disco_app/subscriptions_controller.rb +12 -4
  38. data/app/controllers/disco_app/user_sessions_controller.rb +58 -0
  39. data/app/controllers/disco_app/webhooks_controller.rb +2 -43
  40. data/app/controllers/sessions_controller.rb +5 -6
  41. data/app/helpers/disco_app/application_helper.rb +7 -7
  42. data/app/jobs/application_job.rb +2 -0
  43. data/app/jobs/disco_app/app_installed_job.rb +2 -0
  44. data/app/jobs/disco_app/app_uninstalled_job.rb +2 -0
  45. data/app/jobs/disco_app/concerns/app_installed_job.rb +3 -4
  46. data/app/jobs/disco_app/concerns/app_uninstalled_job.rb +2 -1
  47. data/app/jobs/disco_app/concerns/customers_data_request_job.rb +13 -0
  48. data/app/jobs/disco_app/concerns/customers_redact_job.rb +13 -0
  49. data/app/jobs/disco_app/concerns/render_asset_group_job.rb +2 -1
  50. data/app/jobs/disco_app/concerns/shop_redact_job.rb +13 -0
  51. data/app/jobs/disco_app/concerns/shop_update_job.rb +10 -3
  52. data/app/jobs/disco_app/concerns/subscription_changed_job.rb +2 -1
  53. data/app/jobs/disco_app/concerns/synchronise_carrier_service_job.rb +9 -8
  54. data/app/jobs/disco_app/concerns/synchronise_resources_job.rb +3 -6
  55. data/app/jobs/disco_app/concerns/synchronise_users_job.rb +18 -0
  56. data/app/jobs/disco_app/concerns/synchronise_webhooks_job.rb +48 -18
  57. data/app/jobs/disco_app/customers_data_request_job.rb +5 -0
  58. data/app/jobs/disco_app/customers_redact_job.rb +5 -0
  59. data/app/jobs/disco_app/flow/process_action_job.rb +11 -0
  60. data/app/jobs/disco_app/flow/process_trigger_job.rb +11 -0
  61. data/app/jobs/disco_app/render_asset_group_job.rb +2 -0
  62. data/app/jobs/disco_app/send_subscription_job.rb +1 -1
  63. data/app/jobs/disco_app/shop_job.rb +12 -5
  64. data/app/jobs/disco_app/shop_redact_job.rb +5 -0
  65. data/app/jobs/disco_app/shop_update_job.rb +2 -0
  66. data/app/jobs/disco_app/subscription_changed_job.rb +2 -0
  67. data/app/jobs/disco_app/synchronise_carrier_service_job.rb +2 -0
  68. data/app/jobs/disco_app/synchronise_resources_job.rb +2 -0
  69. data/app/jobs/disco_app/synchronise_users_job.rb +5 -0
  70. data/app/jobs/disco_app/synchronise_webhooks_job.rb +2 -0
  71. data/app/models/application_record.rb +5 -0
  72. data/app/models/disco_app/app_settings.rb +3 -1
  73. data/app/models/disco_app/application_charge.rb +8 -2
  74. data/app/models/disco_app/concerns/app_settings.rb +2 -0
  75. data/app/models/disco_app/concerns/can_be_liquified.rb +34 -18
  76. data/app/models/disco_app/concerns/has_metafields.rb +100 -44
  77. data/app/models/disco_app/concerns/plan.rb +15 -7
  78. data/app/models/disco_app/concerns/plan_code.rb +5 -3
  79. data/app/models/disco_app/concerns/renders_assets.rb +15 -21
  80. data/app/models/disco_app/concerns/shop.rb +39 -16
  81. data/app/models/disco_app/concerns/source.rb +13 -0
  82. data/app/models/disco_app/concerns/subscription.rb +14 -7
  83. data/app/models/disco_app/concerns/synchronises.rb +16 -16
  84. data/app/models/disco_app/concerns/taggable.rb +8 -3
  85. data/app/models/disco_app/concerns/user.rb +21 -0
  86. data/app/models/disco_app/flow/action.rb +9 -0
  87. data/app/models/disco_app/flow/concerns/action.rb +27 -0
  88. data/app/models/disco_app/flow/concerns/trigger.rb +28 -0
  89. data/app/models/disco_app/flow/concerns/trigger_usage.rb +17 -0
  90. data/app/models/disco_app/flow/trigger.rb +9 -0
  91. data/app/models/disco_app/flow/trigger_usage.rb +9 -0
  92. data/app/models/disco_app/plan.rb +3 -1
  93. data/app/models/disco_app/plan_code.rb +3 -1
  94. data/app/models/disco_app/recurring_application_charge.rb +9 -2
  95. data/app/models/disco_app/session_storage.rb +5 -2
  96. data/app/models/disco_app/shop.rb +3 -1
  97. data/app/models/disco_app/source.rb +5 -0
  98. data/app/models/disco_app/subscription.rb +3 -1
  99. data/app/models/disco_app/user.rb +5 -0
  100. data/app/resources/disco_app/admin/resources/concerns/shop_resource.rb +16 -19
  101. data/app/resources/disco_app/admin/resources/shop_resource.rb +1 -0
  102. data/app/services/disco_app/carrier_request_service.rb +3 -3
  103. data/app/services/disco_app/charges_service.rb +28 -38
  104. data/app/services/disco_app/flow/create_action.rb +35 -0
  105. data/app/services/disco_app/flow/create_trigger.rb +34 -0
  106. data/app/services/disco_app/flow/process_action.rb +50 -0
  107. data/app/services/disco_app/flow/process_trigger.rb +72 -0
  108. data/app/services/disco_app/flow/update_trigger_usage.rb +42 -0
  109. data/app/services/disco_app/partner_app_service.rb +151 -0
  110. data/app/services/disco_app/proxy_service.rb +2 -2
  111. data/app/services/disco_app/request_validation_service.rb +2 -2
  112. data/app/services/disco_app/subscription_service.rb +62 -28
  113. data/app/services/disco_app/synchronise_resources_service.rb +54 -0
  114. data/app/services/disco_app/webhook_service.rb +9 -11
  115. data/app/views/disco_app/admin/sources/_form.html.erb +34 -0
  116. data/app/views/disco_app/admin/sources/edit.html.erb +7 -0
  117. data/app/views/disco_app/admin/sources/index.html.erb +32 -0
  118. data/app/views/disco_app/admin/sources/new.html.erb +7 -0
  119. data/app/views/disco_app/user_sessions/new.html.erb +12 -0
  120. data/app/views/layouts/admin/_nav_items.erb +7 -0
  121. data/app/views/layouts/admin.html.erb +1 -2
  122. data/app/views/layouts/application.html.erb +1 -2
  123. data/app/views/layouts/embedded_app.html.erb +2 -4
  124. data/app/views/layouts/embedded_app_modal.html.erb +2 -3
  125. data/app/views/shopify_app/sessions/new.html.erb +2 -4
  126. data/config/routes.rb +15 -3
  127. data/db/migrate/20150525000000_create_shops_if_not_existent.rb +81 -81
  128. data/db/migrate/20170315062548_create_disco_app_sources.rb +12 -0
  129. data/db/migrate/20170315062629_add_sources_to_shop_subscriptions.rb +16 -0
  130. data/db/migrate/20170327214540_create_disco_app_users.rb +14 -0
  131. data/db/migrate/20170606160751_fix_disco_app_users_index.rb +8 -0
  132. data/db/migrate/20181229100327_create_flow_actions_and_triggers.rb +32 -0
  133. data/db/migrate/20200405000000_create_flow_trigger_usages.rb +16 -0
  134. data/lib/disco_app/configuration.rb +12 -5
  135. data/lib/disco_app/constants.rb +4 -2
  136. data/lib/disco_app/engine.rb +1 -1
  137. data/lib/disco_app/session.rb +1 -0
  138. data/lib/disco_app/support/file_fixtures.rb +2 -1
  139. data/lib/disco_app/version.rb +3 -1
  140. data/lib/generators/disco_app/install/USAGE +5 -0
  141. data/lib/generators/disco_app/install/install_generator.rb +297 -0
  142. data/lib/generators/disco_app/{templates → install/templates}/assets/javascripts/application.js +0 -0
  143. data/lib/generators/disco_app/{templates → install/templates}/assets/javascripts/components.js +0 -0
  144. data/lib/generators/disco_app/{templates → install/templates}/assets/stylesheets/application.scss +0 -0
  145. data/lib/generators/disco_app/install/templates/config/appsignal.yml +12 -0
  146. data/lib/generators/disco_app/install/templates/config/cable.yml.tt +11 -0
  147. data/lib/generators/disco_app/{templates → install/templates}/config/database.yml.tt +7 -3
  148. data/lib/generators/disco_app/install/templates/config/environments/staging.rb +108 -0
  149. data/lib/generators/disco_app/{templates → install/templates}/config/puma.rb +0 -0
  150. data/lib/generators/disco_app/{templates → install/templates}/controllers/home_controller.rb +1 -0
  151. data/lib/generators/disco_app/{templates → install/templates}/initializers/disco_app.rb +5 -0
  152. data/lib/generators/disco_app/install/templates/initializers/session_store.rb +2 -0
  153. data/lib/generators/disco_app/install/templates/initializers/shopify_app.rb +11 -0
  154. data/lib/generators/disco_app/{templates → install/templates}/initializers/shopify_session_repository.rb +2 -1
  155. data/lib/generators/disco_app/install/templates/initializers/timber.rb +4 -0
  156. data/lib/generators/disco_app/install/templates/root/.editorconfig +9 -0
  157. data/lib/generators/disco_app/install/templates/root/.env +27 -0
  158. data/lib/generators/disco_app/install/templates/root/.env.local +29 -0
  159. data/lib/generators/disco_app/install/templates/root/.github/PULL_REQUEST_TEMPLATE.md +18 -0
  160. data/lib/generators/disco_app/install/templates/root/.gitignore +65 -0
  161. data/lib/generators/disco_app/install/templates/root/.rspec +1 -0
  162. data/lib/generators/disco_app/install/templates/root/.rubocop.yml +758 -0
  163. data/lib/generators/disco_app/install/templates/root/.tool-versions +2 -0
  164. data/lib/generators/disco_app/{templates → install/templates}/root/CHECKS +0 -0
  165. data/lib/generators/disco_app/{templates → install/templates}/root/Procfile +0 -0
  166. data/lib/generators/disco_app/install/templates/root/README.md +26 -0
  167. data/lib/generators/disco_app/install/templates/root/package.json.tt +17 -0
  168. data/lib/generators/disco_app/install/templates/spec/rails_helper.rb +40 -0
  169. data/lib/generators/disco_app/install/templates/spec/spec_helper.rb +24 -0
  170. data/lib/generators/disco_app/install/templates/spec/support/active_job.rb +13 -0
  171. data/lib/generators/disco_app/install/templates/spec/support/coveralls.rb +3 -0
  172. data/lib/generators/disco_app/install/templates/spec/support/database_cleaner.rb +17 -0
  173. data/lib/generators/disco_app/install/templates/spec/support/factory_bot.rb +3 -0
  174. data/lib/generators/disco_app/install/templates/spec/support/helpers/json_helper.rb +13 -0
  175. data/lib/generators/disco_app/install/templates/spec/support/shared_examples/a_synchronise_job.rb +12 -0
  176. data/lib/generators/disco_app/install/templates/spec/support/shoulda.rb +6 -0
  177. data/lib/generators/disco_app/install/templates/spec/support/vcr.rb +14 -0
  178. data/lib/generators/disco_app/install/templates/spec/support/webmock.rb +8 -0
  179. data/lib/generators/disco_app/{templates → install/templates}/views/home/index.html.erb +0 -0
  180. data/lib/generators/disco_app/react/USAGE +5 -0
  181. data/lib/generators/disco_app/react/react_generator.rb +108 -0
  182. data/lib/generators/disco_app/react/templates/app/controllers/embedded/api/base_controller.rb +18 -0
  183. data/lib/generators/disco_app/react/templates/app/controllers/embedded/api/home_controller.rb +10 -0
  184. data/lib/generators/disco_app/react/templates/app/controllers/embedded/api/shops_controller.rb +11 -0
  185. data/lib/generators/disco_app/react/templates/app/controllers/embedded/api/users_controller.rb +11 -0
  186. data/lib/generators/disco_app/react/templates/app/controllers/embedded/home_controller.rb +13 -0
  187. data/lib/generators/disco_app/react/templates/app/models/api_response.rb +107 -0
  188. data/lib/generators/disco_app/react/templates/app/serializers/disco_app/shop_serializer.rb +13 -0
  189. data/lib/generators/disco_app/react/templates/app/serializers/disco_app/user_serializer.rb +13 -0
  190. data/lib/generators/disco_app/react/templates/app/serializers/empty_serializer.rb +5 -0
  191. data/lib/generators/disco_app/react/templates/app/serializers/error_serializer.rb +76 -0
  192. data/lib/generators/disco_app/react/templates/app/views/embedded/home/index.html.erb +12 -0
  193. data/lib/generators/disco_app/react/templates/app/views/layouts/embedded.html.erb +10 -0
  194. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/App.jsx +77 -0
  195. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/HomePage.jsx +34 -0
  196. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/Shared/EmbeddedPage.jsx +70 -0
  197. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/Shared/ErrorBanner.jsx +58 -0
  198. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/Shared/PaginationWrapper.jsx +10 -0
  199. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/Shared/ScrollToTop.jsx +23 -0
  200. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/components/withApi.jsx +125 -0
  201. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/index.jsx +39 -0
  202. data/lib/generators/disco_app/react/templates/app/webpack/javascripts/embedded/utils.js +19 -0
  203. data/lib/generators/disco_app/react/templates/app/webpack/packs/embedded.js +2 -0
  204. data/lib/generators/disco_app/react/templates/app/webpack/stylesheets/embedded/shared/banners.scss +7 -0
  205. data/lib/generators/disco_app/react/templates/app/webpack/stylesheets/embedded/shared/busy.scss +3 -0
  206. data/lib/generators/disco_app/react/templates/app/webpack/stylesheets/embedded/shared/index.scss +3 -0
  207. data/lib/generators/disco_app/react/templates/app/webpack/stylesheets/embedded/shared/pagination.scss +5 -0
  208. data/lib/generators/disco_app/react/templates/app/webpack/stylesheets/embedded.scss +2 -0
  209. data/lib/generators/disco_app/react/templates/config/initializers/mime_types.rb +13 -0
  210. data/lib/generators/disco_app/react/templates/config/initializers/omniauth.rb +27 -0
  211. data/lib/generators/disco_app/react/templates/config/initializers/version.rb.tt +7 -0
  212. data/lib/generators/disco_app/react/templates/config/webpack/staging.js +5 -0
  213. data/lib/generators/disco_app/react/templates/config/webpack/test.js +5 -0
  214. data/lib/generators/disco_app/react/templates/config/webpacker.yml +96 -0
  215. data/lib/generators/disco_app/react/templates/root/.eslintignore +5 -0
  216. data/lib/generators/disco_app/react/templates/root/.eslintrc +69 -0
  217. data/lib/generators/disco_app/react/templates/root/.prettierrc +3 -0
  218. data/lib/generators/disco_app/react/templates/root/VERSION +1 -0
  219. data/lib/generators/disco_app/react/templates/root/babel.config.js +72 -0
  220. data/lib/generators/disco_app/react/templates/root/package.json.tt +84 -0
  221. data/lib/generators/disco_app/react/templates/root/postcss.config.js +14 -0
  222. data/lib/tasks/api.rake +0 -2
  223. data/lib/tasks/carrier_service.rake +0 -2
  224. data/lib/tasks/database.rake +1 -1
  225. data/lib/tasks/partner_app.rake +26 -0
  226. data/lib/tasks/sessions.rake +0 -2
  227. data/lib/tasks/shops.rake +0 -2
  228. data/lib/tasks/users.rake +8 -0
  229. data/lib/tasks/webhooks.rake +0 -2
  230. data/test/clients/disco_app/api_client_test.rb +3 -3
  231. data/test/controllers/disco_app/admin/shops_controller_test.rb +1 -0
  232. data/test/controllers/disco_app/charges_controller_test.rb +19 -21
  233. data/test/controllers/disco_app/flow/trigger_usage_controller_test.rb +41 -0
  234. data/test/controllers/disco_app/install_controller_test.rb +2 -1
  235. data/test/controllers/disco_app/subscriptions_controller_test.rb +6 -5
  236. data/test/controllers/disco_app/webhooks_controller_test.rb +6 -5
  237. data/test/controllers/home_controller_test.rb +2 -2
  238. data/test/controllers/proxy_controller_test.rb +3 -3
  239. data/test/disco_app_test.rb +3 -1
  240. data/test/dummy/Rakefile +1 -1
  241. data/test/dummy/app/assets/config/manifest.js +2 -0
  242. data/test/dummy/app/controllers/application_controller.rb +2 -0
  243. data/test/dummy/app/controllers/carrier_request_controller.rb +1 -0
  244. data/test/dummy/app/controllers/disco_app/admin/shops_controller.rb +2 -1
  245. data/test/dummy/app/controllers/home_controller.rb +1 -0
  246. data/test/dummy/app/controllers/proxy_controller.rb +2 -1
  247. data/test/dummy/app/javascript/packs/application.js +18 -0
  248. data/test/dummy/app/jobs/application_job.rb +2 -0
  249. data/test/dummy/app/jobs/carts_update_job.rb +1 -1
  250. data/test/dummy/app/jobs/disco_app/app_installed_job.rb +2 -3
  251. data/test/dummy/app/jobs/disco_app/app_uninstalled_job.rb +3 -2
  252. data/test/dummy/app/jobs/products_create_job.rb +1 -1
  253. data/test/dummy/app/jobs/products_delete_job.rb +1 -1
  254. data/test/dummy/app/jobs/products_update_job.rb +1 -1
  255. data/test/dummy/app/models/application_record.rb +5 -0
  256. data/test/dummy/app/models/cart.rb +8 -7
  257. data/test/dummy/app/models/disco_app/shop.rb +8 -6
  258. data/test/dummy/app/models/js_configuration.rb +2 -1
  259. data/test/dummy/app/models/product.rb +4 -3
  260. data/test/dummy/app/models/widget_configuration.rb +2 -1
  261. data/test/dummy/babel.config.js +72 -0
  262. data/test/dummy/bin/bundle +1 -1
  263. data/test/dummy/bin/rails +1 -1
  264. data/test/dummy/bin/setup +8 -8
  265. data/test/dummy/bin/webpack +19 -0
  266. data/test/dummy/bin/webpack-dev-server +19 -0
  267. data/test/dummy/config/application.rb +3 -5
  268. data/test/dummy/config/boot.rb +2 -2
  269. data/test/dummy/config/database.yml +4 -0
  270. data/test/dummy/config/environment.rb +1 -1
  271. data/test/dummy/config/environments/staging.rb +85 -0
  272. data/test/dummy/config/environments/test.rb +2 -2
  273. data/test/dummy/config/initializers/disco_app.rb +8 -1
  274. data/test/dummy/config/initializers/omniauth.rb +3 -4
  275. data/test/dummy/config/initializers/session_store.rb +1 -1
  276. data/test/dummy/config/initializers/shopify_app.rb +1 -0
  277. data/test/dummy/config/initializers/shopify_session_repository.rb +1 -1
  278. data/test/dummy/config/routes.rb +0 -2
  279. data/test/dummy/config/secrets.yml +3 -0
  280. data/test/dummy/config/webpack/development.js +5 -0
  281. data/test/dummy/config/webpack/environment.js +3 -0
  282. data/test/dummy/config/webpack/production.js +5 -0
  283. data/test/dummy/config/webpack/test.js +5 -0
  284. data/test/dummy/config/webpacker.yml +95 -0
  285. data/test/dummy/db/migrate/20160307182229_create_products.rb +3 -1
  286. data/test/dummy/db/migrate/20160530160739_create_asset_models.rb +3 -1
  287. data/test/dummy/db/migrate/20161105054746_create_carts.rb +3 -1
  288. data/test/dummy/db/schema.rb +141 -88
  289. data/test/dummy/package.json +10 -0
  290. data/test/dummy/postcss.config.js +12 -0
  291. data/test/dummy/yarn.lock +7278 -0
  292. data/test/fixtures/api/subscriptions/valid_request.json +2 -2
  293. data/test/fixtures/api/widget_store/charges/{activate_application_charge_request.json → get_active_application_charge_response.json} +1 -1
  294. data/test/fixtures/api/widget_store/charges/{activate_recurring_application_charge_request.json → get_active_recurring_application_charge_response.json} +2 -2
  295. data/test/fixtures/api/widget_store/empty_webhooks.json +3 -0
  296. data/test/fixtures/api/widget_store/existing_webhooks.json +43 -0
  297. data/test/fixtures/api/widget_store/products/get_metafields_empty_response.json +3 -0
  298. data/test/fixtures/api/widget_store/products/get_metafields_with_existing_response.json +11 -0
  299. data/test/fixtures/api/widget_store/products/write_metafields_multiple_namespaces_request.json +4 -0
  300. data/test/fixtures/api/widget_store/products/write_metafields_single_namespace_request.json +2 -0
  301. data/test/fixtures/api/widget_store/products/write_metafields_with_existing_single_namespace_request.json +21 -0
  302. data/test/fixtures/api/widget_store/{charges/activate_application_charge_response.json → products/write_metafields_with_existing_single_namespace_response.json} +0 -0
  303. data/test/fixtures/api/widget_store/shops/get_metafields_with_existing_response.json +11 -0
  304. data/test/fixtures/api/widget_store/shops/write_metafields_with_existing_first_request.json +9 -0
  305. data/test/fixtures/api/widget_store/{charges/activate_recurring_application_charge_response.json → shops/write_metafields_with_existing_first_response.json} +0 -0
  306. data/test/fixtures/api/widget_store/shops/write_metafields_with_existing_second_request.json +9 -0
  307. data/test/fixtures/api/widget_store/shops/write_metafields_with_existing_second_response.json +1 -0
  308. data/test/fixtures/api/widget_store/users.json +42 -0
  309. data/test/fixtures/disco_app/shops.yml +9 -2
  310. data/test/fixtures/disco_app/sources.yml +3 -0
  311. data/test/fixtures/liquid/model.liquid +8 -8
  312. data/test/fixtures/webhooks/flow/trigger_usage.json +7 -0
  313. data/test/integration/synchronises_test.rb +20 -13
  314. data/test/jobs/disco_app/app_installed_job_test.rb +30 -11
  315. data/test/jobs/disco_app/app_uninstalled_job_test.rb +5 -2
  316. data/test/jobs/disco_app/send_subscription_job_test.rb +3 -2
  317. data/test/jobs/disco_app/synchronise_carrier_service_job_test.rb +1 -0
  318. data/test/jobs/disco_app/synchronise_users_job_test.rb +27 -0
  319. data/test/jobs/disco_app/synchronise_webhooks_job_test.rb +78 -9
  320. data/test/models/disco_app/can_be_liquified_test.rb +3 -1
  321. data/test/models/disco_app/has_metafields_test.rb +109 -20
  322. data/test/models/disco_app/renders_assets_test.rb +2 -1
  323. data/test/models/disco_app/session_test.rb +2 -2
  324. data/test/models/disco_app/shop_test.rb +1 -1
  325. data/test/services/disco_app/charges_service_test.rb +10 -14
  326. data/test/services/disco_app/flow/create_action_test.rb +51 -0
  327. data/test/services/disco_app/flow/create_trigger_test.rb +56 -0
  328. data/test/services/disco_app/flow/process_action_test.rb +68 -0
  329. data/test/services/disco_app/flow/process_trigger_test.rb +94 -0
  330. data/test/services/disco_app/flow/update_trigger_usage_test.rb +87 -0
  331. data/test/services/disco_app/subscription_service_test.rb +3 -2
  332. data/test/services/disco_app/synchronise_resources_service_test.rb +57 -0
  333. data/test/support/test_file_fixtures.rb +2 -2
  334. data/test/support/test_shopify_api.rb +1 -1
  335. data/test/test_helper.rb +24 -6
  336. data/test/vcr/flow_trigger_invalid_title.yml +35 -0
  337. data/test/vcr/flow_trigger_valid.yml +38 -0
  338. data/test/vcr/synchronise_products.yml +130 -0
  339. data/test/vcr/synchronise_products_paginated.yml +119 -0
  340. data/test/vcr/synchronise_products_since_id.yml +125 -0
  341. data/test/vcr/synchronise_products_with_params.yml +130 -0
  342. data/test/vcr/webhook_failure.yml +640 -0
  343. metadata +388 -142
  344. data/app/clients/disco_app/disco_api_error.rb +0 -2
  345. data/lib/generators/disco_app/USAGE +0 -5
  346. data/lib/generators/disco_app/disco_app_generator.rb +0 -236
  347. data/lib/generators/disco_app/templates/config/newrelic.yml +0 -26
  348. data/lib/generators/disco_app/templates/initializers/rollbar.rb +0 -23
  349. data/lib/generators/disco_app/templates/initializers/session_store.rb +0 -2
  350. data/lib/generators/disco_app/templates/initializers/shopify_app.rb +0 -6
  351. data/test/dummy/config/database.gitlab-ci.yml +0 -24
  352. data/test/fixtures/api/widget_store/charges/get_accepted_application_charge_response.json +0 -16
  353. data/test/fixtures/api/widget_store/charges/get_accepted_recurring_application_charge_response.json +0 -20
  354. data/test/fixtures/api/widget_store/webhooks.json +0 -1
@@ -1,30 +1,99 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class DiscoApp::SynchroniseWebhooksJobTest < ActionController::TestCase
4
+
4
5
  include ActiveJob::TestHelper
5
6
 
6
7
  def setup
7
8
  @shop = disco_app_shops(:widget_store)
8
-
9
- stub_request(:get, "#{@shop.admin_url}/webhooks.json").to_return(status: 200, body: api_fixture('widget_store/webhooks').to_json)
10
- stub_request(:post, "#{@shop.admin_url}/webhooks.json").to_return(status: 200)
11
9
  end
12
10
 
13
11
  def teardown
14
12
  @shop = nil
15
-
16
13
  WebMock.reset!
17
14
  end
18
15
 
19
16
  test 'webhook synchronisation job creates webhooks for all expected topics' do
20
- perform_enqueued_jobs do
21
- DiscoApp::SynchroniseWebhooksJob.perform_later(@shop)
17
+ with_suppressed_output do
18
+ stub_request(:get, "#{@shop.admin_url}/webhooks.json").to_return(status: 200, body: api_fixture('widget_store/empty_webhooks').to_json)
19
+ stub_request(:post, "#{@shop.admin_url}/webhooks.json").to_return(status: 200)
20
+
21
+ perform_enqueued_jobs do
22
+ DiscoApp::SynchroniseWebhooksJob.perform_later(@shop)
23
+ end
24
+
25
+ # Assert that all 3 webhook topics without field lists were POSTed to.
26
+ ['app/uninstalled', 'shop/update', 'orders/create'].each do |expected_webhook_topic|
27
+ assert_requested(:post, "#{@shop.admin_url}/webhooks.json", times: 1) do |request|
28
+ request.body.include?(%Q("topic":"#{expected_webhook_topic}")) && request.body.include?('"fields":[]')
29
+ end
30
+ end
31
+
32
+ # Assert that the orders/paid webhook topic was posted to with a field restriction.
33
+ assert_requested(:post, "#{@shop.admin_url}/webhooks.json", times: 1) do |request|
34
+ request.body.include?('"topic":"orders/paid"') && request.body.include?('"fields":["id"]')
35
+ end
22
36
  end
37
+ end
38
+
39
+ test 'webhook synchronisation job only creates and updates webhooks when required' do
40
+ with_suppressed_output do
41
+ stub_request(:get, "#{@shop.admin_url}/webhooks.json").to_return(status: 200, body: api_fixture('widget_store/existing_webhooks').to_json)
42
+ stub_request(:put, "#{@shop.admin_url}/webhooks/748073353266.json").to_return(status: 200)
43
+ stub_request(:put, "#{@shop.admin_url}/webhooks/748073353267.json").to_return(status: 200)
44
+ stub_request(:post, "#{@shop.admin_url}/webhooks.json").to_return(status: 200)
45
+
46
+ perform_enqueued_jobs do
47
+ DiscoApp::SynchroniseWebhooksJob.perform_later(@shop)
48
+ end
49
+
50
+ # Assert that a missing webhook was created.
51
+ assert_requested(:post, "#{@shop.admin_url}/webhooks.json", times: 1) do |request|
52
+ request.body.include?('"topic":"app/uninstalled"')
53
+ end
23
54
 
24
- # Assert that all 4 expected webhook topics were POSTed to.
25
- ['app/uninstalled', 'shop/update', 'orders/create', 'orders/paid'].each do |expected_webhook_topic|
26
- assert_requested(:post, "#{@shop.admin_url}/webhooks.json", times: 1) { |request| request.body.include?(expected_webhook_topic) }
55
+ # Assert that no request was made to update an existing webhook with the expected values.
56
+ assert_requested(:post, "#{@shop.admin_url}/webhooks.json", times: 0) do |request|
57
+ request.body.include?('"topic":"shop/update"')
58
+ end
59
+
60
+ # Assert that a request was made to update the URL of a webhook with an out of date URL.
61
+ assert_requested(:put, "#{@shop.admin_url}/webhooks/748073353266.json", times: 1) do |request|
62
+ request.body.include?('"topic":"orders/create"') && request.body.include?('"address":"https://test.example.com/webhooks"')
63
+ end
64
+
65
+ # Assert that a request was made to update the fields of a webhook with out of date fields.
66
+ assert_requested(:put, "#{@shop.admin_url}/webhooks/748073353267.json", times: 1) do |request|
67
+ request.body.include?('"topic":"orders/paid"') && request.body.include?('"fields":["id"]')
68
+ end
27
69
  end
28
70
  end
29
71
 
72
+ test 'returns error messages for webhooks that cannot be registered' do
73
+ VCR.use_cassette('webhook_failure') do
74
+ with_suppressed_output do
75
+ output = capture_io do
76
+ perform_enqueued_jobs do
77
+ DiscoApp::SynchroniseWebhooksJob.perform_later(@shop)
78
+ end
79
+ end
80
+
81
+ assert output.first.include?('Invalid topic specified.')
82
+ assert output.first.include?('orders/create - not registered')
83
+ end
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ # Prevents the output from the webhook synchronisation from
90
+ # printing to STDOUT and messing up the test output
91
+ def with_suppressed_output
92
+ original_stdout = $stdout.clone
93
+ $stdout.reopen(File.new('/dev/null', 'w'))
94
+ yield
95
+ ensure
96
+ $stdout.reopen(original_stdout)
97
+ end
98
+
30
99
  end
@@ -3,6 +3,7 @@ require 'test_helper'
3
3
  class DiscoApp::CanBeLiquifiedTest < ActiveSupport::TestCase
4
4
 
5
5
  class Model
6
+
6
7
  include ActiveModel::Model
7
8
  include DiscoApp::Concerns::CanBeLiquified
8
9
 
@@ -17,6 +18,7 @@ class DiscoApp::CanBeLiquifiedTest < ActiveSupport::TestCase
17
18
  def liquid_model_name
18
19
  'model'
19
20
  end
21
+
20
22
  end
21
23
 
22
24
  def setup
@@ -48,7 +50,7 @@ class DiscoApp::CanBeLiquifiedTest < ActiveSupport::TestCase
48
50
 
49
51
  # Return an asset fixture as a string.
50
52
  def liquid_fixture(path)
51
- filename = File.join(File.dirname(File.dirname(File.dirname(__FILE__))), 'fixtures', 'liquid', "#{path}")
53
+ filename = File.join(File.dirname(File.dirname(File.dirname(__FILE__))), 'fixtures', 'liquid', path.to_s)
52
54
  File.read(filename).strip
53
55
  end
54
56
 
@@ -1,6 +1,7 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class DiscoApp::HasMetafieldsTest < ActiveSupport::TestCase
4
+
4
5
  include DiscoApp::Test::ShopifyAPI
5
6
 
6
7
  def setup
@@ -13,28 +14,116 @@ class DiscoApp::HasMetafieldsTest < ActiveSupport::TestCase
13
14
  @shop = nil
14
15
  end
15
16
 
16
- test 'can write metafields with a single namespace' do
17
- stub_api_request(:put, "#{@shop.admin_url}/products/#{@product.id}.json", 'widget_store/products/write_metafields_single_namespace')
18
- assert @shop.with_api_context { @product.write_metafields(
19
- namespace1: {
20
- key1: 'value1',
21
- key2: 2
22
- }
23
- ) }
17
+ test 'can write product metafields with a single namespace with no existing metafields' do
18
+ stub_api_request(
19
+ :get,
20
+ "#{@shop.admin_url}/products/#{@product.id}/metafields.json",
21
+ 'widget_store/products/get_metafields_empty'
22
+ )
23
+
24
+ stub_api_request(
25
+ :put,
26
+ "#{@shop.admin_url}/products/#{@product.id}.json",
27
+ 'widget_store/products/write_metafields_single_namespace'
28
+ )
29
+
30
+ assert(
31
+ @shop.with_api_context do
32
+ @product.write_metafields(
33
+ namespace1: {
34
+ key1: 'value1',
35
+ key2: 2
36
+ }
37
+ )
38
+ end
39
+ )
40
+ end
41
+
42
+ test 'can write product metafields, including json string type, with a single namespace with one existing metafield' do
43
+ stub_api_request(
44
+ :get,
45
+ "#{@shop.admin_url}/products/#{@product.id}/metafields.json",
46
+ 'widget_store/products/get_metafields_with_existing'
47
+ )
48
+
49
+ stub_api_request(
50
+ :put,
51
+ "#{@shop.admin_url}/products/#{@product.id}.json",
52
+ 'widget_store/products/write_metafields_with_existing_single_namespace'
53
+ )
54
+
55
+ assert(
56
+ @shop.with_api_context do
57
+ @product.write_metafields(
58
+ namespace1: {
59
+ key1: 'value1',
60
+ key2: {
61
+ 'json_key' => 'json_value'
62
+ }
63
+ }
64
+ )
65
+ end
66
+ )
67
+ end
68
+
69
+ test 'can write product metafields with multiple namespaces with no existing metafields' do
70
+ stub_api_request(
71
+ :get,
72
+ "#{@shop.admin_url}/products/#{@product.id}/metafields.json",
73
+ 'widget_store/products/get_metafields_empty'
74
+ )
75
+
76
+ stub_api_request(
77
+ :put,
78
+ "#{@shop.admin_url}/products/#{@product.id}.json",
79
+ 'widget_store/products/write_metafields_multiple_namespaces'
80
+ )
81
+
82
+ assert(
83
+ @shop.with_api_context do
84
+ @product.write_metafields(
85
+ namespace1: {
86
+ n1key1: 'value1',
87
+ n1key2: 2
88
+ },
89
+ namespace2: {
90
+ n2key3: 'value3',
91
+ n2key4: 2
92
+ }
93
+ )
94
+ end
95
+ )
24
96
  end
25
97
 
26
- test 'can write metafields with multiple namespaces' do
27
- stub_api_request(:put, "#{@shop.admin_url}/products/#{@product.id}.json", 'widget_store/products/write_metafields_multiple_namespaces')
28
- assert @shop.with_api_context { @product.write_metafields(
29
- namespace1: {
30
- n1key1: 'value1',
31
- n1key2: 2
32
- },
33
- namespace2: {
34
- n2key3: 'value3',
35
- n2key4: 2
36
- },
37
- ) }
98
+ test 'can write shop metafields with one existing metafield' do
99
+ stub_api_request(
100
+ :get,
101
+ "#{@shop.admin_url}/metafields.json",
102
+ 'widget_store/shops/get_metafields_with_existing'
103
+ )
104
+
105
+ stub_api_request(
106
+ :put,
107
+ "#{@shop.admin_url}/metafields/874857827343.json",
108
+ 'widget_store/shops/write_metafields_with_existing_first'
109
+ )
110
+
111
+ stub_api_request(
112
+ :post,
113
+ "#{@shop.admin_url}/metafields.json",
114
+ 'widget_store/shops/write_metafields_with_existing_second'
115
+ )
116
+
117
+ assert(
118
+ @shop.with_api_context do
119
+ @shop.write_metafields(
120
+ namespace1: {
121
+ key1: 'value1',
122
+ key2: 2
123
+ }
124
+ )
125
+ end
126
+ )
38
127
  end
39
128
 
40
129
  end
@@ -1,6 +1,7 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class DiscoApp::RendersAssetsTest < ActiveSupport::TestCase
4
+
4
5
  include ActiveJob::TestHelper
5
6
  include DiscoApp::Test::ShopifyAPI
6
7
 
@@ -102,7 +103,7 @@ class DiscoApp::RendersAssetsTest < ActiveSupport::TestCase
102
103
 
103
104
  # Return an asset fixture as a string.
104
105
  def asset_fixture(path)
105
- filename = File.join(File.dirname(File.dirname(File.dirname(__FILE__))), 'fixtures', 'assets', "#{path}")
106
+ filename = File.join(File.dirname(File.dirname(File.dirname(__FILE__))), 'fixtures', 'assets', path.to_s)
106
107
  File.read(filename)
107
108
  end
108
109
 
@@ -7,8 +7,8 @@ class DiscoApp::SessionTest < ActiveSupport::TestCase
7
7
  @session = DiscoApp::Session.create(
8
8
  session_id: 'a91bfc51fa79c9d09d43e2615d9345d4',
9
9
  data: {
10
- :shopify => @shop.id,
11
- :shopify_domain => @shop.shopify_domain
10
+ shopify: @shop.id,
11
+ shopify_domain: @shop.shopify_domain
12
12
  }
13
13
  )
14
14
  end
@@ -25,7 +25,7 @@ class DiscoApp::ShopTest < ActiveSupport::TestCase
25
25
  end
26
26
 
27
27
  test 'time_zone helper returns correct time zone instance when known timezone defined' do
28
- assert_equal 'Melbourne', @shop.time_zone.name
28
+ assert_equal 'Australia/Melbourne', @shop.time_zone.name
29
29
  end
30
30
 
31
31
  test 'time_zone helper returns default Rails timezone when no known timezone defined' do
@@ -1,6 +1,7 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class DiscoApp::ChargesServiceTest < ActiveSupport::TestCase
4
+
4
5
  include DiscoApp::Test::ShopifyAPI
5
6
 
6
7
  def setup
@@ -30,15 +31,13 @@ class DiscoApp::ChargesServiceTest < ActiveSupport::TestCase
30
31
  end
31
32
 
32
33
  test 'creating a new charge for a recurring subscription is successful' do
33
- res = { "recurring_application_charge": { "name": "Basic",
34
- "price": "9.99",
35
- "trial_days": 14,
36
- "return_url": /^https:\/\/test\.example\.com\/subscriptions\/304261385\/charges\/53297050(1|2)\/activate$/,
37
- "test": true
38
- } }
34
+ res = { "recurring_application_charge": { "name": 'Basic',
35
+ "price": '9.99',
36
+ "trial_days": 14,
37
+ "return_url": %r{^https://test\.example\.com/subscriptions/304261385/charges/53297050(1|2)/activate$},
38
+ "test": true } }
39
39
  stub_request(:post, "#{@shop.admin_url}/recurring_application_charges.json")
40
- .with(body: res
41
- ).to_return(status: 201, body:api_fixture("widget_store/charges/create_recurring_application_charge_response").to_json)
40
+ .with(body: res).to_return(status: 201, body: api_fixture('widget_store/charges/create_recurring_application_charge_response').to_json)
42
41
 
43
42
  new_charge = DiscoApp::ChargesService.create(@shop, @subscription)
44
43
  assert_equal 654381179, new_charge.shopify_id
@@ -58,8 +57,7 @@ class DiscoApp::ChargesServiceTest < ActiveSupport::TestCase
58
57
  end
59
58
 
60
59
  test 'activating an accepted recurring charge is successful and cancels any existing recurring charges' do
61
- stub_api_request(:get, "#{@shop.admin_url}/recurring_application_charges/654381179.json", 'widget_store/charges/get_accepted_recurring_application_charge')
62
- stub_api_request(:post, "#{@shop.admin_url}/recurring_application_charges/654381179/activate.json", 'widget_store/charges/activate_recurring_application_charge')
60
+ stub_api_request(:get, "#{@shop.admin_url}/recurring_application_charges/654381179.json", 'widget_store/charges/get_active_recurring_application_charge')
63
61
 
64
62
  old_charge = @subscription.active_charge
65
63
  assert old_charge.active?
@@ -72,8 +70,7 @@ class DiscoApp::ChargesServiceTest < ActiveSupport::TestCase
72
70
  end
73
71
 
74
72
  test 'activating an accepted recurring charge cancels other recurring charges' do
75
- stub_api_request(:get, "#{@shop.admin_url}/recurring_application_charges/654381179.json", 'widget_store/charges/get_accepted_recurring_application_charge')
76
- stub_api_request(:post, "#{@shop.admin_url}/recurring_application_charges/654381179/activate.json", 'widget_store/charges/activate_recurring_application_charge')
73
+ stub_api_request(:get, "#{@shop.admin_url}/recurring_application_charges/654381179.json", 'widget_store/charges/get_active_recurring_application_charge')
77
74
 
78
75
  assert DiscoApp::ChargesService.activate(@shop, @new_charge)
79
76
  assert @new_charge.active?
@@ -102,8 +99,7 @@ class DiscoApp::ChargesServiceTest < ActiveSupport::TestCase
102
99
  end
103
100
 
104
101
  test 'activating an accepted one-time charge is successful' do
105
- stub_api_request(:get, "#{@dev_shop.admin_url}/application_charges/1012637323.json", 'widget_store/charges/get_accepted_application_charge')
106
- stub_api_request(:post, "#{@dev_shop.admin_url}/application_charges/1012637323/activate.json", 'widget_store/charges/activate_application_charge')
102
+ stub_api_request(:get, "#{@dev_shop.admin_url}/application_charges/1012637323.json", 'widget_store/charges/get_active_application_charge')
107
103
 
108
104
  assert DiscoApp::ChargesService.activate(@dev_shop, @dev_new_charge)
109
105
  assert @dev_new_charge.active?
@@ -0,0 +1,51 @@
1
+ require 'test_helper'
2
+
3
+ module DiscoApp
4
+ module Flow
5
+ class CreateActionTest < ActiveSupport::TestCase
6
+
7
+ include ActiveJob::TestHelper
8
+
9
+ def setup
10
+ @shop = disco_app_shops(:widget_store)
11
+ end
12
+
13
+ def teardown
14
+ @shop = nil
15
+ end
16
+
17
+ test 'call to create flow action creates model' do
18
+ result = CreateAction.call(shop: @shop, action_id: action_id, action_run_id: action_run_id, properties: properties)
19
+ assert result.success?
20
+ assert result.action.persisted?
21
+ assert result.action.pending?
22
+ assert_equal action_id, result.action.action_id
23
+ assert_equal action_run_id, result.action.action_run_id
24
+ assert_equal properties, result.action.properties
25
+ end
26
+
27
+ test 'call to create flow action enqueues processing job' do
28
+ assert_enqueued_with(job: ProcessActionJob) do
29
+ CreateAction.call(shop: @shop, action_id: action_id, action_run_id: action_run_id, properties: properties)
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def action_id
36
+ 'test_action_id'
37
+ end
38
+
39
+ def action_run_id
40
+ 'bdb15e45-4f9d-4c80-88c8-7b43a24edaac-30892-cc8eb62a-14db-43fc-bc33-d6dea41ae623'
41
+ end
42
+
43
+ def properties
44
+ {
45
+ 'customer_email' => 'name@example.com'
46
+ }
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,56 @@
1
+ require 'test_helper'
2
+
3
+ module DiscoApp
4
+ module Flow
5
+ class CreateTriggerTest < ActiveSupport::TestCase
6
+
7
+ include ActiveJob::TestHelper
8
+
9
+ def setup
10
+ @shop = disco_app_shops(:widget_store)
11
+ end
12
+
13
+ def teardown
14
+ @shop = nil
15
+ end
16
+
17
+ test 'call to create flow trigger creates model' do
18
+ result = CreateTrigger.call(shop: @shop, title: title, resource_name: resource_name, resource_url: resource_url, properties: properties)
19
+ assert result.success?
20
+ assert result.trigger.persisted?
21
+ assert result.trigger.pending?
22
+ assert_equal title, result.trigger.title
23
+ assert_equal resource_name, result.trigger.resource_name
24
+ assert_equal resource_url, result.trigger.resource_url
25
+ assert_equal properties, result.trigger.properties
26
+ end
27
+
28
+ test 'call to create flow trigger enqueues processing job' do
29
+ assert_enqueued_with(job: ProcessTriggerJob) do
30
+ CreateTrigger.call(shop: @shop, title: title, resource_name: resource_name, resource_url: resource_url, properties: properties)
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def title
37
+ 'Test trigger'
38
+ end
39
+
40
+ def resource_name
41
+ 'test_resource_name'
42
+ end
43
+
44
+ def resource_url
45
+ 'https://example.com/test-resource-url'
46
+ end
47
+
48
+ def properties
49
+ {
50
+ 'Customer email' => 'name@example.com'
51
+ }
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,68 @@
1
+ require 'test_helper'
2
+ require 'interactor'
3
+
4
+ class TestActionId
5
+
6
+ include Interactor
7
+
8
+ def call
9
+ # noop
10
+ end
11
+
12
+ end
13
+
14
+ module DiscoApp
15
+ module Flow
16
+ class ProcessActionTest < ActiveSupport::TestCase
17
+
18
+ include ActiveJob::TestHelper
19
+
20
+ def setup
21
+ @shop = disco_app_shops(:widget_store)
22
+ @action = @shop.flow_actions.create(
23
+ action_id: 'test_action_id',
24
+ action_run_id: 'bdb15e45-4f9d-4c80-88c8-7b43a24edaac-30892-cc8eb62a-14db-43fc-bc33-d6dea41ae623',
25
+ properties: { 'customer_email' => 'name@example.com' }
26
+ )
27
+ @now = Time.zone.parse('2018-12-29T00:00:00Z')
28
+ Timecop.freeze(@now)
29
+ end
30
+
31
+ def teardown
32
+ @shop = nil
33
+ @action = nil
34
+ @now = nil
35
+ Timecop.return
36
+ end
37
+
38
+ test 'call to process action that has already succeeded fails' do
39
+ @action.succeeded!
40
+ result = ProcessAction.call(action: @action)
41
+ assert_not result.success?
42
+ end
43
+
44
+ test 'call to process trigger that has already failed fails' do
45
+ @action.failed!
46
+ result = ProcessAction.call(action: @action)
47
+ assert_not result.success?
48
+ end
49
+
50
+ test 'processing pending action with existing service class succeeds' do
51
+ result = ProcessAction.call(action: @action)
52
+ assert result.success?
53
+ assert @action.succeeded?
54
+ assert_equal @now, @action.processed_at
55
+ end
56
+
57
+ test 'processing pending action with non-existent service class does not succeed' do
58
+ @action.update!(action_id: 'unknown_test_action_id')
59
+ result = ProcessAction.call(action: @action)
60
+ assert_not result.success?
61
+ assert @action.failed?
62
+ assert_equal @now, @action.processed_at
63
+ assert_equal ['Could not find service class for unknown_test_action_id'], @action.processing_errors
64
+ end
65
+
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,94 @@
1
+ require 'test_helper'
2
+
3
+ module DiscoApp
4
+ module Flow
5
+ class ProcessTriggerTest < ActiveSupport::TestCase
6
+
7
+ include ActiveJob::TestHelper
8
+
9
+ def setup
10
+ @shop = disco_app_shops(:widget_store)
11
+ @trigger = @shop.flow_triggers.create(
12
+ title: 'Test trigger',
13
+ resource_name: 'test_resource_name',
14
+ resource_url: 'https://example.com/test-resource-url',
15
+ properties: { 'Customer email' => 'name@example.com' }
16
+ )
17
+ @now = Time.zone.parse('2018-12-29T00:00:00Z')
18
+ Timecop.freeze(@now)
19
+ end
20
+
21
+ def teardown
22
+ @shop = nil
23
+ @trigger = nil
24
+ @now = nil
25
+ Timecop.return
26
+ end
27
+
28
+ test 'call to process trigger that has already succeeded fails' do
29
+ @trigger.succeeded!
30
+ result = ProcessTrigger.call(trigger: @trigger)
31
+ assert_not result.success?
32
+ end
33
+
34
+ test 'call to process trigger that has already failed fails' do
35
+ @trigger.failed!
36
+ result = ProcessTrigger.call(trigger: @trigger)
37
+ assert_not result.success?
38
+ end
39
+
40
+ test 'call to process trigger that has already been skipped fails' do
41
+ @trigger.skipped!
42
+ result = ProcessTrigger.call(trigger: @trigger)
43
+ assert_not result.success?
44
+ end
45
+
46
+ test 'call to process trigger that we know is not being used succeeds with skipped status logged' do
47
+ @shop.flow_trigger_usages.create(
48
+ flow_trigger_definition_id: @trigger.title,
49
+ has_enabled_flow: false,
50
+ timestamp: @now
51
+ )
52
+ result = ProcessTrigger.call(trigger: @trigger)
53
+ assert result.success?
54
+ assert @trigger.skipped?
55
+ assert_equal @now, @trigger.processed_at
56
+ end
57
+
58
+ test 'processing valid pending trigger succeeds and makes the expected api call' do
59
+ VCR.use_cassette('flow_trigger_valid') do
60
+ result = ProcessTrigger.call(trigger: @trigger)
61
+ assert result.success?
62
+ assert @trigger.succeeded?
63
+ assert_equal @now, @trigger.processed_at
64
+ end
65
+ end
66
+
67
+ test 'processing valid pending trigger that we know is being used succeeds and makes the expected api call' do
68
+ @shop.flow_trigger_usages.create(
69
+ flow_trigger_definition_id: @trigger.title,
70
+ has_enabled_flow: true,
71
+ timestamp: @now
72
+ )
73
+
74
+ VCR.use_cassette('flow_trigger_valid') do
75
+ result = ProcessTrigger.call(trigger: @trigger)
76
+ assert result.success?
77
+ assert @trigger.succeeded?
78
+ assert_equal @now, @trigger.processed_at
79
+ end
80
+ end
81
+
82
+ test 'processing invalid pending trigger makes the expected api call with errors logged' do
83
+ VCR.use_cassette('flow_trigger_invalid_title') do
84
+ result = ProcessTrigger.call(trigger: @trigger)
85
+ assert_not result.success?
86
+ assert @trigger.failed?
87
+ assert_equal @now, @trigger.processed_at
88
+ assert_equal 1, @trigger.processing_errors.size
89
+ end
90
+ end
91
+
92
+ end
93
+ end
94
+ end