SubscriptionControllerTests.coffee 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. SandboxedModule = require('sandboxed-module')
  2. sinon = require 'sinon'
  3. Settings = require 'settings-sharelatex'
  4. should = require("chai").should()
  5. MockRequest = require "../helpers/MockRequest"
  6. MockResponse = require "../helpers/MockResponse"
  7. modulePath = '../../../../app/js/Features/Subscription/SubscriptionController'
  8. mockSubscriptions =
  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 controller sanboxed", ->
  20. beforeEach ->
  21. @user = {}
  22. @activeRecurlySubscription = mockSubscriptions["subscription-123-active"]
  23. @SecurityManager =
  24. getCurrentUser: sinon.stub().callsArgWith(1, null, @user)
  25. @SubscriptionHandler =
  26. createSubscription: sinon.stub().callsArgWith(2)
  27. updateSubscription: sinon.stub().callsArgWith(2)
  28. reactivateSubscription: sinon.stub().callsArgWith(1)
  29. cancelSubscription: sinon.stub().callsArgWith(1)
  30. recurlyCallback: sinon.stub().callsArgWith(1)
  31. startFreeTrial: sinon.stub()
  32. @PlansLocator =
  33. findLocalPlanInSettings: sinon.stub()
  34. @LimitationsManager =
  35. userHasSubscriptionOrIsGroupMember: sinon.stub()
  36. userHasSubscription : sinon.stub()
  37. @RecurlyWrapper =
  38. sign: sinon.stub().callsArgWith(1, null, "somthing")
  39. @SubscriptionViewModelBuilder =
  40. buildUsersSubscriptionViewModel:sinon.stub().callsArgWith(1, null, @activeRecurlySubscription)
  41. buildViewModel: sinon.stub()
  42. @SubscriptionController = SandboxedModule.require modulePath, requires:
  43. '../../managers/SecurityManager': @SecurityManager
  44. './SubscriptionHandler': @SubscriptionHandler
  45. "./PlansLocator": @PlansLocator
  46. './SubscriptionViewModelBuilder': @SubscriptionViewModelBuilder
  47. "./LimitationsManager": @LimitationsManager
  48. './RecurlyWrapper': @RecurlyWrapper
  49. "logger-sharelatex": log:->
  50. @res = new MockResponse()
  51. @req = new MockRequest()
  52. @req.body = {}
  53. @req.query =
  54. planCode:"123123"
  55. describe "editBillingDetailsPage", ->
  56. describe "with a user with a subscription", ->
  57. beforeEach (done) ->
  58. @LimitationsManager.userHasSubscription.callsArgWith(1, null, true)
  59. @user.id = @activeRecurlySubscription.account.account_code
  60. @res.callback = done
  61. @SubscriptionController.editBillingDetailsPage(@req, @res)
  62. it "should render the edit billing details page", ->
  63. @res.rendered.should.equal true
  64. @res.renderedTemplate.should.equal "subscriptions/edit-billing-details"
  65. it "should set the correct variables for the template", ->
  66. should.exist @res.renderedVariables.signature
  67. @res.renderedVariables.successURL.should.equal "#{Settings.siteUrl}/user/subscription/update"
  68. @res.renderedVariables.user.id.should.equal @user.id
  69. describe "with a user without subscription", ->
  70. beforeEach (done) ->
  71. @res.callback = done
  72. @LimitationsManager.userHasSubscription.callsArgWith(1, null, false)
  73. @SubscriptionController.reactivateSubscription @req, @res
  74. it "should redirect to the subscription dashboard", ->
  75. @res.redirected.should.equal true
  76. @res.redirectedTo.should.equal "/user/subscription"
  77. describe "paymentPage", ->
  78. describe "with a user without a subscription", ->
  79. beforeEach ->
  80. @LimitationsManager.userHasSubscription.callsArgWith(1, null, false)
  81. @PlansLocator.findLocalPlanInSettings.returns({})
  82. describe "with a valid plan code", ->
  83. it "should render the new subscription page", (done)->
  84. @res.render = (page, opts)=>
  85. page.should.equal "subscriptions/new"
  86. done()
  87. @SubscriptionController.paymentPage @req, @res
  88. it "should set the successURL", (done)->
  89. @req.session._csrf = @csrfToken = "mock-csrf-token"
  90. @res.render = (page, opts)=>
  91. url = JSON.parse(opts.subscriptionFormOptions).successURL
  92. url.should.equal("#{Settings.siteUrl}/user/subscription/create?_csrf=#{@csrfToken}")
  93. done()
  94. @SubscriptionController.paymentPage @req, @res
  95. describe "with a user with subscription", ->
  96. it "should redirect to the subscription dashboard", (done)->
  97. @LimitationsManager.userHasSubscription.callsArgWith(1, null, true)
  98. @res.redirect = (url)=>
  99. url.should.equal "/user/subscription"
  100. done()
  101. @SubscriptionController.paymentPage(@req, @res)
  102. describe "with an invalid plan code", ->
  103. it "should redirect to the subscription dashboard", (done)->
  104. @LimitationsManager.userHasSubscription.callsArgWith(1, null, false)
  105. @PlansLocator.findLocalPlanInSettings.returns(null)
  106. @res.redirect = (url)=>
  107. url.should.equal "/user/subscription"
  108. done()
  109. @SubscriptionController.paymentPage(@req, @res)
  110. describe "successful_subscription", ->
  111. beforeEach (done) ->
  112. @SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel.callsArgWith(1, null, {})
  113. @res.callback = done
  114. @SubscriptionController.successful_subscription @req, @res
  115. describe "userSubscriptionPage", ->
  116. describe "with a user without a subscription", ->
  117. beforeEach (done) ->
  118. @res.callback = done
  119. @LimitationsManager.userHasSubscriptionOrIsGroupMember.callsArgWith(1, null, false)
  120. @SubscriptionController.userSubscriptionPage @req, @res
  121. it "should redirect to the plans page", ->
  122. @res.redirected.should.equal true
  123. @res.redirectedTo.should.equal "/user/subscription/plans"
  124. describe "with a user with a paid subscription", ->
  125. beforeEach (done) ->
  126. @res.callback = done
  127. @SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel.callsArgWith(1, null, @activeRecurlySubscription)
  128. @LimitationsManager.userHasSubscriptionOrIsGroupMember.callsArgWith(1, null, true)
  129. @SubscriptionController.userSubscriptionPage @req, @res
  130. it "should render the dashboard", (done)->
  131. @res.rendered.should.equal true
  132. @res.renderedTemplate.should.equal "subscriptions/dashboard"
  133. done()
  134. it "should set the correct subscription details", ->
  135. @res.renderedVariables.subscription.should.deep.equal @activeRecurlySubscription
  136. describe "with a user with a free trial", ->
  137. beforeEach (done) ->
  138. @res.callback = done
  139. @SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel.callsArgWith(1, null, @activeRecurlySubscription)
  140. @LimitationsManager.userHasSubscriptionOrIsGroupMember.callsArgWith(1, null, true)
  141. @SubscriptionController.userSubscriptionPage @req, @res
  142. it "should render the dashboard", ->
  143. @res.renderedTemplate.should.equal "subscriptions/dashboard"
  144. it "should set the correct subscription details", ->
  145. @res.renderedVariables.subscription.should.deep.equal @activeRecurlySubscription
  146. describe "createSubscription", ->
  147. beforeEach (done)->
  148. @res =
  149. redirect:->
  150. done()
  151. sinon.spy @res, "redirect"
  152. @req.body.recurly_token = "1234"
  153. @SubscriptionController.createSubscription @req, @res
  154. it "should send the user and subscriptionId to the handler", (done)->
  155. @SubscriptionHandler.createSubscription.calledWith(@user, @req.body.recurly_token).should.equal true
  156. done()
  157. it "should redurect to the subscription page", (done)->
  158. @res.redirect.calledWith("/user/subscription/thank-you").should.equal true
  159. done()
  160. describe "updateSubscription", ->
  161. beforeEach (done)->
  162. @res =
  163. redirect:->
  164. done()
  165. sinon.spy @res, "redirect"
  166. @plan_code = "1234"
  167. @req.body.plan_code = @plan_code
  168. @SubscriptionController.updateSubscription @req, @res
  169. it "should send the user and subscriptionId to the handler", (done)->
  170. @SubscriptionHandler.updateSubscription.calledWith(@user, @plan_code).should.equal true
  171. done()
  172. it "should redurect to the subscription page", (done)->
  173. @res.redirect.calledWith("/user/subscription").should.equal true
  174. done()
  175. describe "reactivateSubscription", ->
  176. beforeEach (done)->
  177. @res =
  178. redirect:->
  179. done()
  180. sinon.spy @res, "redirect"
  181. @SubscriptionController.reactivateSubscription @req, @res
  182. it "should tell the handler to reactivate this user", (done)->
  183. @SubscriptionHandler.reactivateSubscription.calledWith(@user).should.equal true
  184. done()
  185. it "should redurect to the subscription page", (done)->
  186. @res.redirect.calledWith("/user/subscription").should.equal true
  187. done()
  188. describe "cancelSubscription", ->
  189. beforeEach (done)->
  190. @res =
  191. redirect:->
  192. done()
  193. sinon.spy @res, "redirect"
  194. @SubscriptionController.cancelSubscription @req, @res
  195. it "should tell the handler to cancel this user", (done)->
  196. @SubscriptionHandler.cancelSubscription.calledWith(@user).should.equal true
  197. done()
  198. it "should redurect to the subscription page", (done)->
  199. @res.redirect.calledWith("/user/subscription").should.equal true
  200. done()
  201. describe "recurly callback", ->
  202. describe "with a actionable request", ->
  203. beforeEach (done)->
  204. @req =
  205. body:
  206. expired_subscription_notification:
  207. subscription:
  208. uuid: @activeRecurlySubscription.uuid
  209. @res = send:->
  210. done()
  211. sinon.spy @res, "send"
  212. @SubscriptionController.recurlyCallback @req, @res
  213. it "should tell the SubscriptionHandler to process the recurly callback", (done)->
  214. @SubscriptionHandler.recurlyCallback.called.should.equal true
  215. done()
  216. it "should send a 200", (done)->
  217. @res.send.calledWith(200)
  218. done()
  219. describe "with a non-actionable request", ->
  220. beforeEach (done) ->
  221. @user.id = @activeRecurlySubscription.account.account_code
  222. @req =
  223. body:
  224. new_subscription_notification:
  225. subscription:
  226. uuid: @activeRecurlySubscription.uuid
  227. @res = send:->
  228. done()
  229. sinon.spy @res, "send"
  230. @SubscriptionController.recurlyCallback @req, @res
  231. it "should not call the subscriptionshandler", ->
  232. @SubscriptionHandler.recurlyCallback.called.should.equal false
  233. it "should respond with a 200 status", ->
  234. @res.send.calledWith(200)