Merge branch 'master' into production

This commit is contained in:
Matt Lott 2015-08-27 09:48:48 -07:00
commit 448f4fce88
10 changed files with 443 additions and 58 deletions
app
assets/images/pages/account/subscription
locale
styles/account
templates/account
views/account
scripts/analytics/mongodb/queries
server/payments
test/server/functional

Binary file not shown.

After

(image error) Size: 80 KiB

View file

@ -402,7 +402,7 @@
subscribe:
comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
feature1: "100+ basic levels across 4 worlds"
feature2: "10 powerful <strong>new heroes</strong> with unique skills!"
feature2: "9 powerful <strong>new heroes</strong> with unique skills!" # {changed}
feature3: "70+ bonus levels"
feature4: "<strong>3500 bonus gems</strong> every month!"
feature5: "Video tutorials"
@ -439,12 +439,17 @@
payment_methods_blurb2: "If you require an alternate form of payment, please contact"
sale_already_subscribed: "You're already subscribed!"
sale_blurb1: "Save 35%"
sale_blurb2: "off regular subscription price!"
sale_blurb2: "off regular subscription price of $120 for a whole year!" # {changed}
sale_button: "Sale!"
sale_button_title: "Save 35% when you purchase a 1 year subscription"
sale_click_here: "Click Here"
sale_ends: "Ends"
sale_extended: "*Existing subscriptions will be extended by 1 year."
sale_feature_here: "Here's what you'll get:"
sale_feature4: "<strong>42,000 bonus gems</strong> awarded immediately!"
sale_continue: "Ready to continue adventuring?"
sale_paid: "Payment received. Thanks!"
sale_limited_time: "Limited time offer!"
sale_new_heroes: "New heroes!"
sale_title: "Back to School Sale"
sale_view_button: "Buy 1 year subscription for"
stripe_description: "Monthly Subscription"
@ -613,7 +618,7 @@
sub_includes_2: "70+ practice levels"
sub_includes_3: "Video tutorials"
sub_includes_4: "Premium email support"
sub_includes_5: "10 new heroes with unique skills to master"
sub_includes_5: "9 new heroes with unique skills to master" # {changed}
sub_includes_6: "3500 bonus gems every month"
sub_includes_7: "Private Clans"
monitor_progress_title: "How do I monitor student progress?"

View file

@ -611,7 +611,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
private_clans_1: "Private Clans provide increased privacy and detailed progress information for each student."
private_clans_2: "Pour créer un Clan privé, veuillez vous référer à la boîte à cocher 'Faire un clan privé' pendant la création du"
private_clans_3: "."
who_for_title: "A qui CodeCombat est t-il destiné ?"
who_for_title: "A qui CodeCombat est-il destiné ?"
who_for_1: "Nous recommandons CodeCombat pour les élèves âgés de 9 ans ou plus. Aucune expérience préalable de programmation n'est requise."
who_for_2: "Nous avons conçu CodeCombat pour plaire à la fois aux garçons et aux filles."
material_title: "Quelle quantité de contenu y a t-il ?"

View file

@ -1,7 +1,30 @@
#subscription-sale-view
.above-blurb
margin: 0 16% 0 16%
.center
text-align: center
.feature-description
font-size: 16px
.sale-blurb
font-size: 22px
.sale-ends
position: relative
left: 0px
top: 50px
font-size: 18px
line-height: 18px
background-color: red
color: white
margin: 0 7px
border-radius: 3px
padding: 6px
width: 200px
text-align: center
-ms-transform: rotate(330deg) /* IE 9 */
-moz-transform: rotate(330deg) /* Firefox */
-webkit-transform: rotate(330deg) /* Safari and Chrome */
-o-transform: rotate(330deg) /* Opera */
.sub-extended
font-size: 12px
#pay-button
font-size: 18px

View file

