SubscriptionHandlerTests.coffee 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. SandboxedModule = require('sandboxed-module')
  2. should = require('chai').should()
  3. sinon = require 'sinon'
  4. querystring = require 'querystring'
  5. modulePath = "../../../../app/js/Features/Subscription/SubscriptionHandler"
  6. SubscriptionHandler = require modulePath
  7. tk = require 'timekeeper'
  8. mockRecurlySubscriptions =
  9. "subscription-123-active":
  10. uuid: "subscription-123-active"
  11. plan:
  12. name: "Gold"
  13. plan_code: "gold"
  14. current_period_ends_at: new Date()
  15. state: "active"
  16. unit_amount_in_cents: 999
  17. account:
  18. account_code: "user-123"
  19. describe "Subscription Handler sanboxed", ->
  20. beforeEach ->
  21. @Settings =
  22. plans : [{
  23. planCode: "collaborator"
  24. name: "Collaborator"
  25. features:
  26. collaborators: -1
  27. versioning: true
  28. }]
  29. defaultPlanCode :
  30. collaborators: 0
  31. versioning: false
  32. @activeRecurlySubscription = mockRecurlySubscriptions["subscription-123-active"]
  33. @User = {}
  34. @user =
  35. _id: "user_id_here_"
  36. @subscription =
  37. recurlySubscription_id: @activeRecurlySubscription.uuid
  38. @RecurlyWrapper =
  39. getSubscription: sinon.stub().callsArgWith(2, null, @activeRecurlySubscription)
  40. updateSubscription: sinon.stub().callsArgWith(2, null, @activeRecurlySubscription)
  41. cancelSubscription: sinon.stub().callsArgWith(1)
  42. reactivateSubscription: sinon.stub().callsArgWith(1)
  43. @AnalyticsManager =
  44. trackSubscriptionCancelled: sinon.stub()
  45. trackSubscriptionStarted: sinon.stub()
  46. trackFreeTrialStarted: sinon.stub()
  47. @SubscriptionUpdater =
  48. syncSubscription: sinon.stub().callsArgWith(2)
  49. startFreeTrial: sinon.stub().callsArgWith(1)
  50. @LimitationsManager =
  51. userHasSubscription: sinon.stub()
  52. userHasSubscriptionOrFreeTrial: sinon.stub()
  53. @EmailHandler =
  54. sendEmail:sinon.stub()
  55. @SubscriptionHandler = SandboxedModule.require modulePath, requires:
  56. "./RecurlyWrapper": @RecurlyWrapper
  57. "settings-sharelatex": @Settings
  58. '../../models/User': User:@User
  59. './SubscriptionUpdater': @SubscriptionUpdater
  60. '../Analytics/AnalyticsManager': @AnalyticsManager
  61. "logger-sharelatex":{log:->}
  62. './LimitationsManager':@LimitationsManager
  63. "../Email/EmailHandler":@EmailHandler
  64. @SubscriptionHandler.syncSubscriptionToUser = sinon.stub().callsArgWith(2)
  65. describe "createSubscription", ->
  66. beforeEach (done) ->
  67. @SubscriptionHandler.createSubscription(@user, @activeRecurlySubscription.uuid, done)
  68. it "should get the subscription", (done)->
  69. @RecurlyWrapper.getSubscription.calledWith(@activeRecurlySubscription.uuid, {recurlyJsResult: true}).should.equal true
  70. done()
  71. it "should sync the subscription to the user", (done)->
  72. @SubscriptionUpdater.syncSubscription.calledOnce.should.equal true
  73. @SubscriptionUpdater.syncSubscription.args[0][0].should.deep.equal @activeRecurlySubscription
  74. @SubscriptionUpdater.syncSubscription.args[0][1].should.deep.equal @user._id
  75. done()
  76. describe "updateSubscription", ->
  77. describe "with a user with a subscription", ->
  78. describe "with a valid plan code", ->
  79. beforeEach (done) ->
  80. @plan_code = "collaborator"
  81. @LimitationsManager.userHasSubscription.callsArgWith(1, null, true, @subscription)
  82. @SubscriptionHandler.updateSubscription(@user, @plan_code, done)
  83. it "should update the subscription", ->
  84. @RecurlyWrapper.updateSubscription.calledWith(@subscription.recurlySubscription_id).should.equal true
  85. updateOptions = @RecurlyWrapper.updateSubscription.args[0][1]
  86. updateOptions.plan_code.should.equal @plan_code
  87. it "should update immediately", ->
  88. updateOptions = @RecurlyWrapper.updateSubscription.args[0][1]
  89. updateOptions.timeframe.should.equal "now"
  90. it "should sync the new subscription to the user", ->
  91. @SubscriptionUpdater.syncSubscription.calledOnce.should.equal true
  92. @SubscriptionUpdater.syncSubscription.args[0][0].should.deep.equal @activeRecurlySubscription
  93. @SubscriptionUpdater.syncSubscription.args[0][1].should.deep.equal @user._id
  94. # describe "without a valid plan code", ->
  95. # beforeEach (done) ->
  96. # @plan_code = "not-a-plan"
  97. # @LimitationsManager.userHasSubscription.callsArgWith(1, null, true)
  98. # @SubscriptionHandler.updateSubscription(@user, @plan_code, done)
  99. # it "should not update the subscription", ->
  100. # @RecurlyWrapper.updateSubscription.called.should.equal false
  101. # @SubscriptionHandler.syncSubscriptionToUser.called.should.equal false
  102. describe "with a user without a subscription", ->
  103. beforeEach (done) ->
  104. @LimitationsManager.userHasSubscription.callsArgWith(1, null, false)
  105. @SubscriptionHandler.updateSubscription(@user, @plan_code, done)
  106. it "should redirect to the subscription dashboard", ->
  107. @RecurlyWrapper.updateSubscription.called.should.equal false
  108. @SubscriptionHandler.syncSubscriptionToUser.called.should.equal false
  109. describe "cancelSubscription", ->
  110. describe "with a user without a subscription", ->
  111. beforeEach (done) ->
  112. @LimitationsManager.userHasSubscription.callsArgWith(1, null, false, @subscription)
  113. @SubscriptionHandler.cancelSubscription @user, done
  114. it "should redirect to the subscription dashboard", ->
  115. @RecurlyWrapper.cancelSubscription.called.should.equal false
  116. describe "with a user with a subscription", ->
  117. beforeEach (done) ->
  118. @LimitationsManager.userHasSubscription.callsArgWith(1, null, true, @subscription)
  119. @SubscriptionHandler.cancelSubscription @user, done
  120. it "should cancel the subscription", ->
  121. @RecurlyWrapper.cancelSubscription.called.should.equal true
  122. @RecurlyWrapper.cancelSubscription.calledWith(@subscription.recurlySubscription_id).should.equal true
  123. it "should track the cancellation", ->
  124. @AnalyticsManager.trackSubscriptionCancelled
  125. .calledWith(@user)
  126. .should.equal true
  127. it "should send a cancellation email", ->
  128. @EmailHandler.sendEmail.calledWith("canceledSubscription", {to:@user.email, first_name:@user.first_name}).should.equal true
  129. describe "reactiveRecurlySubscription", ->
  130. describe "with a user without a subscription", ->
  131. beforeEach (done) ->
  132. @LimitationsManager.userHasSubscription.callsArgWith(1, null, false, @subscription)
  133. @SubscriptionHandler.reactivateSubscription @user, done
  134. it "should redirect to the subscription dashboard", ->
  135. @RecurlyWrapper.reactivateSubscription.called.should.equal false
  136. describe "with a user with a subscription", ->
  137. beforeEach (done) ->
  138. @LimitationsManager.userHasSubscription.callsArgWith(1, null, true, @subscription)
  139. @SubscriptionHandler.reactivateSubscription @user, done
  140. it "should reactivate the subscription", ->
  141. @RecurlyWrapper.reactivateSubscription.called.should.equal true
  142. @RecurlyWrapper.reactivateSubscription.calledWith(@subscription.recurlySubscription_id).should.equal true
  143. describe "recurlyCallback", ->
  144. describe "with an actionable request", ->
  145. beforeEach (done) ->
  146. @user.id = @activeRecurlySubscription.account.account_code
  147. @User.findById = (userId, callback) =>
  148. userId.should.equal @user.id
  149. callback null, @user
  150. @SubscriptionHandler.recurlyCallback(@activeRecurlySubscription, done)
  151. it "should request the affected subscription from the API", ->
  152. @RecurlyWrapper.getSubscription.calledWith(@activeRecurlySubscription.uuid).should.equal true
  153. it "should request the account details of the subscription", ->
  154. options = @RecurlyWrapper.getSubscription.args[0][1]
  155. options.includeAccount.should.equal true
  156. it "should sync the subscription to the user", ->
  157. @SubscriptionUpdater.syncSubscription.calledOnce.should.equal true
  158. @SubscriptionUpdater.syncSubscription.args[0][0].should.deep.equal @activeRecurlySubscription
  159. @SubscriptionUpdater.syncSubscription.args[0][1].should.deep.equal @user._id