SubscriptionTests.coffee 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. expect = require('chai').expect
  2. async = require("async")
  3. User = require "./helpers/User"
  4. {Subscription} = require "../../../app/js/models/Subscription"
  5. {Institution} = require "../../../app/js/models/Institution"
  6. SubscriptionViewModelBuilder = require "../../../app/js/Features/Subscription/SubscriptionViewModelBuilder"
  7. MockRecurlyApi = require "./helpers/MockRecurlyApi"
  8. MockV1Api = require "./helpers/MockV1Api"
  9. describe 'Subscriptions', ->
  10. describe 'dashboard', ->
  11. before (done) ->
  12. @user = new User()
  13. @user.ensureUserExists done
  14. describe 'when the user has no subscription', ->
  15. before (done) ->
  16. SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
  17. return done(error) if error?
  18. done()
  19. it 'should return no personalSubscription', ->
  20. expect(@data.personalSubscription).to.equal null
  21. it 'should return no memberGroupSubscriptions', ->
  22. expect(@data.memberGroupSubscriptions).to.deep.equal []
  23. describe 'when the user has a subscription with recurly', ->
  24. before (done) ->
  25. MockRecurlyApi.accounts['mock-account-id'] = @accounts = {
  26. hosted_login_token: 'mock-login-token'
  27. }
  28. MockRecurlyApi.subscriptions['mock-subscription-id'] = @subscription = {
  29. plan_code: 'collaborator',
  30. tax_in_cents: 100,
  31. tax_rate: 0.2,
  32. unit_amount_in_cents: 500,
  33. currency: 'GBP',
  34. current_period_ends_at: new Date(2018,4,5),
  35. state: 'active',
  36. account_id: 'mock-account-id',
  37. trial_ends_at: new Date(2018, 6, 7)
  38. }
  39. Subscription.create {
  40. admin_id: @user._id,
  41. manager_ids: [@user._id],
  42. recurlySubscription_id: 'mock-subscription-id',
  43. planCode: 'collaborator'
  44. }, (error) =>
  45. return done(error) if error?
  46. SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
  47. return done(error) if error?
  48. done()
  49. return
  50. after (done) ->
  51. MockRecurlyApi.accounts = {}
  52. MockRecurlyApi.subscriptions = {}
  53. Subscription.remove {
  54. admin_id: @user._id
  55. }, done
  56. return
  57. it 'should return a personalSubscription with populated recurly data', ->
  58. subscription = @data.personalSubscription
  59. expect(subscription).to.exist
  60. expect(subscription.planCode).to.equal 'collaborator'
  61. expect(subscription.recurly).to.exist
  62. expect(subscription.recurly).to.deep.equal {
  63. "billingDetailsLink": "https://test.recurly.com/account/billing_info/edit?ht=mock-login-token"
  64. "currency": "GBP"
  65. "nextPaymentDueAt": "5th May 2018"
  66. "price": "£6.00"
  67. "state": "active"
  68. "tax": 100
  69. "taxRate": 0.2
  70. "trial_ends_at": new Date(2018, 6, 7),
  71. "trialEndsAtFormatted": "7th July 2018"
  72. }
  73. it 'should return no memberGroupSubscriptions', ->
  74. expect(@data.memberGroupSubscriptions).to.deep.equal []
  75. describe 'when the user has a subscription without recurly', ->
  76. before (done) ->
  77. Subscription.create {
  78. admin_id: @user._id,
  79. manager_ids: [@user._id],
  80. planCode: 'collaborator'
  81. }, (error) =>
  82. return done(error) if error?
  83. SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
  84. return done(error) if error?
  85. done()
  86. return
  87. after (done) ->
  88. Subscription.remove {
  89. admin_id: @user._id
  90. }, done
  91. return
  92. it 'should return a personalSubscription with no recurly data', ->
  93. subscription = @data.personalSubscription
  94. expect(subscription).to.exist
  95. expect(subscription.planCode).to.equal 'collaborator'
  96. expect(subscription.recurly).to.not.exist
  97. it 'should return no memberGroupSubscriptions', ->
  98. expect(@data.memberGroupSubscriptions).to.deep.equal []
  99. describe 'when the user is a member of a group subscription', ->
  100. before (done) ->
  101. @owner1 = new User()
  102. @owner2 = new User()
  103. async.series [
  104. (cb) => @owner1.ensureUserExists cb
  105. (cb) => @owner2.ensureUserExists cb
  106. (cb) => Subscription.create {
  107. admin_id: @owner1._id,
  108. manager_ids: [@owner1._id],
  109. planCode: 'collaborator',
  110. groupPlan: true,
  111. member_ids: [@user._id]
  112. }, cb
  113. (cb) => Subscription.create {
  114. admin_id: @owner2._id,
  115. manager_ids: [@owner2._id],
  116. planCode: 'collaborator',
  117. groupPlan: true,
  118. member_ids: [@user._id]
  119. }, cb
  120. ], (error) =>
  121. return done(error) if error?
  122. SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
  123. return done(error) if error?
  124. done()
  125. return
  126. after (done) ->
  127. Subscription.remove {
  128. admin_id: @owner1._id
  129. }, (error) =>
  130. return done(error) if error?
  131. Subscription.remove {
  132. admin_id: @owner2._id
  133. }, done
  134. return
  135. it 'should return no personalSubscription', ->
  136. expect(@data.personalSubscription).to.equal null
  137. it 'should return the two memberGroupSubscriptions', ->
  138. expect(@data.memberGroupSubscriptions.length).to.equal 2
  139. expect(
  140. # Mongoose populates the admin_id with the user
  141. @data.memberGroupSubscriptions[0].admin_id._id.toString()
  142. ).to.equal @owner1._id
  143. expect(
  144. @data.memberGroupSubscriptions[1].admin_id._id.toString()
  145. ).to.equal @owner2._id
  146. describe 'when the user is a manager of a group subscription', ->
  147. before (done) ->
  148. @owner1 = new User()
  149. @owner2 = new User()
  150. async.series [
  151. (cb) => @owner1.ensureUserExists cb
  152. (cb) => @owner2.ensureUserExists cb
  153. (cb) => Subscription.create {
  154. admin_id: @owner1._id,
  155. manager_ids: [@owner1._id, @user._id],
  156. planCode: 'collaborator',
  157. groupPlan: true
  158. }, cb
  159. ], (error) =>
  160. return done(error) if error?
  161. SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
  162. return done(error) if error?
  163. done()
  164. return
  165. after (done) ->
  166. Subscription.remove {
  167. admin_id: @owner1._id
  168. }, done
  169. return
  170. it 'should return no personalSubscription', ->
  171. expect(@data.personalSubscription).to.equal null
  172. it 'should return the managedGroupSubscriptions', ->
  173. expect(@data.managedGroupSubscriptions.length).to.equal 1
  174. subscription = @data.managedGroupSubscriptions[0]
  175. expect(
  176. # Mongoose populates the admin_id with the user
  177. subscription.admin_id._id.toString()
  178. ).to.equal @owner1._id
  179. expect(subscription.groupPlan).to.equal true
  180. describe 'when the user is a manager of an institution', ->
  181. before (done) ->
  182. @v1Id = MockV1Api.nextV1Id()
  183. async.series [
  184. (cb) =>
  185. Institution.create({
  186. v1Id: @v1Id,
  187. managerIds: [@user._id]
  188. }, cb)
  189. ], (error) =>
  190. return done(error) if error?
  191. SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
  192. return done(error) if error?
  193. done()
  194. return
  195. after (done) ->
  196. Institution.remove {
  197. v1Id: @v1Id
  198. }, done
  199. return
  200. it 'should return the managedInstitutions', ->
  201. expect(@data.managedInstitutions.length).to.equal 1
  202. institution = @data.managedInstitutions[0]
  203. expect(institution.v1Id).to.equal @v1Id
  204. expect(institution.name).to.equal "Institution #{@v1Id}"
  205. describe 'when the user is a member of an affiliation', ->
  206. before (done) ->
  207. v1Id = MockV1Api.nextV1Id()
  208. MockV1Api.setUser v1Id, {
  209. subscription: {},
  210. subscription_status: {}
  211. }
  212. MockV1Api.setAffiliations [{
  213. email: 'confirmed-affiliation-email@stanford.example.edu'
  214. institution: { name: 'Stanford', licence: 'pro_plus', confirmed: true }
  215. }, {
  216. email: 'unconfirmed-affiliation-email@harvard.example.edu'
  217. institution: { name: 'Harvard', licence: 'pro_plus', confirmed: true }
  218. }, {
  219. email: 'confirmed-affiliation-email@mit.example.edu'
  220. institution: { name: 'MIT', licence: 'pro_plus', confirmed: false }
  221. }]
  222. async.series [
  223. (cb) =>
  224. @user.setV1Id v1Id, cb
  225. (cb) =>
  226. @user.addEmail 'unconfirmed-affiliation-email@harvard.example.edu', cb
  227. (cb) =>
  228. @user.addEmail 'confirmed-affiliation-email@stanford.example.edu', cb
  229. (cb) =>
  230. @user.confirmEmail 'confirmed-affiliation-email@stanford.example.edu', cb
  231. (cb) =>
  232. @user.addEmail 'confirmed-affiliation-email@mit.example.edu', cb
  233. (cb) =>
  234. @user.confirmEmail 'confirmed-affiliation-email@mit.example.edu', cb
  235. ], (error) =>
  236. return done(error) if error?
  237. SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
  238. return done(error) if error?
  239. done()
  240. it 'should return only the affilations with confirmed institutions, and confirmed emails', ->
  241. expect(@data.confirmedMemberInstitutions).to.deep.equal [
  242. { name: 'Stanford', licence: 'pro_plus', confirmed: true }
  243. ]
  244. describe 'when the user has a v1 subscription', ->
  245. before (done) ->
  246. MockV1Api.setUser v1Id = MockV1Api.nextV1Id(), {
  247. subscription: @subscription = {
  248. trial: false,
  249. has_plan: true,
  250. teams: [{
  251. id: 56,
  252. name: 'Test team'
  253. }]
  254. }
  255. subscription_status: @subscription_status = {
  256. product: { 'mock': 'product' }
  257. team: null
  258. }
  259. }
  260. @user.setV1Id v1Id, (error) =>
  261. return done(error) if error?
  262. SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
  263. return done(error) if error?
  264. done()
  265. it 'should return no personalSubscription', ->
  266. expect(@data.personalSubscription).to.equal null
  267. it 'should return no memberGroupSubscriptions', ->
  268. expect(@data.memberGroupSubscriptions).to.deep.equal []
  269. it 'should return a v1SubscriptionStatus', ->
  270. expect(@data.v1SubscriptionStatus).to.deep.equal @subscription_status
  271. describe 'canceling', ->
  272. before (done) ->
  273. @user = new User()
  274. MockV1Api.setUser v1Id = MockV1Api.nextV1Id(), @v1_user = {}
  275. async.series [
  276. (cb) => @user.login(cb)
  277. (cb) => @user.setV1Id(v1Id, cb)
  278. ], (error) =>
  279. @user.request {
  280. method: 'POST',
  281. url: '/user/subscription/v1/cancel'
  282. }, (error, @response) =>
  283. return done(error) if error?
  284. done()
  285. it 'should tell v1 to cancel the subscription', ->
  286. expect(@v1_user.canceled).to.equal true
  287. it 'should redirect to the subscription dashboard', ->
  288. expect(@response.statusCode).to.equal 302
  289. expect(@response.headers.location).to.equal '/user/subscription'