@ -12,9 +12,7 @@ block content
a(href="/account/subscription", data-i18n="account.subscription")
li.active(data-i18n="account.sale") Sale
if me.get('anonymous')
p(data-i18n="account_settings.not_logged_in")
else if me.hasSubscription()
if hasSubscription
h1(data-i18n="subscribe.sale_already_subscribed")
span.spr(data-i18n="subscribe.sale_continue")
a(href="/play", data-i18n="subscribe.sale_click_here")
@ -22,25 +20,47 @@ block content
if state === 'purchasing'
.alert.alert-info(data-i18n="account_invoices.purchasing")
else
div.sale-ends
if new Date() < saleEndDate
span.spr(data-i18n="subscribe.sale_ends")
span #{moment(saleEndDate).fromNow()}
else
span(data-i18n="subscribe.sale_limited_time")
h1.center(data-i18n="subscribe.sale_title")
p.center
img(src="/images/pages/account/subscription/teacher-banner.png")
br
p.center.sale-blurb
strong.spr(data-i18n="subscribe.sale_blurb1")
span(data-i18n="subscribe.sale_blurb2")
.above-blurb
p.sale-blurb
strong.spr(data-i18n="subscribe.sale_blurb1")
span(data-i18n="subscribe.sale_blurb2")
br
div
.sale-blurb(data-i18n="subscribe.sale_feature_here")
ul
li.feature-description(data-i18n="[html]subscribe.feature2")
li.feature-description(data-i18n="subscribe.feature3")
li.feature-description(data-i18n="[html]subscribe.sale_feature4")
li.feature-description(data-i18n="subscribe.feature5")
li.feature-description(data-i18n="[html]subscribe.feature7")
div.sub-extended(data-i18n="subscribe.sale_extended")
br
p.center
button.btn.btn-success#pay-button #{payButtonText}
table.above-blurb(cellpadding="8")
tr
td(colspan=2)
h2.center(data-i18n="subscribe.sale_new_heroes")
each hero in heroes
if hero.get('extendedName') !== 'Captain Anya Weston' && hero.get('extendedName') !== 'Sir Tharin Thunderfist'
tr
td
img(src="http://codecombat.com#{hero.getPortraitURL()}")
td
p.sale-blurb #{hero.name}
p #{hero.class}
p #{hero.description}
br
if !state || state !== 'invoice_paid'
p.center
button.btn.btn-success#pay-button #{payButtonText}
br
else if state === 'invoice_paid'
div.center
span.spr(data-i18n="subscribe.sale_continue")
a(href="/play", data-i18n="subscribe.sale_click_here")
br
#declined-alert.alert.alert-success.alert-dismissible
button.close(type="button" data-dismiss="alert")
span(aria-hidden="true") &times;
p(data-i18n="subscribe.sale_paid")
if state === 'declined'
#declined-alert.alert.alert-danger.alert-dismissible
span(data-i18n="account_invoices.declined")

View file

@ -1,12 +1,17 @@
RootView = require 'views/core/RootView'
template = require 'templates/account/subscription-sale-view'
app = require 'core/application'
AuthModal = require 'views/core/AuthModal'
CocoCollection = require 'collections/CocoCollection'
stripeHandler = require 'core/services/stripe'
ThangType = require 'models/ThangType'
utils = require 'core/utils'
module.exports = class SubscriptionSaleView extends RootView
id: "subscription-sale-view"
template: template
yearSaleAmount: 7900
saleEndDate: new Date('2015-09-05')
events:
'click #pay-button': 'onPayButton'
@ -19,15 +24,34 @@ module.exports = class SubscriptionSaleView extends RootView
@description = $.i18n.t('subscribe.stripe_description_year_sale')
displayAmount = (@yearSaleAmount / 100).toFixed(2)
@payButtonText = "#{$.i18n.t('subscribe.sale_view_button')} $#{displayAmount}"
@heroes = new CocoCollection([], {model: ThangType})
@heroes.url = '/db/thang.type?view=heroes'
@heroes.setProjection ['original','name','heroClass','description', 'gems','extendedName','i18n']
@heroes.comparator = 'gems'
@listenToOnce @heroes, 'sync', @onHeroesLoaded
@supermodel.loadCollection(@heroes, 'heroes')
getRenderData: ->
c = super()
c.hasSubscription = me.get('stripe')?.sponsorID
c.heroes = @heroes.models
c.payButtonText = @payButtonText
c.saleEndDate = @saleEndDate
c.state = @state
c.stateMessage = @stateMessage
c
onHeroesLoaded: ->
@formatHero hero for hero in @heroes.models
formatHero: (hero) ->
hero.name = utils.i18n hero.attributes, 'extendedName'
hero.name ?= utils.i18n hero.attributes, 'name'
hero.description = utils.i18n hero.attributes, 'description'
hero.class = hero.get('heroClass') or 'Warrior'
onPayButton: ->
return @openModalView new AuthModal() if me.isAnonymous()
@state = undefined
@stateMessage = undefined
@render()
@ -53,10 +77,8 @@ module.exports = class SubscriptionSaleView extends RootView
jqxhr = $.post('/db/subscription/-/year_sale', data)
jqxhr.done (data, textStatus, jqXHR) =>
application.tracker?.trackEvent 'Finished sale landing page subscription purchase', value: @yearSaleAmount
me.set 'stripe', data?.stripe if data?.stripe?
@state = 'invoice_paid'
@stateMessage = undefined
@render?()
me.fetch(cache: false).always =>
app.router.navigate '/play', trigger: true
jqxhr.fail (xhr, textStatus, errorThrown) =>
console.error 'We got an error subscribing with Stripe from our server:', textStatus, errorThrown
application.tracker?.trackEvent 'Failed to finish 1 year subscription purchase', status: textStatus

