SubscriptionUpdaterTests.coffee 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. SandboxedModule = require('sandboxed-module')
  2. should = require('chai').should()
  3. expect = require('chai').expect
  4. sinon = require 'sinon'
  5. modulePath = "../../../../app/js/Features/Subscription/SubscriptionUpdater"
  6. assert = require("chai").assert
  7. ObjectId = require('mongoose').Types.ObjectId
  8. describe "SubscriptionUpdater", ->
  9. beforeEach ->
  10. @recurlySubscription =
  11. uuid: "1238uoijdasjhd"
  12. plan:
  13. plan_code: "kjhsakjds"
  14. @adminUser =
  15. _id: @adminuser_id = "5208dd34438843e2db000007"
  16. @otherUserId = "5208dd34438842e2db000005"
  17. @allUserIds = ["13213", "dsadas", "djsaiud89"]
  18. @userStub = _id: 'mock-user-stub-id', email: 'mock-stub-email@baz.com'
  19. @subscription = subscription =
  20. _id: "111111111111111111111111"
  21. admin_id: @adminUser._id
  22. manager_ids: [@adminUser._id]
  23. member_ids: @allUserIds
  24. save: sinon.stub().callsArgWith(0)
  25. planCode:"student_or_something"
  26. @user_id = @adminuser_id
  27. @groupSubscription =
  28. _id: "222222222222222222222222"
  29. admin_id: @adminUser._id
  30. manager_ids: [@adminUser._id]
  31. member_ids: @allUserIds
  32. save: sinon.stub().callsArgWith(0)
  33. planCode:"group_subscription"
  34. @updateStub = sinon.stub().callsArgWith(2, null)
  35. @updateManyStub = sinon.stub().callsArgWith(2, null)
  36. @findAndModifyStub = sinon.stub().callsArgWith(2, null, @subscription)
  37. @SubscriptionModel = class
  38. constructor: (opts)->
  39. subscription.admin_id = opts.admin_id
  40. subscription.manager_ids = [opts.admin_id]
  41. return subscription
  42. @remove: sinon.stub().yields()
  43. @SubscriptionModel.update = @updateStub
  44. @SubscriptionModel.updateMany = @updateManyStub
  45. @SubscriptionModel.findAndModify = @findAndModifyStub
  46. @SubscriptionLocator =
  47. getUsersSubscription: sinon.stub()
  48. getGroupSubscriptionMemberOf:sinon.stub()
  49. getMemberSubscriptions: sinon.stub().yields(null, [])
  50. @Settings =
  51. defaultPlanCode: "personal"
  52. defaultFeatures: { "default": "features" }
  53. @UserFeaturesUpdater =
  54. updateFeatures : sinon.stub().yields()
  55. @PlansLocator =
  56. findLocalPlanInSettings: sinon.stub().returns({})
  57. @UserGetter =
  58. getUsers: (memberIds, projection, callback) ->
  59. users = memberIds.map (id) -> { _id: id }
  60. callback(null, users)
  61. getUserOrUserStubById: sinon.stub()
  62. @ReferalFeatures = getBonusFeatures: sinon.stub().callsArgWith(1)
  63. @Modules = {hooks: {fire: sinon.stub().callsArgWith(2, null, null)}}
  64. @SubscriptionUpdater = SandboxedModule.require modulePath, requires:
  65. '../../models/Subscription': Subscription:@SubscriptionModel
  66. './UserFeaturesUpdater': @UserFeaturesUpdater
  67. './SubscriptionLocator': @SubscriptionLocator
  68. '../User/UserGetter': @UserGetter
  69. './PlansLocator': @PlansLocator
  70. "logger-sharelatex": log:->
  71. 'settings-sharelatex': @Settings
  72. "./FeaturesUpdater": @FeaturesUpdater = {}
  73. describe "syncSubscription", ->
  74. beforeEach ->
  75. @SubscriptionLocator.getUsersSubscription.callsArgWith(1, null, @subscription)
  76. @SubscriptionUpdater._updateSubscriptionFromRecurly = sinon.stub().callsArgWith(2)
  77. it "should update the subscription if the user already is admin of one", (done)->
  78. @SubscriptionUpdater._createNewSubscription = sinon.stub()
  79. @SubscriptionUpdater.syncSubscription @recurlySubscription, @adminUser._id, (err)=>
  80. @SubscriptionLocator.getUsersSubscription.calledWith(@adminUser._id).should.equal true
  81. @SubscriptionUpdater._updateSubscriptionFromRecurly.called.should.equal true
  82. @SubscriptionUpdater._updateSubscriptionFromRecurly.calledWith(@recurlySubscription, @subscription).should.equal true
  83. done()
  84. it "should not call updateFeatures with group subscription if recurly subscription is not expired", (done)->
  85. @SubscriptionUpdater.syncSubscription @recurlySubscription, @adminUser._id, (err)=>
  86. @SubscriptionLocator.getUsersSubscription.calledWith(@adminUser._id).should.equal true
  87. @SubscriptionUpdater._updateSubscriptionFromRecurly.called.should.equal true
  88. @SubscriptionUpdater._updateSubscriptionFromRecurly.calledWith(@recurlySubscription, @subscription).should.equal true
  89. @UserFeaturesUpdater.updateFeatures.called.should.equal false
  90. done()
  91. describe "_updateSubscriptionFromRecurly", ->
  92. beforeEach ->
  93. @FeaturesUpdater.refreshFeatures = sinon.stub().callsArgWith(1)
  94. @SubscriptionUpdater.deleteSubscription = sinon.stub().yields()
  95. it "should update the subscription with token etc when not expired", (done)->
  96. @SubscriptionUpdater._updateSubscriptionFromRecurly @recurlySubscription, @subscription, (err)=>
  97. @subscription.recurlySubscription_id.should.equal @recurlySubscription.uuid
  98. @subscription.planCode.should.equal @recurlySubscription.plan.plan_code
  99. @subscription.save.called.should.equal true
  100. @FeaturesUpdater.refreshFeatures.calledWith(@adminUser._id).should.equal true
  101. done()
  102. it "should remove the subscription when expired", (done)->
  103. @recurlySubscription.state = "expired"
  104. @SubscriptionUpdater._updateSubscriptionFromRecurly @recurlySubscription, @subscription, (err)=>
  105. @SubscriptionUpdater.deleteSubscription.calledWith(@subscription._id).should.equal true
  106. done()
  107. it "should update all the users features", (done)->
  108. @SubscriptionUpdater._updateSubscriptionFromRecurly @recurlySubscription, @subscription, (err)=>
  109. @FeaturesUpdater.refreshFeatures.calledWith(@adminUser._id).should.equal true
  110. @FeaturesUpdater.refreshFeatures.calledWith(@allUserIds[0]).should.equal true
  111. @FeaturesUpdater.refreshFeatures.calledWith(@allUserIds[1]).should.equal true
  112. @FeaturesUpdater.refreshFeatures.calledWith(@allUserIds[2]).should.equal true
  113. done()
  114. it "should set group to true and save how many members can be added to group", (done)->
  115. @PlansLocator.findLocalPlanInSettings.withArgs(@recurlySubscription.plan.plan_code).returns({groupPlan:true, membersLimit:5})
  116. @SubscriptionUpdater._updateSubscriptionFromRecurly @recurlySubscription, @subscription, (err)=>
  117. @subscription.membersLimit.should.equal 5
  118. @subscription.groupPlan.should.equal true
  119. done()
  120. it "should not set group to true or set groupPlan", (done)->
  121. @SubscriptionUpdater._updateSubscriptionFromRecurly @recurlySubscription, @subscription, (err)=>
  122. assert.notEqual @subscription.membersLimit, 5
  123. assert.notEqual @subscription.groupPlan, true
  124. done()
  125. describe "_createNewSubscription", ->
  126. it "should create a new subscription then update the subscription", (done)->
  127. @SubscriptionUpdater._createNewSubscription @adminUser._id, =>
  128. @subscription.admin_id.should.equal @adminUser._id
  129. @subscription.manager_ids.should.deep.equal [@adminUser._id]
  130. @subscription.save.called.should.equal true
  131. done()
  132. describe "addUserToGroup", ->
  133. beforeEach ->
  134. @SubscriptionUpdater.addUsersToGroup = sinon.stub().yields(null)
  135. it "delegates to addUsersToGroup", (done)->
  136. @SubscriptionUpdater.addUserToGroup @subscription._id, @otherUserId, =>
  137. @SubscriptionUpdater.addUsersToGroup
  138. .calledWith(@subscription._id, [@otherUserId]).should.equal true
  139. done()
  140. describe "addUsersToGroup", ->
  141. beforeEach ->
  142. @FeaturesUpdater.refreshFeatures = sinon.stub().callsArgWith(1)
  143. it "should add the user ids to the group as a set", (done)->
  144. @SubscriptionUpdater.addUsersToGroup @subscription._id, [@otherUserId], =>
  145. searchOps =
  146. _id: @subscription._id
  147. insertOperation =
  148. { $addToSet: { member_ids: { $each: [@otherUserId] } } }
  149. @findAndModifyStub.calledWith(searchOps, insertOperation).should.equal true
  150. done()
  151. it "should update the users features", (done)->
  152. @SubscriptionUpdater.addUserToGroup @subscription._id, @otherUserId, =>
  153. @FeaturesUpdater.refreshFeatures.calledWith(@otherUserId).should.equal true
  154. done()
  155. describe "removeUserFromGroups", ->
  156. beforeEach ->
  157. @FeaturesUpdater.refreshFeatures = sinon.stub().callsArgWith(1)
  158. @UserGetter.getUserOrUserStubById.yields(null, {}, false)
  159. @fakeSubscriptions = [{ _id: 'fake-id-1' }, { _id: 'fake-id-2' }]
  160. @SubscriptionLocator.getMemberSubscriptions.yields(null, @fakeSubscriptions)
  161. it "should pull the users id from the group", (done)->
  162. @SubscriptionUpdater.removeUserFromGroup @subscription._id, @otherUserId, =>
  163. searchOps =
  164. _id: @subscription._id
  165. removeOperation =
  166. "$pull": {member_ids:@otherUserId}
  167. @updateManyStub.calledWith(searchOps, removeOperation).should.equal true
  168. done()
  169. it "should pull the users id from all groups", (done)->
  170. @SubscriptionUpdater.removeUserFromAllGroups @otherUserId, =>
  171. filter =
  172. _id: ['fake-id-1', 'fake-id-2']
  173. removeOperation =
  174. "$pull": {member_ids:@otherUserId}
  175. sinon.assert.calledWith(@updateManyStub, filter, removeOperation)
  176. done()
  177. it "should update the users features", (done)->
  178. @SubscriptionUpdater.removeUserFromGroup @subscription._id, @otherUserId, =>
  179. @FeaturesUpdater.refreshFeatures.calledWith(@otherUserId).should.equal true
  180. done()
  181. it "should not update features for user stubs", (done)->
  182. @UserGetter.getUserOrUserStubById.yields(null, {}, true)
  183. @SubscriptionUpdater.removeUserFromGroup @subscription._id, @userStub._id, =>
  184. @FeaturesUpdater.refreshFeatures.called.should.equal false
  185. done()
  186. describe "deleteSubscription", ->
  187. beforeEach (done) ->
  188. @subscription_id = ObjectId().toString()
  189. @subscription = {
  190. "mock": "subscription",
  191. admin_id: ObjectId(),
  192. member_ids: [ ObjectId(), ObjectId(), ObjectId() ]
  193. }
  194. @SubscriptionLocator.getSubscription = sinon.stub().yields(null, @subscription)
  195. @FeaturesUpdater.refreshFeatures = sinon.stub().yields()
  196. @SubscriptionUpdater.deleteSubscription @subscription_id, done
  197. it "should look up the subscription", ->
  198. @SubscriptionLocator.getSubscription
  199. .calledWith(@subscription_id)
  200. .should.equal true
  201. it "should remove the subscription", ->
  202. @SubscriptionModel.remove
  203. .calledWith({_id: ObjectId(@subscription_id)})
  204. .should.equal true
  205. it "should downgrade the admin_id", ->
  206. @FeaturesUpdater.refreshFeatures
  207. .calledWith(@subscription.admin_id)
  208. .should.equal true
  209. it "should downgrade all of the members", ->
  210. for user_id in @subscription.member_ids
  211. @FeaturesUpdater.refreshFeatures
  212. .calledWith(user_id)
  213. .should.equal true