overleaf/services/web/test/UnitTests/coffee/Subscription/SubscriptionHandlerTests.coffee

209 lines
8 KiB
CoffeeScript

SandboxedModule = require('sandboxed-module')
should = require('chai').should()
sinon = require 'sinon'
querystring = require 'querystring'
modulePath = "../../../../app/js/Features/Subscription/SubscriptionHandler"
mockRecurlySubscriptions =
"subscription-123-active":
uuid: "subscription-123-active"
plan:
name: "Gold"
plan_code: "gold"
current_period_ends_at: new Date()
state: "active"
unit_amount_in_cents: 999
account:
account_code: "user-123"
describe "Subscription Handler sanboxed", ->
beforeEach ->
@Settings =
plans : [{
planCode: "collaborator"
name: "Collaborator"
features:
collaborators: -1
versioning: true
}]
defaultPlanCode :
collaborators: 0
versioning: false
@activeRecurlySubscription = mockRecurlySubscriptions["subscription-123-active"]
@User = {}
@user =
_id: "user_id_here_"
@subscription =
recurlySubscription_id: @activeRecurlySubscription.uuid
@RecurlyWrapper =
getSubscription: sinon.stub().callsArgWith(2, null, @activeRecurlySubscription)
updateSubscription: sinon.stub().callsArgWith(2, null, @activeRecurlySubscription)
cancelSubscription: sinon.stub().callsArgWith(1)
reactivateSubscription: sinon.stub().callsArgWith(1)
redeemCoupon:sinon.stub().callsArgWith(2)
createSubscription: sinon.stub().callsArgWith(3, null, @activeRecurlySubscription)
@DropboxHandler =
unlinkAccount:sinon.stub().callsArgWith(1)
@SubscriptionUpdater =
syncSubscription: sinon.stub().callsArgWith(2)
startFreeTrial: sinon.stub().callsArgWith(1)
@LimitationsManager =
userHasSubscription: sinon.stub()
userHasSubscriptionOrFreeTrial: sinon.stub()
@EmailHandler =
sendEmail:sinon.stub()
@SubscriptionHandler = SandboxedModule.require modulePath, requires:
"./RecurlyWrapper": @RecurlyWrapper
"settings-sharelatex": @Settings
'../../models/User': User:@User
'./SubscriptionUpdater': @SubscriptionUpdater
"logger-sharelatex":{log:->}
'./LimitationsManager':@LimitationsManager
"../Email/EmailHandler":@EmailHandler
"../Dropbox/DropboxHandler":@DropboxHandler
"../../infrastructure/Events": @Events = {emit: sinon.stub()}
@SubscriptionHandler.syncSubscriptionToUser = sinon.stub().callsArgWith(2)
describe "createSubscription", ->
beforeEach (done) ->
@subscriptionDetails =
cvv:"123"
number:"12345"
@recurly_token_id = "45555666"
@SubscriptionHandler.createSubscription(@user, @subscriptionDetails, @recurly_token_id, done)
it "should create the subscription with the wrapper", (done)->
@RecurlyWrapper.createSubscription.calledWith(@user, @subscriptionDetails, @recurly_token_id).should.equal true
done()
it "should sync the subscription to the user", (done)->
@SubscriptionUpdater.syncSubscription.calledOnce.should.equal true
@SubscriptionUpdater.syncSubscription.args[0][0].should.deep.equal @activeRecurlySubscription
@SubscriptionUpdater.syncSubscription.args[0][1].should.deep.equal @user._id
done()
describe "updateSubscription", ->
describe "with a user with a subscription", ->
describe "with a valid plan code", ->
beforeEach (done) ->
@plan_code = "collaborator"
@LimitationsManager.userHasSubscription.callsArgWith(1, null, true, @subscription)
@SubscriptionHandler.updateSubscription(@user, @plan_code, null, done)
it "should update the subscription", ->
@RecurlyWrapper.updateSubscription.calledWith(@subscription.recurlySubscription_id).should.equal true
updateOptions = @RecurlyWrapper.updateSubscription.args[0][1]
updateOptions.plan_code.should.equal @plan_code
it "should update immediately", ->
updateOptions = @RecurlyWrapper.updateSubscription.args[0][1]
updateOptions.timeframe.should.equal "now"
it "should sync the new subscription to the user", ->
@SubscriptionUpdater.syncSubscription.calledOnce.should.equal true
@SubscriptionUpdater.syncSubscription.args[0][0].should.deep.equal @activeRecurlySubscription
@SubscriptionUpdater.syncSubscription.args[0][1].should.deep.equal @user._id
describe "with a user without a subscription", ->
beforeEach (done) ->
@LimitationsManager.userHasSubscription.callsArgWith(1, null, false)
@SubscriptionHandler.updateSubscription(@user, @plan_code, null, done)
it "should redirect to the subscription dashboard", ->
@RecurlyWrapper.updateSubscription.called.should.equal false
@SubscriptionHandler.syncSubscriptionToUser.called.should.equal false
describe "with a coupon code", ->
beforeEach (done) ->
@plan_code = "collaborator"
@coupon_code = "1231312"
@LimitationsManager.userHasSubscription.callsArgWith(1, null, true, @subscription)
@SubscriptionHandler.updateSubscription(@user, @plan_code, @coupon_code, done)
it "should get the users account", ->
@RecurlyWrapper.getSubscription.calledWith(@activeRecurlySubscription.uuid).should.equal true
it "should redeme the coupon", (done)->
@RecurlyWrapper.redeemCoupon.calledWith(@activeRecurlySubscription.account.account_code, @coupon_code).should.equal true
done()
it "should update the subscription", ->
@RecurlyWrapper.updateSubscription.calledWith(@subscription.recurlySubscription_id).should.equal true
updateOptions = @RecurlyWrapper.updateSubscription.args[0][1]
updateOptions.plan_code.should.equal @plan_code
describe "cancelSubscription", ->
describe "with a user without a subscription", ->
beforeEach (done) ->
@LimitationsManager.userHasSubscription.callsArgWith(1, null, false, @subscription)
@SubscriptionHandler.cancelSubscription @user, done
it "should redirect to the subscription dashboard", ->
@RecurlyWrapper.cancelSubscription.called.should.equal false
describe "with a user with a subscription", ->
beforeEach (done) ->
@LimitationsManager.userHasSubscription.callsArgWith(1, null, true, @subscription)
@SubscriptionHandler.cancelSubscription @user, done
it "should cancel the subscription", ->
@RecurlyWrapper.cancelSubscription.called.should.equal true
@RecurlyWrapper.cancelSubscription.calledWith(@subscription.recurlySubscription_id).should.equal true
it "should trigger the cancel subscription event", ->
@Events.emit.calledWith("cancelSubscription", @user._id).should.equal true
describe "reactiveRecurlySubscription", ->
describe "with a user without a subscription", ->
beforeEach (done) ->
@LimitationsManager.userHasSubscription.callsArgWith(1, null, false, @subscription)
@SubscriptionHandler.reactivateSubscription @user, done
it "should redirect to the subscription dashboard", ->
@RecurlyWrapper.reactivateSubscription.called.should.equal false
describe "with a user with a subscription", ->
beforeEach (done) ->
@LimitationsManager.userHasSubscription.callsArgWith(1, null, true, @subscription)
@SubscriptionHandler.reactivateSubscription @user, done
it "should reactivate the subscription", ->
@RecurlyWrapper.reactivateSubscription.called.should.equal true
@RecurlyWrapper.reactivateSubscription.calledWith(@subscription.recurlySubscription_id).should.equal true
describe "recurlyCallback", ->
describe "with an actionable request", ->
beforeEach (done) ->
@user.id = @activeRecurlySubscription.account.account_code
@User.findById = (userId, callback) =>
userId.should.equal @user.id
callback null, @user
@SubscriptionHandler.recurlyCallback(@activeRecurlySubscription, done)
it "should request the affected subscription from the API", ->
@RecurlyWrapper.getSubscription.calledWith(@activeRecurlySubscription.uuid).should.equal true
it "should request the account details of the subscription", ->
options = @RecurlyWrapper.getSubscription.args[0][1]
options.includeAccount.should.equal true
it "should sync the subscription to the user", ->
@SubscriptionUpdater.syncSubscription.calledOnce.should.equal true
@SubscriptionUpdater.syncSubscription.args[0][0].should.deep.equal @activeRecurlySubscription
@SubscriptionUpdater.syncSubscription.args[0][1].should.deep.equal @user._id