RecurlyEventHandlerTests.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. const SandboxedModule = require('sandboxed-module')
  2. const sinon = require('sinon')
  3. const modulePath =
  4. '../../../../app/src/Features/Subscription/RecurlyEventHandler'
  5. describe('RecurlyEventHandler', function () {
  6. beforeEach(function () {
  7. this.userId = '123abc234bcd456cde567def'
  8. this.planCode = 'collaborator-annual'
  9. this.eventData = {
  10. account: {
  11. account_code: this.userId,
  12. },
  13. subscription: {
  14. plan: {
  15. plan_code: 'collaborator-annual',
  16. },
  17. quantity: 1,
  18. state: 'active',
  19. trial_started_at: new Date('2021-01-01 12:34:56'),
  20. trial_ends_at: new Date('2021-01-08 12:34:56'),
  21. current_period_started_at: new Date('2021-01-01 12:34:56'),
  22. current_period_ends_at: new Date('2021-01-08 12:34:56'),
  23. },
  24. }
  25. this.RecurlyEventHandler = SandboxedModule.require(modulePath, {
  26. requires: {
  27. './SubscriptionEmailHandler': (this.SubscriptionEmailHandler = {
  28. sendTrialOnboardingEmail: sinon.stub(),
  29. }),
  30. '../Analytics/AnalyticsManager': (this.AnalyticsManager = {
  31. recordEventForUser: sinon.stub(),
  32. setUserPropertyForUser: sinon.stub(),
  33. }),
  34. },
  35. })
  36. })
  37. it('with new_subscription_notification - free trial', function () {
  38. this.RecurlyEventHandler.sendRecurlyAnalyticsEvent(
  39. 'new_subscription_notification',
  40. this.eventData
  41. )
  42. sinon.assert.calledWith(
  43. this.AnalyticsManager.recordEventForUser,
  44. this.userId,
  45. 'subscription-started',
  46. {
  47. plan_code: this.planCode,
  48. quantity: 1,
  49. is_trial: true,
  50. }
  51. )
  52. sinon.assert.calledWith(
  53. this.AnalyticsManager.setUserPropertyForUser,
  54. this.userId,
  55. 'subscription-plan-code',
  56. this.planCode
  57. )
  58. sinon.assert.calledWith(
  59. this.AnalyticsManager.setUserPropertyForUser,
  60. this.userId,
  61. 'subscription-state',
  62. 'active'
  63. )
  64. sinon.assert.calledWith(
  65. this.AnalyticsManager.setUserPropertyForUser,
  66. this.userId,
  67. 'subscription-is-trial',
  68. true
  69. )
  70. })
  71. it('sends free trial onboarding email if user starting a trial', async function () {
  72. await this.RecurlyEventHandler.sendRecurlyAnalyticsEvent(
  73. 'new_subscription_notification',
  74. this.eventData
  75. )
  76. sinon.assert.called(this.SubscriptionEmailHandler.sendTrialOnboardingEmail)
  77. })
  78. it('with new_subscription_notification - no free trial', function () {
  79. this.eventData.subscription.current_period_started_at = new Date(
  80. '2021-02-10 12:34:56'
  81. )
  82. this.eventData.subscription.current_period_ends_at = new Date(
  83. '2021-02-17 12:34:56'
  84. )
  85. this.eventData.subscription.quantity = 3
  86. this.RecurlyEventHandler.sendRecurlyAnalyticsEvent(
  87. 'new_subscription_notification',
  88. this.eventData
  89. )
  90. sinon.assert.calledWith(
  91. this.AnalyticsManager.recordEventForUser,
  92. this.userId,
  93. 'subscription-started',
  94. {
  95. plan_code: this.planCode,
  96. quantity: 3,
  97. is_trial: false,
  98. }
  99. )
  100. sinon.assert.calledWith(
  101. this.AnalyticsManager.setUserPropertyForUser,
  102. this.userId,
  103. 'subscription-state',
  104. 'active'
  105. )
  106. sinon.assert.calledWith(
  107. this.AnalyticsManager.setUserPropertyForUser,
  108. this.userId,
  109. 'subscription-is-trial',
  110. false
  111. )
  112. })
  113. it('with updated_subscription_notification', function () {
  114. this.planCode = 'new-plan-code'
  115. this.eventData.subscription.plan.plan_code = this.planCode
  116. this.RecurlyEventHandler.sendRecurlyAnalyticsEvent(
  117. 'updated_subscription_notification',
  118. this.eventData
  119. )
  120. sinon.assert.calledWith(
  121. this.AnalyticsManager.recordEventForUser,
  122. this.userId,
  123. 'subscription-updated',
  124. {
  125. plan_code: this.planCode,
  126. quantity: 1,
  127. is_trial: true,
  128. }
  129. )
  130. sinon.assert.calledWith(
  131. this.AnalyticsManager.setUserPropertyForUser,
  132. this.userId,
  133. 'subscription-plan-code',
  134. this.planCode
  135. )
  136. sinon.assert.calledWith(
  137. this.AnalyticsManager.setUserPropertyForUser,
  138. this.userId,
  139. 'subscription-state',
  140. 'active'
  141. )
  142. sinon.assert.calledWith(
  143. this.AnalyticsManager.setUserPropertyForUser,
  144. this.userId,
  145. 'subscription-is-trial',
  146. true
  147. )
  148. })
  149. it('with canceled_subscription_notification', function () {
  150. this.eventData.subscription.state = 'cancelled'
  151. this.RecurlyEventHandler.sendRecurlyAnalyticsEvent(
  152. 'canceled_subscription_notification',
  153. this.eventData
  154. )
  155. sinon.assert.calledWith(
  156. this.AnalyticsManager.recordEventForUser,
  157. this.userId,
  158. 'subscription-cancelled',
  159. {
  160. plan_code: this.planCode,
  161. quantity: 1,
  162. is_trial: true,
  163. }
  164. )
  165. sinon.assert.calledWith(
  166. this.AnalyticsManager.setUserPropertyForUser,
  167. this.userId,
  168. 'subscription-state',
  169. 'cancelled'
  170. )
  171. sinon.assert.calledWith(
  172. this.AnalyticsManager.setUserPropertyForUser,
  173. this.userId,
  174. 'subscription-is-trial',
  175. true
  176. )
  177. })
  178. it('with expired_subscription_notification', function () {
  179. this.eventData.subscription.state = 'expired'
  180. this.RecurlyEventHandler.sendRecurlyAnalyticsEvent(
  181. 'expired_subscription_notification',
  182. this.eventData
  183. )
  184. sinon.assert.calledWith(
  185. this.AnalyticsManager.recordEventForUser,
  186. this.userId,
  187. 'subscription-expired',
  188. {
  189. plan_code: this.planCode,
  190. quantity: 1,
  191. is_trial: true,
  192. }
  193. )
  194. sinon.assert.calledWith(
  195. this.AnalyticsManager.setUserPropertyForUser,
  196. this.userId,
  197. 'subscription-plan-code',
  198. this.planCode
  199. )
  200. sinon.assert.calledWith(
  201. this.AnalyticsManager.setUserPropertyForUser,
  202. this.userId,
  203. 'subscription-state',
  204. 'expired'
  205. )
  206. sinon.assert.calledWith(
  207. this.AnalyticsManager.setUserPropertyForUser,
  208. this.userId,
  209. 'subscription-is-trial',
  210. true
  211. )
  212. })
  213. it('with renewed_subscription_notification', function () {
  214. this.RecurlyEventHandler.sendRecurlyAnalyticsEvent(
  215. 'renewed_subscription_notification',
  216. this.eventData
  217. )
  218. sinon.assert.calledWith(
  219. this.AnalyticsManager.recordEventForUser,
  220. this.userId,
  221. 'subscription-renewed',
  222. {
  223. plan_code: this.planCode,
  224. quantity: 1,
  225. is_trial: true,
  226. }
  227. )
  228. })
  229. it('with reactivated_account_notification', function () {
  230. this.RecurlyEventHandler.sendRecurlyAnalyticsEvent(
  231. 'reactivated_account_notification',
  232. this.eventData
  233. )
  234. sinon.assert.calledWith(
  235. this.AnalyticsManager.recordEventForUser,
  236. this.userId,
  237. 'subscription-reactivated',
  238. {
  239. plan_code: this.planCode,
  240. quantity: 1,
  241. }
  242. )
  243. })
  244. it('with paid_charge_invoice_notification', function () {
  245. this.RecurlyEventHandler.sendRecurlyAnalyticsEvent(
  246. 'paid_charge_invoice_notification',
  247. {
  248. account: {
  249. account_code: this.userId,
  250. },
  251. invoice: {
  252. state: 'paid',
  253. total_in_cents: 720,
  254. },
  255. }
  256. )
  257. sinon.assert.calledWith(
  258. this.AnalyticsManager.recordEventForUser,
  259. this.userId,
  260. 'subscription-invoice-collected'
  261. )
  262. })
  263. it('with paid_charge_invoice_notification and total_in_cents 0', function () {
  264. this.RecurlyEventHandler.sendRecurlyAnalyticsEvent(
  265. 'paid_charge_invoice_notification',
  266. {
  267. account: {
  268. account_code: this.userId,
  269. },
  270. invoice: {
  271. state: 'paid',
  272. total_in_cents: 0,
  273. },
  274. }
  275. )
  276. sinon.assert.notCalled(this.AnalyticsManager.recordEventForUser)
  277. })
  278. it('with closed_invoice_notification', function () {
  279. this.RecurlyEventHandler.sendRecurlyAnalyticsEvent(
  280. 'closed_invoice_notification',
  281. {
  282. account: {
  283. account_code: this.userId,
  284. },
  285. invoice: {
  286. state: 'collected',
  287. total_in_cents: 720,
  288. },
  289. }
  290. )
  291. sinon.assert.calledWith(
  292. this.AnalyticsManager.recordEventForUser,
  293. this.userId,
  294. 'subscription-invoice-collected'
  295. )
  296. })
  297. it('with closed_invoice_notification and total_in_cents 0', function () {
  298. this.RecurlyEventHandler.sendRecurlyAnalyticsEvent(
  299. 'closed_invoice_notification',
  300. {
  301. account: {
  302. account_code: this.userId,
  303. },
  304. invoice: {
  305. state: 'collected',
  306. total_in_cents: 0,
  307. },
  308. }
  309. )
  310. sinon.assert.notCalled(this.AnalyticsManager.recordEventForUser)
  311. })
  312. it('nothing is called with invalid account code', function () {
  313. this.eventData.account.account_code = 'foo_bar'
  314. this.RecurlyEventHandler.sendRecurlyAnalyticsEvent(
  315. 'new_subscription_notification',
  316. this.eventData
  317. )
  318. sinon.assert.notCalled(this.AnalyticsManager.recordEventForUser)
  319. sinon.assert.notCalled(this.AnalyticsManager.setUserPropertyForUser)
  320. sinon.assert.notCalled(this.AnalyticsManager.setUserPropertyForUser)
  321. sinon.assert.notCalled(this.AnalyticsManager.setUserPropertyForUser)
  322. })
  323. })