diff --git a/test/api/unit/libs/cron.test.js b/test/api/unit/libs/cron.test.js index eb15119ee1..2b177b6f2e 100644 --- a/test/api/unit/libs/cron.test.js +++ b/test/api/unit/libs/cron.test.js @@ -231,13 +231,16 @@ describe('cron', async () => { }, }); // user1 has a 1-month recurring subscription starting today - user1.purchased.plan.customerId = 'subscribedId'; - user1.purchased.plan.dateUpdated = moment().toDate(); - user1.purchased.plan.planId = 'basic'; - user1.purchased.plan.consecutive.count = 0; - user1.purchased.plan.consecutive.offset = 0; - user1.purchased.plan.consecutive.trinkets = 0; - user1.purchased.plan.consecutive.gemCapExtra = 0; + beforeEach(async () => { + user1.purchased.plan.customerId = 'subscribedId'; + user1.purchased.plan.dateUpdated = moment().toDate(); + user1.purchased.plan.planId = 'basic'; + user1.purchased.plan.consecutive.count = 0; + user1.purchased.plan.perkMonthCount = 0; + user1.purchased.plan.consecutive.offset = 0; + user1.purchased.plan.consecutive.trinkets = 0; + user1.purchased.plan.consecutive.gemCapExtra = 0; + }); it('does not increment consecutive benefits after the first month', async () => { clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(1, 'months') @@ -271,6 +274,24 @@ describe('cron', async () => { expect(user1.purchased.plan.consecutive.gemCapExtra).to.equal(0); }); + it('increments consecutive benefits after the second month if they also received a 1 month gift subscription', async () => { + user1.purchased.plan.perkMonthCount = 1; + clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(2, 'months') + .add(2, 'days') + .toDate()); + // Add 1 month to simulate what happens a month after the subscription was created. + // Add 2 days so that we're sure we're not affected by any start-of-month effects + // e.g., from time zone oddness. + await cron({ + user: user1, tasksByType, daysMissed, analytics, + }); + expect(user1.purchased.plan.perkMonthCount).to.equal(0); + expect(user1.purchased.plan.consecutive.count).to.equal(2); + expect(user1.purchased.plan.consecutive.offset).to.equal(0); + expect(user1.purchased.plan.consecutive.trinkets).to.equal(1); + expect(user1.purchased.plan.consecutive.gemCapExtra).to.equal(5); + }); + it('increments consecutive benefits after the third month', async () => { clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(3, 'months') .add(2, 'days') @@ -315,6 +336,26 @@ describe('cron', async () => { expect(user1.purchased.plan.consecutive.trinkets).to.equal(3); expect(user1.purchased.plan.consecutive.gemCapExtra).to.equal(15); }); + + it('initialized plan.perkMonthCount if necessary', async () => { + user.purchased.plan.perkMonthCount = undefined; + clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(1, 'months') + .add(2, 'days') + .toDate()); + await cron({ + user, tasksByType, daysMissed, analytics, + }); + expect(user.purchased.plan.perkMonthCount).to.equal(1); + user.purchased.plan.perkMonthCount = undefined; + clock.restore(); + clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(2, 'months') + .add(2, 'days') + .toDate()); + await cron({ + user, tasksByType, daysMissed, analytics, + }); + expect(user.purchased.plan.perkMonthCount).to.equal(2); + }); }); describe('for a 3-month recurring subscription', async () => { @@ -330,13 +371,16 @@ describe('cron', async () => { }, }); // user3 has a 3-month recurring subscription starting today - user3.purchased.plan.customerId = 'subscribedId'; - user3.purchased.plan.dateUpdated = moment().toDate(); - user3.purchased.plan.planId = 'basic_3mo'; - user3.purchased.plan.consecutive.count = 0; - user3.purchased.plan.consecutive.offset = 3; - user3.purchased.plan.consecutive.trinkets = 1; - user3.purchased.plan.consecutive.gemCapExtra = 5; + beforeEach(async () => { + user3.purchased.plan.customerId = 'subscribedId'; + user3.purchased.plan.dateUpdated = moment().toDate(); + user3.purchased.plan.planId = 'basic_3mo'; + user3.purchased.plan.perkMonthCount = 0; + user3.purchased.plan.consecutive.count = 0; + user3.purchased.plan.consecutive.offset = 3; + user3.purchased.plan.consecutive.trinkets = 1; + user3.purchased.plan.consecutive.gemCapExtra = 5; + }); it('does not increment consecutive benefits in the first month of the first paid period that they already have benefits for', async () => { clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(1, 'months') @@ -390,6 +434,17 @@ describe('cron', async () => { expect(user3.purchased.plan.consecutive.gemCapExtra).to.equal(10); }); + it('keeps existing plan.perkMonthCount intact when incrementing consecutive benefits', async () => { + user3.purchased.plan.perkMonthCount = 2 + clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(4, 'months') + .add(2, 'days') + .toDate()); + await cron({ + user: user3, tasksByType, daysMissed, analytics, + }); + expect(user3.purchased.plan.perkMonthCount).to.equal(2); + }); + it('does not increment consecutive benefits in the second month of the second period that they already have benefits for', async () => { clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(5, 'months') .add(2, 'days') @@ -417,6 +472,7 @@ describe('cron', async () => { }); it('increments consecutive benefits the month after the third paid period has started', async () => { + console.log(user3.purchased.plan); clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(7, 'months') .add(2, 'days') .toDate()); @@ -456,13 +512,15 @@ describe('cron', async () => { }, }); // user6 has a 6-month recurring subscription starting today - user6.purchased.plan.customerId = 'subscribedId'; + beforeEach(async () => { + user6.purchased.plan.customerId = 'subscribedId'; user6.purchased.plan.dateUpdated = moment().toDate(); user6.purchased.plan.planId = 'google_6mo'; user6.purchased.plan.consecutive.count = 0; user6.purchased.plan.consecutive.offset = 6; user6.purchased.plan.consecutive.trinkets = 2; user6.purchased.plan.consecutive.gemCapExtra = 10; + }); it('does not increment consecutive benefits in the first month of the first paid period that they already have benefits for', async () => { clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(1, 'months') diff --git a/test/api/unit/libs/payments/payments.test.js b/test/api/unit/libs/payments/payments.test.js index 3ffd1230e4..22728c21a1 100644 --- a/test/api/unit/libs/payments/payments.test.js +++ b/test/api/unit/libs/payments/payments.test.js @@ -13,7 +13,7 @@ import { import * as worldState from '../../../../../website/server/libs/worldState'; import { TransactionModel } from '../../../../../website/server/models/transaction'; -describe.only('payments/index', () => { +describe('payments/index', () => { let user; let group; let data; @@ -270,6 +270,8 @@ describe.only('payments/index', () => { data.gift.subscription.months = 1; expect(recipient.purchased.plan.perkMonthCount).to.eql(2); + expect(recipient.purchased.plan.consecutive.trinkets).to.eql(0); + expect(recipient.purchased.plan.consecutive.gemCapExtra).to.eql(0); await api.createSubscription(data); expect(recipient.purchased.plan.perkMonthCount).to.eql(0); @@ -277,6 +279,21 @@ describe.only('payments/index', () => { expect(recipient.purchased.plan.consecutive.gemCapExtra).to.eql(5); }); + it('awards perks if plan.perkMonthCount goes over 3', async () => { + recipient.purchased.plan = plan; + recipient.purchased.plan.perkMonthCount = 2; + data.sub.key = 'basic_earned'; + + expect(recipient.purchased.plan.perkMonthCount).to.eql(2); + expect(recipient.purchased.plan.consecutive.trinkets).to.eql(0); + expect(recipient.purchased.plan.consecutive.gemCapExtra).to.eql(0); + await api.createSubscription(data); + + expect(recipient.purchased.plan.perkMonthCount).to.eql(2); + expect(recipient.purchased.plan.consecutive.trinkets).to.eql(1); + expect(recipient.purchased.plan.consecutive.gemCapExtra).to.eql(5); + }); + it('sets plan.customerId to "Gift" if it does not already exist', async () => { expect(recipient.purchased.plan.customerId).to.not.exist; @@ -443,6 +460,7 @@ describe.only('payments/index', () => { expect(user.purchased.plan.customerId).to.eql('customer-id'); expect(user.purchased.plan.dateUpdated).to.exist; expect(user.purchased.plan.gemsBought).to.eql(0); + expect(user.purchased.plan.perkMonthCount).to.eql(0); expect(user.purchased.plan.paymentMethod).to.eql('Payment Method'); expect(user.purchased.plan.extraMonths).to.eql(0); expect(user.purchased.plan.dateTerminated).to.eql(null); diff --git a/website/server/libs/payments/subscriptions.js b/website/server/libs/payments/subscriptions.js index f9a160326c..859cd1c76e 100644 --- a/website/server/libs/payments/subscriptions.js +++ b/website/server/libs/payments/subscriptions.js @@ -258,7 +258,6 @@ async function createSubscription (data) { if (!data.gift && !groupId) { plan.consecutive.offset = months; } - console.log("giving benes"); await plan.incrementPerkCounterAndReward(recipient._id, months); } diff --git a/website/server/models/subscriptionPlan.js b/website/server/models/subscriptionPlan.js index db4c39725b..a4f6b7ec81 100644 --- a/website/server/models/subscriptionPlan.js +++ b/website/server/models/subscriptionPlan.js @@ -53,11 +53,17 @@ schema.plugin(baseModel, { schema.methods.incrementPerkCounterAndReward = async function incrementPerkCounterAndReward (userID, adding) { // if perkMonthCount wasn't used before, initialize it. - if (!this.perkMonthCount) this.perkMonthCount = this.consecutive.count % SUBSCRIPTION_BASIC_BLOCK_LENGTH; - this.perkMonthCount += adding; + if (this.perkMonthCount == undefined && adding == 1) { + this.perkMonthCount = (this.consecutive.count-1) % SUBSCRIPTION_BASIC_BLOCK_LENGTH; + console.log(`initializing perk count with ${this.perkMonthCount}`); + } else { + this.perkMonthCount += adding; + } + console.log(this.perkMonthCount); const perks = Math.floor(this.perkMonthCount / 3); if (perks > 0) { + console.log(`giving benefits for ${perks} from ${this.perkMonthCount}, ${adding}`); this.consecutive.gemCapExtra += 5 * perks; // 5 extra Gems every 3 months // cap it at 50 (hard 25 limit + extra 25) if (this.consecutive.gemCapExtra > 25) this.consecutive.gemCapExtra = 25;