codecombat/spec/server/functional/prepaid.spec.coffee
2016-05-24 16:38:52 -07:00

715 lines
29 KiB
CoffeeScript

require '../common'
config = require '../../../server_config'
moment = require 'moment'
{findStripeSubscription} = require '../../../server/lib/utils'
async = require 'async'
nockUtils = require '../nock-utils'
utils = require '../utils'
Promise = require 'bluebird'
Payment = require '../../../server/models/Payment'
Prepaid = require '../../../server/models/Prepaid'
User = require '../../../server/models/User'
Course = require '../../../server/models/Course'
CourseInstance = require '../../../server/models/CourseInstance'
request = require '../request'
describe 'POST /db/prepaid', ->
beforeEach utils.wrap (done) ->
yield utils.clearModels([User, Prepaid])
admin = yield utils.initAdmin()
yield utils.loginUser(admin)
done()
it 'creates a new prepaid for type "course"', utils.wrap (done) ->
user = yield utils.initUser()
[res, body] = yield request.postAsync({url: getURL('/db/prepaid'), json: {
type: 'course'
creator: user.id
}})
expect(res.statusCode).toBe(201)
prepaid = yield Prepaid.findById(res.body._id)
expect(prepaid).toBeDefined()
expect(prepaid.get('creator').equals(user._id)).toBe(true)
expect(prepaid.get('code')).toBeDefined()
done()
it 'does not work for non-admins', utils.wrap (done) ->
user = yield utils.initUser()
yield utils.loginUser(user)
[res, body] = yield request.postAsync({url: getURL('/db/prepaid'), json: {
type: 'course'
creator: user.id
}})
expect(res.statusCode).toBe(403)
done()
it 'accepts start and end dates', utils.wrap (done) ->
user = yield utils.initUser()
[res, body] = yield request.postAsync({url: getURL('/db/prepaid'), json: {
type: 'course'
creator: user.id
startDate: new Date().toISOString(2001,1,1)
endDate: new Date().toISOString(2010,1,1)
}})
expect(res.statusCode).toBe(201)
prepaid = yield Prepaid.findById(res.body._id)
expect(prepaid).toBeDefined()
expect(prepaid.get('startDate')).toBeDefined()
expect(prepaid.get('endDate')).toBeDefined()
done()
describe 'GET /db/prepaid/:handle', ->
it 'populates startDate and endDate with default values', utils.wrap (done) ->
prepaid = new Prepaid({type: 'course' })
yield prepaid.save()
[res, body] = yield request.getAsync({url: getURL("/db/prepaid/#{prepaid.id}"), json: true})
expect(body.endDate).toBe(Prepaid.DEFAULT_END_DATE)
expect(body.startDate).toBe(Prepaid.DEFAULT_START_DATE)
done()
describe 'POST /db/prepaid/:handle/redeemers', ->
beforeEach utils.wrap (done) ->
yield utils.clearModels([Course, CourseInstance, Payment, Prepaid, User])
@teacher = yield utils.initUser({role: 'teacher'})
@admin = yield utils.initAdmin()
yield utils.loginUser(@admin)
@prepaid = yield utils.makePrepaid({ creator: @teacher.id })
yield utils.loginUser(@teacher)
@student = yield utils.initUser()
@url = getURL("/db/prepaid/#{@prepaid.id}/redeemers")
done()
it 'adds a given user to the redeemers property', utils.wrap (done) ->
[res, body] = yield request.postAsync {uri: @url, json: { userID: @student.id } }
expect(body.redeemers.length).toBe(1)
expect(res.statusCode).toBe(201)
prepaid = yield Prepaid.findById(body._id)
expect(prepaid.get('redeemers').length).toBe(1)
@student = yield User.findById(@student.id)
expect(@student.get('coursePrepaid')._id.equals(@prepaid._id)).toBe(true)
expect(@student.get('role')).toBe('student')
done()
it 'returns 403 if maxRedeemers is reached', utils.wrap (done) ->
admin = yield utils.initAdmin()
yield utils.loginUser(admin)
prepaid = yield utils.makePrepaid({ creator: @teacher.id, maxRedeemers: 0 })
url = getURL("/db/prepaid/#{prepaid.id}/redeemers")
yield utils.loginUser(@teacher)
[res, body] = yield request.postAsync({uri: url, json: { userID: @student.id } })
expect(res.statusCode).toBe(403)
expect(res.body.message).toBe('This prepaid is exhausted')
done()
it 'returns 403 unless the user is the "creator"', utils.wrap (done) ->
@otherTeacher = yield utils.initUser({role: 'teacher'})
yield utils.loginUser(@otherTeacher)
[res, body] = yield request.postAsync({uri: @url, json: { userID: @student.id } })
expect(res.statusCode).toBe(403)
expect(res.body.message).toBe('You may not redeem enrollments from this prepaid')
done()
it 'returns 403 if the prepaid is expired', utils.wrap (done) ->
admin = yield utils.initAdmin()
yield utils.loginUser(admin)
prepaid = yield utils.makePrepaid({ creator: @teacher.id, endDate: moment().subtract(1, 'month').toISOString() })
url = getURL("/db/prepaid/#{prepaid.id}/redeemers")
yield utils.loginUser(@teacher)
[res, body] = yield request.postAsync({uri: url, json: { userID: @student.id } })
expect(res.statusCode).toBe(403)
expect(res.body.message).toBe('This prepaid is expired')
done()
it 'is idempotent across prepaids collection', utils.wrap (done) ->
student = yield utils.initUser({ coursePrepaid: { _id: new Prepaid()._id } })
[res, body] = yield request.postAsync({uri: @url, json: { userID: student.id } })
expect(res.statusCode).toBe(200)
expect(body.redeemers.length).toBe(0)
done()
it 'is idempotent to itself', utils.wrap (done) ->
[res, body] = yield request.postAsync({uri: @url, json: { userID: @student.id } })
expect(body.redeemers?.length).toBe(1)
expect(res.statusCode).toBe(201)
[res, body] = yield request.postAsync({uri: @url, json: { userID: @student.id } })
expect(body.redeemers?.length).toBe(1)
expect(res.statusCode).toBe(200)
prepaid = yield Prepaid.findById(body._id)
expect(prepaid.get('redeemers').length).toBe(1)
student = yield User.findById(@student.id)
expect(student.get('coursePrepaid')._id.equals(@prepaid._id)).toBe(true)
done()
it 'updates the user if their enrollment is expired', utils.wrap (done) ->
yield utils.loginUser(@admin)
prepaid = yield utils.makePrepaid({
creator: @teacher.id
startDate: moment().subtract(2, 'month').toISOString()
endDate: moment().subtract(1, 'month').toISOString()
})
@student.set('coursePrepaid', _.pick(prepaid.toObject(), '_id', 'startDate', 'endDate'))
yield @student.save()
yield utils.loginUser(@teacher)
[res, body] = yield request.postAsync {uri: @url, json: { userID: @student.id } }
expect(body.redeemers.length).toBe(1)
expect(res.statusCode).toBe(201)
student = yield User.findById(@student.id)
expect(student.get('coursePrepaid')._id.equals(@prepaid._id)).toBe(true)
done()
describe 'GET /db/prepaid?creator=:id', ->
beforeEach utils.wrap (done) ->
yield utils.clearModels([Course, CourseInstance, Payment, Prepaid, User])
@teacher = yield utils.initUser({role: 'teacher'})
admin = yield utils.initAdmin()
yield utils.loginUser(admin)
@prepaid = yield utils.makePrepaid({ creator: @teacher.id })
@otherPrepaid = yield utils.makePrepaid({ creator: admin.id })
@expiredPrepaid = yield utils.makePrepaid({ creator: @teacher.id, endDate: moment().subtract(1, 'month').toISOString() })
@unmigratedPrepaid = yield utils.makePrepaid({ creator: @teacher.id })
yield @unmigratedPrepaid.update({$unset: { endDate: '', startDate: '' }})
yield utils.loginUser(@teacher)
done()
it 'return all prepaids for the creator', utils.wrap (done) ->
url = getURL("/db/prepaid?creator=#{@teacher.id}")
[res, body] = yield request.getAsync({uri: url, json: true})
expect(res.statusCode).toBe(200)
expect(res.body.length).toEqual(3)
if _.any((prepaid._id is @otherPrepaid.id for prepaid in res.body))
fail('Found the admin prepaid in response')
for prepaid in res.body
unless prepaid.startDate and prepaid.endDate
fail('All prepaids should have start and end dates')
expect(res.body[0]._id).toBe(@prepaid.id)
done()
it 'returns 403 if the user tries to view another user\'s prepaids', utils.wrap (done) ->
anotherUser = yield utils.initUser()
url = getURL("/db/prepaid?creator=#{anotherUser.id}")
[res, body] = yield request.getAsync({uri: url, json: true})
expect(res.statusCode).toBe(403)
done()
describe '/db/prepaid', ->
prepaidURL = getURL('/db/prepaid')
headers = {'X-Change-Plan': 'true'}
joeData = null
stripe = require('stripe')(config.stripe.secretKey)
joeCode = null
verifyCoursePrepaid = (user, prepaid, done) ->
expect(prepaid.creator).toEqual(user.id)
expect(prepaid.type).toEqual('course')
expect(prepaid.maxRedeemers).toBeGreaterThan(0)
expect(prepaid.code).toMatch(/^\w{8}$/)
return done() if user.isAdmin()
Payment.findOne {prepaidID: new ObjectId(prepaid._id)}, (err, payment) ->
expect(err).toBeNull()
expect(payment).not.toBeNull()
expect(payment?.get('purchaser')).toEqual(user._id)
done()
verifySubscriptionPrepaid = (user, prepaid, done) ->
expect(prepaid.creator).toEqual(user.id)
expect(prepaid.type).toEqual('subscription')
expect(prepaid.maxRedeemers).toBeGreaterThan(0)
expect(prepaid.code).toMatch(/^\w{8}$/)
expect(prepaid.properties?.couponID).toEqual('free')
return done() if user.isAdmin()
Payment.findOne {prepaidID: new ObjectId(prepaid._id)}, (err, payment) ->
expect(err).toBeNull()
expect(payment).not.toBeNull()
expect(payment?.get('purchaser')).toEqual(user._id)
done()
it 'Clear database', (done) ->
clearModels [Course, CourseInstance, Payment, Prepaid, User], (err) ->
throw err if err
done()
it 'Anonymous creates prepaid code', (done) ->
createPrepaid 'subscription', 1, 0, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(401)
done()
it 'Non-admin creates prepaid code', (done) ->
loginNewUser (user1) ->
expect(user1.isAdmin()).toEqual(false)
createPrepaid 'subscription', 4, 0, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(403)
done()
it 'Admin creates prepaid code with type subscription', (done) ->
loginNewUser (user1) ->
user1.set('permissions', ['admin'])
user1.save (err, user1) ->
expect(err).toBeNull()
expect(user1.isAdmin()).toEqual(true)
createPrepaid 'subscription', 1, 0, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
verifySubscriptionPrepaid user1, body, done
it 'Admin creates prepaid code with type terminal_subscription', (done) ->
loginNewUser (user1) ->
user1.set('permissions', ['admin'])
user1.save (err, user1) ->
expect(err).toBeNull()
expect(user1.isAdmin()).toEqual(true)
createPrepaid 'terminal_subscription', 2, 3, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
expect(body.creator).toEqual(user1.id)
expect(body.type).toEqual('terminal_subscription')
expect(body.maxRedeemers).toEqual(2)
expect(body.properties?.months).toEqual(3)
expect(body.code).toMatch(/^\w{8}$/)
done()
it 'Admin creates prepaid code with invalid type', (done) ->
loginNewUser (user1) ->
user1.set('permissions', ['admin'])
user1.save (err, user1) ->
expect(err).toBeNull()
expect(user1.isAdmin()).toEqual(true)
createPrepaid 'bulldozer', 1, 0, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(403)
done()
it 'Admin creates prepaid code with no type specified', (done) ->
loginNewUser (user1) ->
user1.set('permissions', ['admin'])
user1.save (err, user1) ->
expect(err).toBeNull()
expect(user1.isAdmin()).toEqual(true)
createPrepaid null, 1, 0, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(403)
done()
it 'Admin creates prepaid code with invalid maxRedeemers', (done) ->
loginNewUser (user1) ->
user1.set('permissions', ['admin'])
user1.save (err, user1) ->
expect(err).toBeNull()
expect(user1.isAdmin()).toEqual(true)
createPrepaid 'subscription', 0, 0, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(403)
done()
it 'Non-admin requests /db/prepaid', (done) ->
loginNewUser (user1) ->
expect(user1.isAdmin()).toEqual(false)
request.get {uri: prepaidURL}, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(403)
done()
it 'Admin requests /db/prepaid', (done) ->
loginNewUser (user1) ->
user1.set('permissions', ['admin'])
user1.save (err, user1) ->
expect(err).toBeNull()
expect(user1.isAdmin()).toEqual(true)
createPrepaid 'subscription', 1, 0, (err, res, prepaid) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
request.get {uri: prepaidURL}, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
prepaids = JSON.parse(body)
found = false
for p in prepaids
if p._id is prepaid._id
found = true
verifySubscriptionPrepaid user1, p, done
break
expect(found).toEqual(true)
done() unless found
describe 'Purchase course', ->
afterEach nockUtils.teardownNock
it 'Standard user purchases a prepaid for 0 seats', (done) ->
nockUtils.setupNock 'db-prepaid-purchase-course-test-1.json', (err, nockDone) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user1) ->
purchasePrepaid 'course', {}, 0, token.id, (err, res, prepaid) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(422)
nockDone()
done()
it 'Standard user purchases a prepaid for 1 seat', (done) ->
nockUtils.setupNock 'db-prepaid-purchase-course-test-2.json', (err, nockDone) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user1) ->
purchasePrepaid 'course', {}, 1, token.id, (err, res, prepaid) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
verifyCoursePrepaid user1, prepaid, ->
nockDone()
done()
it 'Standard user purchases a prepaid for 3 seats', (done) ->
nockUtils.setupNock 'db-prepaid-purchase-course-test-3.json', (err, nockDone) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user1) ->
purchasePrepaid 'course', {}, 3, token.id, (err, res, prepaid) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
verifyCoursePrepaid user1, prepaid, ->
nockDone()
done()
describe 'Purchase terminal_subscription', ->
afterEach nockUtils.teardownNock
it 'Anonymous submits a prepaid purchase', (done) ->
nockUtils.setupNock 'db-prepaid-purchase-term-sub-test-1.json', (err, nockDone) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
logoutUser () ->
purchasePrepaid 'terminal_subscription', months: 3, 3, token.id, (err, res, prepaid) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(401)
nockDone()
done()
it 'Should error if type isnt terminal_subscription', (done) ->
nockUtils.setupNock 'db-prepaid-purchase-term-sub-test-2.json', (err, nockDone) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user1) ->
purchasePrepaid 'subscription', months: 3, 3, token.id, (err, res, prepaid) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(403)
nockDone()
done()
it 'Should error if maxRedeemers is -1', (done) ->
nockUtils.setupNock 'db-prepaid-purchase-term-sub-test-3.json', (err, nockDone) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user1) ->
purchasePrepaid 'terminal_subscription', months: 3, -1, token.id, (err, res, prepaid) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(422)
nockDone()
done()
it 'Should error if maxRedeemers is foo', (done) ->
nockUtils.setupNock 'db-prepaid-purchase-term-sub-test-4.json', (err, nockDone) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user1) ->
purchasePrepaid 'terminal_subscription', months: 3, 'foo', token.id, (err, res, prepaid) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(422)
nockDone()
done()
it 'Should error if months is -1', (done) ->
nockUtils.setupNock 'db-prepaid-purchase-term-sub-test-5.json', (err, nockDone) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user1) ->
purchasePrepaid 'terminal_subscription', months: -1, 3, token.id, (err, res, prepaid) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(422)
nockDone()
done()
it 'Should error if months is foo', (done) ->
nockUtils.setupNock 'db-prepaid-purchase-term-sub-test-6.json', (err, nockDone) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user1) ->
purchasePrepaid 'terminal_subscription', months: 'foo', 3, token.id, (err, res, prepaid) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(422)
nockDone()
done()
it 'Should error if maxRedeemers and months are less than 3', (done) ->
nockUtils.setupNock 'db-prepaid-purchase-term-sub-test-7.json', (err, nockDone) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user1) ->
purchasePrepaid 'terminal_subscription', months: 1, 1, token.id, (err, res, prepaid) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(403)
nockDone()
done()
it 'User submits valid prepaid code purchase', (done) ->
nockUtils.setupNock 'db-prepaid-purchase-term-sub-test-8.json', (err, nockDone) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
stripeTokenID = token.id
loginJoe (joe) ->
joeData = joe.toObject()
joeData.stripe = {
token: stripeTokenID
planID: 'basic'
}
request.put {uri: getURL('/db/user'), json: joeData, headers: headers }, (err, res, body) ->
joeData = body
expect(res.statusCode).toBe(200)
expect(joeData.stripe.customerID).toBeDefined()
expect(firstSubscriptionID = joeData.stripe.subscriptionID).toBeDefined()
expect(joeData.stripe.planID).toBe('basic')
expect(joeData.stripe.token).toBeUndefined()
# TODO: is this test still valid after new token?
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
purchasePrepaid 'terminal_subscription', months: 3, 3, token.id, (err, res, prepaid) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
expect(prepaid.type).toEqual('terminal_subscription')
expect(prepaid.code).toBeDefined()
# Saving this code for later tests
# TODO: don't make tests dependent on each other
joeCode = prepaid.code
expect(prepaid.creator).toBeDefined()
expect(prepaid.maxRedeemers).toEqual(3)
expect(prepaid.exhausted).toBe(false)
expect(prepaid.properties).toBeDefined()
expect(prepaid.properties.months).toEqual(3)
nockDone()
done()
it 'Should have logged a Payment with the correct amount', (done) ->
loginJoe (joe) ->
query =
purchaser: joe._id
Payment.find query, (err, payments) ->
expect(err).toBeNull()
expect(payments).not.toBeNull()
expect(payments.length).toEqual(1)
expect(payments[0].get('amount')).toEqual(900)
done()
it 'Anonymous cant redeem a prepaid code', (done) ->
logoutUser () ->
subscribeWithPrepaid joeCode, (err, res) ->
expect(err).toBeNull()
expect(res?.statusCode).toEqual(401)
done()
it 'User cant redeem a nonexistant prepaid code', (done) ->
loginJoe (joe) ->
subscribeWithPrepaid 'abc123', (err, res) ->
expect(err).toBeNull()
expect(res.statusCode).toEqual(404)
done()
it 'User cant redeem empty code', (done) ->
loginJoe (joe) ->
subscribeWithPrepaid '', (err, res) ->
expect(err).toBeNull()
expect(res.statusCode).toEqual(422)
done()
it 'Anonymous cant fetch a prepaid code', (done) ->
expect(joeCode).not.toBeNull()
logoutUser () ->
fetchPrepaid joeCode, (err, res) ->
expect(err).toBeNull()
expect(res.statusCode).toEqual(403)
done()
it 'User can fetch a prepaid code', (done) ->
expect(joeCode).not.toBeNull()
loginJoe (joe) ->
fetchPrepaid joeCode, (err, res, body) ->
expect(err).toBeNull()
expect(res.statusCode).toEqual(200)
expect(body).toBeDefined()
return done() unless body
prepaid = JSON.parse(body)
expect(prepaid.code).toEqual(joeCode)
expect(prepaid.maxRedeemers).toEqual(3)
expect(prepaid.properties?.months).toEqual(3)
done()
# TODO: Move redeem subscription prepaid code tests to subscription tests file
describe 'Subscription redeem tests', ->
afterEach nockUtils.teardownNock
it 'Creator can redeeem a prepaid code', (done) ->
nockUtils.setupNock 'db-sub-redeem-test-1.json', (err, nockDone) ->
loginJoe (joe) ->
expect(joeCode).not.toBeNull()
expect(joeData.stripe?.customerID).toBeDefined()
expect(joeData.stripe?.subscriptionID).toBeDefined()
return done() unless joeData.stripe?.customerID
# joe has a stripe subscription, so test if the months are added to the end of it.
stripe.customers.retrieve joeData.stripe.customerID, (err, customer) =>
expect(err).toBeNull()
findStripeSubscription customer.id, subscriptionID: joeData.stripe?.subscriptionID, (subscription) =>
if subscription
stripeSubscriptionPeriodEndDate = new moment(subscription.current_period_end * 1000)
else
expect(stripeSubscriptionPeriodEndDate).toBeDefined()
return done()
subscribeWithPrepaid joeCode, (err, res, result) =>
expect(err).toBeNull()
expect(res.statusCode).toEqual(200)
endDate = stripeSubscriptionPeriodEndDate.add(3, 'months').toISOString().substring(0, 10)
expect(result?.stripe?.free).toEqual(endDate)
expect(result?.purchased?.gems).toEqual(14000)
findStripeSubscription customer.id, subscriptionID: joeData.stripe?.subscriptionID, (subscription) =>
expect(subscription).toBeNull()
nockDone()
done()
it 'User can redeem a prepaid code', (done) ->
loginSam (sam) ->
subscribeWithPrepaid joeCode, (err, res, result) ->
expect(err).toBeNull()
expect(res.statusCode).toEqual(200)
endDate = new moment().add(3, 'months').toISOString().substring(0, 10)
expect(result?.stripe?.free).toEqual(endDate)
expect(result?.purchased?.gems).toEqual(10500)
done()
it 'Wont allow the same person to redeem twice', (done) ->
loginSam (sam) ->
subscribeWithPrepaid joeCode, (err, res, result) ->
expect(err).toBeNull()
expect(res.statusCode).toEqual(403)
done()
it 'Will return redeemed code as part of codes list', (done) ->
loginSam (sam) ->
request.get "#{getURL('/db/user')}/#{sam.id}/prepaid_codes", (err, res) ->
expect(err).toBeNull()
expect(res.statusCode).toEqual(200)
codes = JSON.parse res.body
expect(codes.length).toEqual(1)
done()
it 'Third user can redeem a prepaid code', (done) ->
loginNewUser (user) ->
subscribeWithPrepaid joeCode, (err, res, result) ->
expect(err).toBeNull()
expect(res.statusCode).toEqual(200)
endDate = new moment().add(3, 'months').toISOString().substring(0, 10)
expect(result?.stripe?.free).toEqual(endDate)
expect(result?.purchased?.gems).toEqual(10500)
done()
it 'Fourth user cannot redeem code', (done) ->
loginNewUser (user) ->
subscribeWithPrepaid joeCode, (err, res, result) ->
expect(err).toBeNull()
expect(res.statusCode).toEqual(403)
done()
it 'Can fetch a list of purchased and redeemed prepaid codes', (done) ->
nockUtils.setupNock 'db-sub-redeem-test-2.json', (err, nockDone) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user) ->
purchasePrepaid 'terminal_subscription', months: 1, 3, token.id, (err, res, prepaid) ->
request.get "#{getURL('/db/user')}/#{user.id}/prepaid_codes", (err, res) ->
expect(err).toBeNull()
expect(res.statusCode).toEqual(200);
codes = JSON.parse res.body
expect(codes.length).toEqual(1)
expect(codes[0].maxRedeemers).toEqual(3)
expect(codes[0].properties).toBeDefined()
expect(codes[0].properties.months).toEqual(1)
nockDone()
done()
it 'Test for injection', (done) ->
loginNewUser (user) ->
code = { $exists: true }
subscribeWithPrepaid code, (err, res, result) ->
expect(err).toBeNull()
expect(res.statusCode).not.toEqual(200)
done()
it 'enforces the maximum number of redeemers in a race condition', utils.wrap (done) ->
nockDone = yield nockUtils.setupNockAsync 'db-sub-redeem-test-3.json'
stripe.tokens.createAsync = Promise.promisify(stripe.tokens.create, {context: stripe.tokens})
token = yield stripe.tokens.createAsync({
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
})
user = yield utils.initUser()
yield utils.loginUser(user)
codeRedeemers = 50
codeMonths = 3
redeemers = 51
purchasePrepaidAsync = Promise.promisify(purchasePrepaid, {multiArgs: true})
[res, prepaid] = yield purchasePrepaidAsync('terminal_subscription', months: codeMonths, codeRedeemers, token.id)
expect(prepaid).toBeDefined()
expect(prepaid.code).toBeDefined()
# Make 'threads', which are objects that encapsulate each user and their cookies
threads = []
for index in [0...redeemers]
thread = {}
thread.request = request.defaults({jar: request.jar()})
thread.request.postAsync = Promise.promisify(thread.request.post, { context: thread.request })
thread.user = yield utils.initUser()
yield utils.loginUser(thread.user, {request: thread.request})
threads.push(thread)
# Spawn all requests at once!
requests = []
options = {
url: getURL('/db/subscription/-/subscribe_prepaid')
json: { ppc: prepaid.code }
}
for thread in threads
requests.push(thread.request.postAsync(options))
# Wait until all requests finish, make sure all but one succeeded
responses = yield requests
redeemed = _.size(_.where(responses, {statusCode: 200}))
errors = _.size(_.where(responses, {statusCode: 403}))
expect(redeemed).toEqual(codeRedeemers)
expect(errors).toEqual(redeemers - codeRedeemers)
nockDone()
done()