From 5a83f93ade5eddb037ca3e5bff45120559c86a4b Mon Sep 17 00:00:00 2001 From: Jawad Jahangir Date: Thu, 15 Aug 2019 21:06:56 +0600 Subject: [PATCH] Free group plan subscription from a party/guild no longer gets cancelled after leaving a guild - fixes #11055 (#11228) * bug fix: free group plan subscription from party/guild is no longer cancelled when leaving a guild * free group plan subscription from party/guild no longer gets cancelled when leaving a guild * bug fix: free group plan subscription from party/guild is no longer cancelled when leaving a guild * free group plan subscription from party/guild no longer gets cancelled when leaving a guild * Added tests to check if a member of a group plan maintains free subscription when leaving another group without a plan * Added tests to check if member of a group plan still keeps free subscription when leaving some other group without a plan * bug fix: free group plan subscription from party/guild is no longer cancelled when leaving a guild * free group plan subscription from party/guild no longer gets cancelled when leaving a guild * bug fix: free group plan subscription from party/guild is no longer cancelled when leaving a guild * free group plan subscription from party/guild no longer gets cancelled when leaving a guild * Added tests to check if a member of a group plan maintains free subscription when leaving another group without a plan * Added tests to check if member of a group plan still keeps free subscription when leaving some other group without a plan --- .../groups/POST-groups_groupId_leave.js | 94 ++++++++++++------- website/server/controllers/api-v3/groups.js | 2 +- website/server/libs/payments/groupPayments.js | 6 +- website/server/models/user/methods.js | 2 +- 4 files changed, 65 insertions(+), 39 deletions(-) diff --git a/test/api/v3/integration/groups/POST-groups_groupId_leave.js b/test/api/v3/integration/groups/POST-groups_groupId_leave.js index eab4442224..65d76f4714 100644 --- a/test/api/v3/integration/groups/POST-groups_groupId_leave.js +++ b/test/api/v3/integration/groups/POST-groups_groupId_leave.js @@ -276,44 +276,70 @@ describe('POST /groups/:groupId/leave', () => { }); }); - context('Leaving a group plan', () => { - it('cancels the free subscription', async () => { - // Create group - let { group, groupLeader, members } = await createAndPopulateGroup({ - groupDetails: { - name: 'Test Private Guild', - type: 'guild', - }, - members: 1, + each(typesOfGroups, (groupDetails, groupType) => { + context(`Leaving a group plan when the group is a ${groupType}`, () => { + let groupWithPlan; + let leader; + let member; + + beforeEach(async () => { + let { group, groupLeader, members } = await createAndPopulateGroup({ + groupDetails, + members: 1, + }); + leader = groupLeader; + member = members[0]; + groupWithPlan = group; + let userWithFreePlan = await User.findById(leader._id).exec(); + + // Create subscription + let paymentData = { + user: userWithFreePlan, + groupId: groupWithPlan._id, + sub: { + key: 'basic_3mo', + }, + customerId: 'customer-id', + paymentMethod: 'Payment Method', + headers: { + 'x-client': 'habitica-web', + 'user-agent': '', + }, + }; + await payments.createSubscription(paymentData); + await member.sync(); }); - let leader = groupLeader; - let member = members[0]; - let userWithFreePlan = await User.findById(leader._id).exec(); + it('cancels the free subscription', async () => { + expect(member.purchased.plan.planId).to.equal('group_plan_auto'); + expect(member.purchased.plan.dateTerminated).to.not.exist; - // Create subscription - let paymentData = { - user: userWithFreePlan, - groupId: group._id, - sub: { - key: 'basic_3mo', - }, - customerId: 'customer-id', - paymentMethod: 'Payment Method', - headers: { - 'x-client': 'habitica-web', - 'user-agent': '', - }, - }; - await payments.createSubscription(paymentData); - await member.sync(); - expect(member.purchased.plan.planId).to.equal('group_plan_auto'); - expect(member.purchased.plan.dateTerminated).to.not.exist; + // Leave + await member.post(`/groups/${groupWithPlan._id}/leave`); + await member.sync(); + expect(member.purchased.plan.dateTerminated).to.exist; + }); - // Leave - await member.post(`/groups/${group._id}/leave`); - await member.sync(); - expect(member.purchased.plan.dateTerminated).to.exist; + it('preserves the free subscription when leaving a any other group without a plan', async () => { + // Joining a guild without a group plan + let { group: groupWithNoPlan } = await createAndPopulateGroup({ + groupDetails: { + name: 'Group Without Plan', + type: 'guild', + privacy: 'public', + }, + }); + + await member.post(`/groups/${groupWithNoPlan._id}/join`); + await member.sync(); + expect(member.purchased.plan.planId).to.equal('group_plan_auto'); + expect(member.purchased.plan.dateTerminated).to.not.exist; + + // Leaving the guild without a group plan + await member.post(`/groups/${groupWithNoPlan._id}/leave`); + await member.sync(); + expect(member.purchased.plan.dateTerminated).to.not.exist; + }); }); }); }); diff --git a/website/server/controllers/api-v3/groups.js b/website/server/controllers/api-v3/groups.js index e214bda27b..41e1884ae5 100644 --- a/website/server/controllers/api-v3/groups.js +++ b/website/server/controllers/api-v3/groups.js @@ -776,7 +776,7 @@ api.leaveGroup = { if (group.type !== 'party') { let guildIndex = user.guilds.indexOf(group._id); - user.guilds.splice(guildIndex, 1); + if (guildIndex >= 0) user.guilds.splice(guildIndex, 1); } let isMemberOfGroupPlan = await user.isMemberOfGroupPlan(); diff --git a/website/server/libs/payments/groupPayments.js b/website/server/libs/payments/groupPayments.js index 5da9309f1f..ff4c9abf97 100644 --- a/website/server/libs/payments/groupPayments.js +++ b/website/server/libs/payments/groupPayments.js @@ -211,13 +211,13 @@ async function cancelGroupSubscriptionForUser (user, group, userWasRemoved = fal if (user.party._id) userGroups.push(user.party._id); let index = userGroups.indexOf(group._id); - userGroups.splice(index, 1); + if (index >= 0) userGroups.splice(index, 1); let groupPlansQuery = { - type: {$in: ['guild', 'party']}, + // type: { $in: ['guild', 'party'] }, // privacy: 'private', _id: {$in: userGroups}, - 'purchased.plan.dateTerminated': null, + 'purchased.plan.dateTerminated': { $type: 'null' }, }; let groupFields = `${basicGroupFields} purchased`; diff --git a/website/server/models/user/methods.js b/website/server/models/user/methods.js index 2be8135fa1..5a49fea5a0 100644 --- a/website/server/models/user/methods.js +++ b/website/server/models/user/methods.js @@ -392,7 +392,7 @@ schema.methods.canGetGems = async function canObtainGems () { schema.methods.isMemberOfGroupPlan = async function isMemberOfGroupPlan () { const groups = await getUserGroupData(this); - return groups.every(g => { + return groups.some(g => { return g.isSubscribed(); }); };