mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
85e7f688d5
Display Pricing Exceptions on Subscription Dashboard GitOrigin-RevId: 31de89824db70b7af1f8704e6da592064ce44bfd
354 lines
11 KiB
CoffeeScript
354 lines
11 KiB
CoffeeScript
expect = require('chai').expect
|
|
async = require("async")
|
|
User = require "./helpers/User"
|
|
{Subscription} = require "../../../app/js/models/Subscription"
|
|
{Institution} = require "../../../app/js/models/Institution"
|
|
SubscriptionViewModelBuilder = require "../../../app/js/Features/Subscription/SubscriptionViewModelBuilder"
|
|
|
|
MockRecurlyApi = require "./helpers/MockRecurlyApi"
|
|
MockV1Api = require "./helpers/MockV1Api"
|
|
|
|
describe 'Subscriptions', ->
|
|
describe 'dashboard', ->
|
|
before (done) ->
|
|
@user = new User()
|
|
@user.ensureUserExists done
|
|
|
|
describe 'when the user has no subscription', ->
|
|
before (done) ->
|
|
SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
|
|
return done(error) if error?
|
|
done()
|
|
|
|
it 'should return no personalSubscription', ->
|
|
expect(@data.personalSubscription).to.equal null
|
|
|
|
it 'should return no memberGroupSubscriptions', ->
|
|
expect(@data.memberGroupSubscriptions).to.deep.equal []
|
|
|
|
describe 'when the user has a subscription with recurly', ->
|
|
before (done) ->
|
|
MockRecurlyApi.accounts['mock-account-id'] = @accounts = {
|
|
hosted_login_token: 'mock-login-token'
|
|
}
|
|
MockRecurlyApi.subscriptions['mock-subscription-id'] = @subscription = {
|
|
plan_code: 'collaborator',
|
|
tax_in_cents: 100,
|
|
tax_rate: 0.2,
|
|
unit_amount_in_cents: 500,
|
|
currency: 'GBP',
|
|
current_period_ends_at: new Date(2018,4,5),
|
|
state: 'active',
|
|
account_id: 'mock-account-id',
|
|
trial_ends_at: new Date(2018, 6, 7)
|
|
}
|
|
MockRecurlyApi.coupons = @coupons = {
|
|
'test-coupon-1': { description: 'Test Coupon 1' }
|
|
'test-coupon-2': { description: 'Test Coupon 2' }
|
|
'test-coupon-3': { name: 'TestCoupon3' }
|
|
}
|
|
Subscription.create {
|
|
admin_id: @user._id,
|
|
manager_ids: [@user._id],
|
|
recurlySubscription_id: 'mock-subscription-id',
|
|
planCode: 'collaborator'
|
|
}, (error) =>
|
|
return done(error) if error?
|
|
SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
|
|
return done(error) if error?
|
|
done()
|
|
return
|
|
|
|
after (done) ->
|
|
MockRecurlyApi.accounts = {}
|
|
MockRecurlyApi.subscriptions = {}
|
|
MockRecurlyApi.coupons = {}
|
|
MockRecurlyApi.redemptions = {}
|
|
Subscription.remove {
|
|
admin_id: @user._id
|
|
}, done
|
|
return
|
|
|
|
it 'should return a personalSubscription with populated recurly data', ->
|
|
subscription = @data.personalSubscription
|
|
expect(subscription).to.exist
|
|
expect(subscription.planCode).to.equal 'collaborator'
|
|
expect(subscription.recurly).to.exist
|
|
expect(subscription.recurly).to.deep.equal {
|
|
"activeCoupons": []
|
|
"billingDetailsLink": "https://test.recurly.com/account/billing_info/edit?ht=mock-login-token"
|
|
"currency": "GBP"
|
|
"nextPaymentDueAt": "5th May 2018"
|
|
"price": "£6.00"
|
|
"state": "active"
|
|
"tax": 100
|
|
"taxRate": 0.2
|
|
"trial_ends_at": new Date(2018, 6, 7),
|
|
"trialEndsAtFormatted": "7th July 2018"
|
|
}
|
|
|
|
it 'should return no memberGroupSubscriptions', ->
|
|
expect(@data.memberGroupSubscriptions).to.deep.equal []
|
|
|
|
it 'should include redeemed coupons', (done) ->
|
|
MockRecurlyApi.redemptions['mock-account-id'] = [
|
|
{ state: 'active', coupon_code: 'test-coupon-1' }
|
|
{ state: 'inactive', coupon_code: 'test-coupon-2' }
|
|
{ state: 'active', coupon_code: 'test-coupon-3' }
|
|
]
|
|
|
|
# rebuild the view model with the redemptions
|
|
SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, data) ->
|
|
expect(error).to.not.exist
|
|
expect(data.personalSubscription.recurly.activeCoupons).to.deep.equal [
|
|
{
|
|
coupon_code: 'test-coupon-1',
|
|
name: '',
|
|
description: 'Test Coupon 1'
|
|
}
|
|
{
|
|
coupon_code: 'test-coupon-3',
|
|
name: 'TestCoupon3',
|
|
description: ''
|
|
}
|
|
]
|
|
done()
|
|
|
|
describe 'when the user has a subscription without recurly', ->
|
|
before (done) ->
|
|
Subscription.create {
|
|
admin_id: @user._id,
|
|
manager_ids: [@user._id],
|
|
planCode: 'collaborator'
|
|
}, (error) =>
|
|
return done(error) if error?
|
|
SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
|
|
return done(error) if error?
|
|
done()
|
|
return
|
|
|
|
after (done) ->
|
|
Subscription.remove {
|
|
admin_id: @user._id
|
|
}, done
|
|
return
|
|
|
|
it 'should return a personalSubscription with no recurly data', ->
|
|
subscription = @data.personalSubscription
|
|
expect(subscription).to.exist
|
|
expect(subscription.planCode).to.equal 'collaborator'
|
|
expect(subscription.recurly).to.not.exist
|
|
|
|
it 'should return no memberGroupSubscriptions', ->
|
|
expect(@data.memberGroupSubscriptions).to.deep.equal []
|
|
|
|
describe 'when the user is a member of a group subscription', ->
|
|
before (done) ->
|
|
@owner1 = new User()
|
|
@owner2 = new User()
|
|
async.series [
|
|
(cb) => @owner1.ensureUserExists cb
|
|
(cb) => @owner2.ensureUserExists cb
|
|
(cb) => Subscription.create {
|
|
admin_id: @owner1._id,
|
|
manager_ids: [@owner1._id],
|
|
planCode: 'collaborator',
|
|
groupPlan: true,
|
|
member_ids: [@user._id]
|
|
}, cb
|
|
(cb) => Subscription.create {
|
|
admin_id: @owner2._id,
|
|
manager_ids: [@owner2._id],
|
|
planCode: 'collaborator',
|
|
groupPlan: true,
|
|
member_ids: [@user._id]
|
|
}, cb
|
|
], (error) =>
|
|
return done(error) if error?
|
|
SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
|
|
return done(error) if error?
|
|
done()
|
|
return
|
|
|
|
after (done) ->
|
|
Subscription.remove {
|
|
admin_id: @owner1._id
|
|
}, (error) =>
|
|
return done(error) if error?
|
|
Subscription.remove {
|
|
admin_id: @owner2._id
|
|
}, done
|
|
return
|
|
|
|
it 'should return no personalSubscription', ->
|
|
expect(@data.personalSubscription).to.equal null
|
|
|
|
it 'should return the two memberGroupSubscriptions', ->
|
|
expect(@data.memberGroupSubscriptions.length).to.equal 2
|
|
expect(
|
|
# Mongoose populates the admin_id with the user
|
|
@data.memberGroupSubscriptions[0].admin_id._id.toString()
|
|
).to.equal @owner1._id
|
|
expect(
|
|
@data.memberGroupSubscriptions[1].admin_id._id.toString()
|
|
).to.equal @owner2._id
|
|
|
|
describe 'when the user is a manager of a group subscription', ->
|
|
before (done) ->
|
|
@owner1 = new User()
|
|
@owner2 = new User()
|
|
async.series [
|
|
(cb) => @owner1.ensureUserExists cb
|
|
(cb) => @owner2.ensureUserExists cb
|
|
(cb) => Subscription.create {
|
|
admin_id: @owner1._id,
|
|
manager_ids: [@owner1._id, @user._id],
|
|
planCode: 'collaborator',
|
|
groupPlan: true
|
|
}, cb
|
|
], (error) =>
|
|
return done(error) if error?
|
|
SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
|
|
return done(error) if error?
|
|
done()
|
|
return
|
|
|
|
after (done) ->
|
|
Subscription.remove {
|
|
admin_id: @owner1._id
|
|
}, done
|
|
return
|
|
|
|
it 'should return no personalSubscription', ->
|
|
expect(@data.personalSubscription).to.equal null
|
|
|
|
it 'should return the managedGroupSubscriptions', ->
|
|
expect(@data.managedGroupSubscriptions.length).to.equal 1
|
|
subscription = @data.managedGroupSubscriptions[0]
|
|
expect(
|
|
# Mongoose populates the admin_id with the user
|
|
subscription.admin_id._id.toString()
|
|
).to.equal @owner1._id
|
|
expect(subscription.groupPlan).to.equal true
|
|
|
|
describe 'when the user is a manager of an institution', ->
|
|
before (done) ->
|
|
@v1Id = MockV1Api.nextV1Id()
|
|
async.series [
|
|
(cb) =>
|
|
Institution.create({
|
|
v1Id: @v1Id,
|
|
managerIds: [@user._id]
|
|
}, cb)
|
|
], (error) =>
|
|
return done(error) if error?
|
|
SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
|
|
return done(error) if error?
|
|
done()
|
|
return
|
|
|
|
after (done) ->
|
|
Institution.remove {
|
|
v1Id: @v1Id
|
|
}, done
|
|
return
|
|
|
|
it 'should return the managedInstitutions', ->
|
|
expect(@data.managedInstitutions.length).to.equal 1
|
|
institution = @data.managedInstitutions[0]
|
|
expect(institution.v1Id).to.equal @v1Id
|
|
expect(institution.name).to.equal "Institution #{@v1Id}"
|
|
|
|
describe 'when the user is a member of an affiliation', ->
|
|
before (done) ->
|
|
v1Id = MockV1Api.nextV1Id()
|
|
MockV1Api.setUser v1Id, {
|
|
subscription: {},
|
|
subscription_status: {}
|
|
}
|
|
MockV1Api.setAffiliations [{
|
|
email: 'confirmed-affiliation-email@stanford.example.edu'
|
|
institution: { name: 'Stanford', licence: 'pro_plus', confirmed: true }
|
|
}, {
|
|
email: 'unconfirmed-affiliation-email@harvard.example.edu'
|
|
institution: { name: 'Harvard', licence: 'pro_plus', confirmed: true }
|
|
}, {
|
|
email: 'confirmed-affiliation-email@mit.example.edu'
|
|
institution: { name: 'MIT', licence: 'pro_plus', confirmed: false }
|
|
}]
|
|
async.series [
|
|
(cb) =>
|
|
@user.setV1Id v1Id, cb
|
|
(cb) =>
|
|
@user.addEmail 'unconfirmed-affiliation-email@harvard.example.edu', cb
|
|
(cb) =>
|
|
@user.addEmail 'confirmed-affiliation-email@stanford.example.edu', cb
|
|
(cb) =>
|
|
@user.confirmEmail 'confirmed-affiliation-email@stanford.example.edu', cb
|
|
(cb) =>
|
|
@user.addEmail 'confirmed-affiliation-email@mit.example.edu', cb
|
|
(cb) =>
|
|
@user.confirmEmail 'confirmed-affiliation-email@mit.example.edu', cb
|
|
], (error) =>
|
|
return done(error) if error?
|
|
SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
|
|
return done(error) if error?
|
|
done()
|
|
|
|
it 'should return only the affilations with confirmed institutions, and confirmed emails', ->
|
|
expect(@data.confirmedMemberInstitutions).to.deep.equal [
|
|
{ name: 'Stanford', licence: 'pro_plus', confirmed: true }
|
|
]
|
|
|
|
describe 'when the user has a v1 subscription', ->
|
|
before (done) ->
|
|
MockV1Api.setUser v1Id = MockV1Api.nextV1Id(), {
|
|
subscription: @subscription = {
|
|
trial: false,
|
|
has_plan: true,
|
|
teams: [{
|
|
id: 56,
|
|
name: 'Test team'
|
|
}]
|
|
}
|
|
subscription_status: @subscription_status = {
|
|
product: { 'mock': 'product' }
|
|
team: null
|
|
}
|
|
}
|
|
@user.setV1Id v1Id, (error) =>
|
|
return done(error) if error?
|
|
SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel @user, (error, @data) =>
|
|
return done(error) if error?
|
|
done()
|
|
|
|
it 'should return no personalSubscription', ->
|
|
expect(@data.personalSubscription).to.equal null
|
|
|
|
it 'should return no memberGroupSubscriptions', ->
|
|
expect(@data.memberGroupSubscriptions).to.deep.equal []
|
|
|
|
it 'should return a v1SubscriptionStatus', ->
|
|
expect(@data.v1SubscriptionStatus).to.deep.equal @subscription_status
|
|
|
|
describe 'canceling', ->
|
|
before (done) ->
|
|
@user = new User()
|
|
MockV1Api.setUser v1Id = MockV1Api.nextV1Id(), @v1_user = {}
|
|
async.series [
|
|
(cb) => @user.login(cb)
|
|
(cb) => @user.setV1Id(v1Id, cb)
|
|
], (error) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/subscription/v1/cancel'
|
|
}, (error, @response) =>
|
|
return done(error) if error?
|
|
done()
|
|
|
|
it 'should tell v1 to cancel the subscription', ->
|
|
expect(@v1_user.canceled).to.equal true
|
|
|
|
it 'should redirect to the subscription dashboard', ->
|
|
expect(@response.statusCode).to.equal 302
|
|
expect(@response.headers.location).to.equal '/user/subscription'
|