View file

@ -0,0 +1,126 @@
// Compare customer polls to user polls
// TODO: Only looks at subscribers currently, but it should look at other payments as well.
// Usage:
// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
var scriptStartTime = new Date();
try {
var polls = getPolls();
var pollRecords = getPollRecords();
var users = getUsers(Object.keys(pollRecords));
print("Crunching the data...");
// answerCounts format {<pollID>: {name: <name>, answers: {<answer key>: {customer: <count>, user: <count>}}, totals: {customer: <count>, user: <count>}}
var answerCounts = {};
for (var userID in pollRecords) {
for (var pollID in pollRecords[userID].polls) {
var answer = pollRecords[userID].polls[pollID];
if (!answerCounts[pollID]) {
answerCounts[pollID] = {
name: polls[pollID].name,
answers: {},
totals: {customer: 0, user: 0}
};
}
if (!answerCounts[pollID].answers[answer]) answerCounts[pollID].answers[answer] = {customer: 0, user: 0};
if (isCustomer(users[userID])) {
answerCounts[pollID].answers[answer].customer++;
answerCounts[pollID].totals.customer++;
}
else {
answerCounts[pollID].answers[answer].user++;
answerCounts[pollID].totals.user++;
}
}
}
for (var pollID in answerCounts) {
var pollName = answerCounts[pollID].name;
print(pollName);
var customerTotal = answerCounts[pollID].totals.customer;
var userTotal = answerCounts[pollID].totals.user;
for (var answer in answerCounts[pollID].answers) {
var customerCount = answerCounts[pollID].answers[answer].customer;
var customerPercentage = parseFloat(customerCount) / customerTotal;
// customerPercentage = (customerPercentage * 100).toFixed(2);
var userCount = answerCounts[pollID].answers[answer].user;
var userPercentage = parseFloat(userCount) / userTotal;
// userPercentage = (userPercentage * 100).toFixed(2);
print(answer + "\t" + customerCount + "\t" + customerTotal + "\t" + customerPercentage + "\t" + userCount + "\t" + userTotal + "\t" + userPercentage);
}
}
}
catch(err) {
log("ERROR: " + err);
printjson(err);
}
finally {
log("Script runtime: " + (new Date() - scriptStartTime));
}
function getPolls()
{
print("Fetching polls...");
var polls = {};
var cursor = db.polls.find({}, {name: 1});
while (cursor.hasNext()) {
var doc = cursor.next();
polls[doc._id.valueOf()] = doc;
}
return polls;
}
function getPollRecords()
{
print("Fetching poll records...");
var pollRecords = {};
var cursor = db['user.polls.records'].find({}, {polls: 1, user: 1});
while (cursor.hasNext()) {
var doc = cursor.next();
pollRecords[doc.user] = doc;
}
return pollRecords;
}
function getUsers(userIDs)
{
print("Fetching users...");
var userObjectIds = [];
for (var i = 0; i < userIDs.length; i++) {
userObjectIds.push(ObjectId(userIDs[i]));
}
var users = {};
var cursor = db.users.find({$and: [{_id: {$in: userObjectIds}}, {stripe: {$exists: true}}]}, {stripe: 1});
while (cursor.hasNext()) {
var doc = cursor.next();
users[doc._id.valueOf()] = doc;
}
return users;
}
// *** Helper functions ***
function log(str) {
print(new Date().toISOString() + " " + str);
}
function objectIdWithTimestamp(timestamp) {
// Convert string date to Date object (otherwise assume timestamp is a date)
if (typeof(timestamp) == 'string') timestamp = new Date(timestamp);
// Convert date object to hex seconds since Unix epoch
var hexSeconds = Math.floor(timestamp/1000).toString(16);
// Create an ObjectId with that hex timestamp
var constructedObjectId = ObjectId(hexSeconds + "0000000000000000");
return constructedObjectId
}
function isCustomer(user) {
if (!user) return false;
var stripe = user.stripe;
if (!stripe) return false;
if (stripe.sponsorID || stripe.subscriptionID || stripe.free === true) return true;
if (typeof stripe.free === 'string' && new Date() < new Date(stripe.free)) return true;
return false;
}

