Merge branch 'bugfix-extramonths-lost-when-subscription-terminated' of https://github.com/hamboomger/habitica into hamboomger-bugfix-extramonths-lost-when-subscription-terminated

This commit is contained in:
Matteo Pagliazzi
2020-04-20 23:30:19 +02:00
11 changed files with 193 additions and 38 deletions

View File

@@ -0,0 +1,64 @@
import moment from 'moment';
import { calculateSubscriptionTerminationDate } from '../../../../../../website/server/libs/payments/util';
import api from '../../../../../../website/server/libs/payments/payments';
describe('#calculateSubscriptionTerminationDate', () => {
let plan;
let nextBill;
beforeEach(() => {
plan = {
customerId: 'customer-id',
extraMonths: 0,
};
nextBill = moment();
});
it('should extend date to the exact amount of days left before the next bill will occur', () => {
nextBill = moment()
.add(5, 'days');
const expectedTerminationDate = moment()
.add(5, 'days');
const terminationDate = calculateSubscriptionTerminationDate(nextBill, plan, api.constants);
expect(expectedTerminationDate.diff(terminationDate, 'days')).to.eql(0);
});
it('if nextBill is null, add 30 days to termination date', () => {
nextBill = null;
const expectedTerminationDate = moment()
.add(30, 'days');
const terminationDate = calculateSubscriptionTerminationDate(nextBill, plan, api.constants);
expect(expectedTerminationDate.diff(terminationDate, 'days')).to.eql(0);
});
it('if nextBill is null and it\'s a group plan, add 2 days instead of 30', () => {
nextBill = null;
plan.customerId = api.constants.GROUP_PLAN_CUSTOMER_ID;
const expectedTerminationDate = moment()
.add(2, 'days');
const terminationDate = calculateSubscriptionTerminationDate(nextBill, plan, api.constants);
expect(expectedTerminationDate.diff(terminationDate, 'days')).to.eql(0);
});
it('should add 30.5 days for each extraMonth', () => {
plan.extraMonths = 4;
const expectedTerminationDate = moment()
.add(30.5 * 4, 'days');
const terminationDate = calculateSubscriptionTerminationDate(nextBill, plan, api.constants);
expect(expectedTerminationDate.diff(terminationDate, 'days')).to.eql(0);
});
it('should round up if total days gained by extraMonth is a decimal number', () => {
plan.extraMonths = 5;
const expectedTerminationDate = moment()
.add(Math.ceil(30.5 * 5), 'days');
const terminationDate = calculateSubscriptionTerminationDate(nextBill, plan, api.constants);
expect(expectedTerminationDate.diff(terminationDate, 'days')).to.eql(0);
});
it('behaves like extraMonths is 0 if it\'s set to a negative number', () => {
plan.extraMonths = -5;
const expectedTerminationDate = moment();
const terminationDate = calculateSubscriptionTerminationDate(nextBill, plan, api.constants);
expect(expectedTerminationDate.diff(terminationDate, 'days')).to.eql(0);
});
});

View File

@@ -2402,29 +2402,29 @@ describe('Group Model', () => {
});
});
context('isSubscribed', () => {
context('hasActiveGroupPlan', () => {
it('returns false if group does not have customer id', () => {
expect(party.isSubscribed()).to.be.undefined;
expect(party.hasActiveGroupPlan()).to.be.undefined;
});
it('returns true if group does not have plan.dateTerminated', () => {
party.purchased.plan.customerId = 'test-id';
expect(party.isSubscribed()).to.be.true;
expect(party.hasActiveGroupPlan()).to.be.true;
});
it('returns true if group if plan.dateTerminated is after today', () => {
party.purchased.plan.customerId = 'test-id';
party.purchased.plan.dateTerminated = moment().add(1, 'days').toDate();
expect(party.isSubscribed()).to.be.true;
expect(party.hasActiveGroupPlan()).to.be.true;
});
it('returns false if group if plan.dateTerminated is before today', () => {
party.purchased.plan.customerId = 'test-id';
party.purchased.plan.dateTerminated = moment().subtract(1, 'days').toDate();
expect(party.isSubscribed()).to.be.false;
expect(party.hasActiveGroupPlan()).to.be.false;
});
});

View File

@@ -2,6 +2,7 @@ import { v4 as generateUUID } from 'uuid';
import {
each,
} from 'lodash';
import moment from 'moment';
import {
generateChallenge,
checkExistence,
@@ -12,6 +13,7 @@ import {
} from '../../../../helpers/api-integration/v3';
import { model as User } from '../../../../../website/server/models/user';
import payments from '../../../../../website/server/libs/payments/payments';
import { calculateSubscriptionTerminationDate } from '../../../../../website/server/libs/payments/util';
describe('POST /groups/:groupId/leave', () => {
const typesOfGroups = {
@@ -338,4 +340,48 @@ describe('POST /groups/:groupId/leave', () => {
});
});
});
each(typesOfGroups, (groupDetails, groupType) => {
context(`Leaving a group with extraMonths left plan when the group is a ${groupType}`, () => {
const extraMonths = 12;
let groupWithPlan;
let member;
beforeEach(async () => {
const { group, members } = await createAndPopulateGroup({
groupDetails,
members: 1,
upgradeToGroupPlan: true,
});
[member] = members;
groupWithPlan = group;
await member.update({
'purchased.plan.extraMonths': extraMonths,
});
});
it('calculates dateTerminated and sets extraMonths to zero after user leaves the group', async () => {
const userBeforeLeave = await User.findById(member._id).exec();
await member.post(`/groups/${groupWithPlan._id}/leave`);
const userAfterLeave = await User.findById(member._id).exec();
const dateTerminatedBefore = userBeforeLeave.purchased.plan.dateTerminated;
const extraMonthsBefore = userBeforeLeave.purchased.plan.extraMonths;
const dateTerminatedAfter = userAfterLeave.purchased.plan.dateTerminated;
const extraMonthsAfter = userAfterLeave.purchased.plan.extraMonths;
const expectedTerminationDate = calculateSubscriptionTerminationDate(null, {
customerId: payments.constants.GROUP_PLAN_CUSTOMER_ID,
extraMonths,
}, payments.constants);
expect(extraMonthsBefore).to.gte(12);
expect(extraMonthsAfter).to.equal(0);
expect(dateTerminatedBefore).to.be.null;
expect(dateTerminatedAfter).to.exist;
expect(moment(dateTerminatedAfter).diff(expectedTerminationDate, 'days')).to.equal(0);
});
});
});
});