View file

@ -307,6 +307,7 @@ PaymentHandler = class PaymentHandler extends Handler
if err
@logPaymentError(req, 'Stripe incr db error. '+err)
return @sendDatabaseError(res, err)
@sendPaymentHipChatMessage user: req.user, payment: payment
@sendCreated(res, @formatEntity(req, payment))
)
)

View file

@ -7,6 +7,7 @@ mongoose = require 'mongoose'
async = require 'async'
config = require '../../server_config'
Handler = require '../commons/Handler'
hipchat = require '../hipchat'
discountHandler = require './discount_handler'
Prepaid = require '../prepaids/Prepaid'
User = require '../users/User'
@ -118,48 +119,78 @@ class SubscriptionHandler extends Handler
purchaseYearSale: (req, res) ->
return @sendForbiddenError(res) unless req.user?
return @sendForbiddenError(res) if req.user?.hasSubscription()
return @sendForbiddenError(res) if req.user?.get('stripe')?.sponsorID
cancelSubscriptionImmediately = (user, subscription, done) =>
return done() unless user and subscription
stripe.customers.cancelSubscription subscription.customer, subscription.id, (err) =>
return done(err) if err
stripeInfo = _.cloneDeep(user.get('stripe') ? {})
delete stripeInfo.planID
delete stripeInfo.prepaidCode
delete stripeInfo.subscriptionID
user.set('stripe', stripeInfo)
user.save (err) =>
return done(err) if err
done()
StripeUtils.getCustomer req.user, req.body.stripe?.token, (err, customer) =>
if err
@logSubscriptionError(req.user, "Purchase year sale get customer: #{JSON.stringify(err)}")
return @sendDatabaseError(res, err)
metadata =
type: req.body.type
userID: req.user._id + ''
gems: subscriptions.basic.gems * 12
timestamp: parseInt(req.body.stripe?.timestamp)
description: req.body.description
StripeUtils.createCharge req.user, subscriptions.year_sale.amount, metadata, (err, charge) =>
if err
@logSubscriptionError(req.user, "Purchase year sale create charge: #{JSON.stringify(err)}")
return @sendDatabaseError(res, err)
findStripeSubscription customer.id, subscriptionID: req.user.get('stripe')?.subscriptionID, (subscription) =>
stripeSubscriptionPeriodEndDate = new Date(subscription.current_period_end * 1000) if subscription
StripeUtils.createPayment req.user, charge, (err, payment) =>
cancelSubscriptionImmediately req.user, subscription, (err) =>
if err
@logSubscriptionError(req.user, "Purchase year sale create payment: #{JSON.stringify(err)}")
@logSubscriptionError(user, "Purchase year sale Stripe cancel subscription error: #{JSON.stringify(err)}")
return @sendDatabaseError(res, err)
metadata =
type: req.body.type
userID: req.user._id + ''
gems: subscriptions.basic.gems * 12
timestamp: parseInt(req.body.stripe?.timestamp)
description: req.body.description
# Add terminal subscription to User
endDate = new Date()
endDate.setUTCFullYear(endDate.getUTCFullYear() + 1)
stripeInfo = _.cloneDeep(req.user.get('stripe') ? {})
stripeInfo.free = endDate.toISOString().substring(0, 10)
req.user.set('stripe', stripeInfo)
# Add year's worth of gems to User
purchased = _.clone(req.user.get('purchased'))
purchased ?= {}
purchased.gems ?= 0
purchased.gems += parseInt(charge.metadata.gems)
req.user.set('purchased', purchased)
req.user.save (err, user) =>
StripeUtils.createCharge req.user, subscriptions.year_sale.amount, metadata, (err, charge) =>
if err
@logSubscriptionError(req.user, "User save error: #{JSON.stringify(err)}")
@logSubscriptionError(req.user, "Purchase year sale create charge: #{JSON.stringify(err)}")
return @sendDatabaseError(res, err)
@sendSuccess(res, user)
StripeUtils.createPayment req.user, charge, (err, payment) =>
if err
@logSubscriptionError(req.user, "Purchase year sale create payment: #{JSON.stringify(err)}")
return @sendDatabaseError(res, err)
# Add terminal subscription to User with extensions for existing subscriptions
stripeInfo = _.cloneDeep(req.user.get('stripe') ? {})
endDate = new Date()
if stripeSubscriptionPeriodEndDate
endDate = stripeSubscriptionPeriodEndDate
else if _.isString(stripeInfo.free) and new Date() < new Date(stripeInfo.free)
endDate = new Date(stripeInfo.free)
endDate.setUTCFullYear(endDate.getUTCFullYear() + 1)
stripeInfo.free = endDate.toISOString().substring(0, 10)
req.user.set('stripe', stripeInfo)
# Add year's worth of gems to User
purchased = _.clone(req.user.get('purchased'))
purchased ?= {}
purchased.gems ?= 0
purchased.gems += parseInt(charge.metadata.gems)
req.user.set('purchased', purchased)
req.user.save (err, user) =>
if err
@logSubscriptionError(req.user, "User save error: #{JSON.stringify(err)}")
return @sendDatabaseError(res, err)
try
msg = "Year subscription purchased by #{req.user.get('email')} #{req.user.id}"
hipchat.sendHipChatMessage msg, ['tower']
catch error
@logSubscriptionError(req.user, "Year sub sale HipChat tower msg error: #{JSON.stringify(error)}")
@sendSuccess(res, user)
subscribeUser: (req, user, done) ->
if (not req.user) or req.user.isAnonymous() or user.isAnonymous()

View file

@ -1400,3 +1400,160 @@ describe 'Subscriptions', ->
expect(payment).toBeDefined()
expect(payment.get('gems')).toEqual(3500*12)
done()
it 'year_sale when stripe.free === true', (done) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user1) ->
user1.set('stripe', {free: true})
user1.save (err, user1) ->
expect(err).toBeNull()
expect(user1.get('stripe')?.free).toEqual(true)
requestBody =
stripe:
token: token.id
timestamp: new Date()
request.put {uri: "#{subscriptionURL}/-/year_sale", json: requestBody, headers: headers }, (err, res) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
User.findById user1.id, (err, user1) ->
expect(err).toBeNull()
stripeInfo = user1.get('stripe')
expect(stripeInfo).toBeDefined()
return done() unless stripeInfo
endDate = new Date()
endDate.setUTCFullYear(endDate.getUTCFullYear() + 1)
expect(stripeInfo.free).toEqual(endDate.toISOString().substring(0, 10))
expect(stripeInfo.customerID).toBeDefined()
expect(user1.get('purchased')?.gems).toEqual(3500*12)
Payment.findOne 'stripe.customerID': stripeInfo.customerID, (err, payment) ->
expect(err).toBeNull()
expect(payment).toBeDefined()
expect(payment.get('gems')).toEqual(3500*12)
done()
it 'year_sale when stripe.free < today', (done) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user1) ->
endDate = new Date()
endDate.setUTCFullYear(endDate.getUTCFullYear() - 1)
user1.set('stripe', {free: endDate.toISOString().substring(0, 10)})
user1.save (err, user1) ->
expect(err).toBeNull()
expect(user1.get('stripe')?.free).toEqual(endDate.toISOString().substring(0, 10))
requestBody =
stripe:
token: token.id
timestamp: new Date()
request.put {uri: "#{subscriptionURL}/-/year_sale", json: requestBody, headers: headers }, (err, res) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
User.findById user1.id, (err, user1) ->
expect(err).toBeNull()
stripeInfo = user1.get('stripe')
expect(stripeInfo).toBeDefined()
return done() unless stripeInfo
endDate = new Date()
endDate.setUTCFullYear(endDate.getUTCFullYear() + 1)
expect(stripeInfo.free).toEqual(endDate.toISOString().substring(0, 10))
expect(stripeInfo.customerID).toBeDefined()
expect(user1.get('purchased')?.gems).toEqual(3500*12)
Payment.findOne 'stripe.customerID': stripeInfo.customerID, (err, payment) ->
expect(err).toBeNull()
expect(payment).toBeDefined()
expect(payment.get('gems')).toEqual(3500*12)
done()
it 'year_sale when stripe.free > today', (done) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user1) ->
endDate = new Date()
endDate.setUTCDate(endDate.getUTCDate() + 5)
user1.set('stripe', {free: endDate.toISOString().substring(0, 10)})
user1.save (err, user1) ->
expect(err).toBeNull()
expect(user1.get('stripe')?.free).toEqual(endDate.toISOString().substring(0, 10))
requestBody =
stripe:
token: token.id
timestamp: new Date()
request.put {uri: "#{subscriptionURL}/-/year_sale", json: requestBody, headers: headers }, (err, res) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
User.findById user1.id, (err, user1) ->
expect(err).toBeNull()
stripeInfo = user1.get('stripe')
expect(stripeInfo).toBeDefined()
return done() unless stripeInfo
endDate = new Date()
endDate.setUTCFullYear(endDate.getUTCFullYear() + 1)
endDate.setUTCDate(endDate.getUTCDate() + 5)
expect(stripeInfo.free).toEqual(endDate.toISOString().substring(0, 10))
expect(stripeInfo.customerID).toBeDefined()
expect(user1.get('purchased')?.gems).toEqual(3500*12)
Payment.findOne 'stripe.customerID': stripeInfo.customerID, (err, payment) ->
expect(err).toBeNull()
expect(payment).toBeDefined()
expect(payment.get('gems')).toEqual(3500*12)
done()
it 'year_sale with monthly sub', (done) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user1) ->
subscribeUser user1, token, null, ->
User.findById user1.id, (err, user1) ->
expect(err).toBeNull()
stripeInfo = user1.get('stripe')
stripe.customers.retrieveSubscription stripeInfo.customerID, stripeInfo.subscriptionID, (err, subscription) ->
expect(err).toBeNull()
expect(subscription).not.toBeNull()
stripeSubscriptionPeriodEndDate = new Date(subscription.current_period_end * 1000)
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
requestBody =
stripe:
token: token.id
timestamp: new Date()
request.put {uri: "#{subscriptionURL}/-/year_sale", json: requestBody, headers: headers }, (err, res) ->
expect(err).toBeNull()
expect(res.statusCode).toBe(200)
User.findById user1.id, (err, user1) ->
expect(err).toBeNull()
stripeInfo = user1.get('stripe')
expect(stripeInfo).toBeDefined()
return done() unless stripeInfo
endDate = stripeSubscriptionPeriodEndDate
endDate.setUTCFullYear(endDate.getUTCFullYear() + 1)
expect(stripeInfo.free).toEqual(endDate.toISOString().substring(0, 10))
expect(stripeInfo.customerID).toBeDefined()
expect(user1.get('purchased')?.gems).toEqual(3500+3500*12)
Payment.findOne 'stripe.customerID': stripeInfo.customerID, (err, payment) ->
expect(err).toBeNull()
expect(payment).toBeDefined()
expect(payment.get('gems')).toEqual(3500*12)
done()
it 'year_sale with sponsored sub', (done) ->
stripe.tokens.create {
card: { number: '4242424242424242', exp_month: 12, exp_year: 2020, cvc: '123' }
}, (err, token) ->
loginNewUser (user1) ->
user1.set('stripe', {sponsorID: 'dummyID'})
user1.save (err, user1) ->
expect(err).toBeNull()
requestBody =
stripe:
token: token.id
timestamp: new Date()
request.put {uri: "#{subscriptionURL}/-/year_sale", json: requestBody, headers: headers }, (err, res) ->
console.log err
expect(err).toBeNull()
done()