diff --git a/test/api/v3/integration/groups/POST-group_remove_manager.test.js b/test/api/v3/integration/groups/POST-group_remove_manager.test.js index 6c5d4cee9f..894a225d26 100644 --- a/test/api/v3/integration/groups/POST-group_remove_manager.test.js +++ b/test/api/v3/integration/groups/POST-group_remove_manager.test.js @@ -7,7 +7,7 @@ import { describe('POST /group/:groupId/remove-manager', () => { let leader; let nonLeader; let groupToUpdate; - const groupName = 'Test Public Guild'; + const groupName = 'Test Private Guild'; const groupType = 'guild'; let nonManager; @@ -20,9 +20,10 @@ describe('POST /group/:groupId/remove-manager', () => { groupDetails: { name: groupName, type: groupType, - privacy: 'public', + privacy: 'private', }, members: 2, + upgradeToGroupPlan: true, }); groupToUpdate = group; @@ -83,7 +84,7 @@ describe('POST /group/:groupId/remove-manager', () => { await nonLeader.sync(); - expect(nonLeader.notifications.length).to.equal(0); + expect(nonLeader.notifications.length).to.equal(1); // user gets mystery items expect(updatedGroup.managers[nonLeader._id]).to.not.exist; }); }); diff --git a/test/api/v3/integration/tasks/GET-tasks_id.test.js b/test/api/v3/integration/tasks/GET-tasks_id.test.js index 2e9353a9a3..396ab433bb 100644 --- a/test/api/v3/integration/tasks/GET-tasks_id.test.js +++ b/test/api/v3/integration/tasks/GET-tasks_id.test.js @@ -134,6 +134,7 @@ describe('GET /tasks/:id', () => { type: 'guild', }, members: 1, + upgradeToGroupPlan: true, }); group = groupData.group; diff --git a/test/api/v3/integration/tasks/POST-tasks_clearCompletedTodos.test.js b/test/api/v3/integration/tasks/POST-tasks_clearCompletedTodos.test.js index f3328fbb64..92fcb6a13c 100644 --- a/test/api/v3/integration/tasks/POST-tasks_clearCompletedTodos.test.js +++ b/test/api/v3/integration/tasks/POST-tasks_clearCompletedTodos.test.js @@ -7,7 +7,11 @@ import { describe('POST /tasks/clearCompletedTodos', () => { it('deletes all completed todos except the ones from a challenge and group', async () => { const user = await generateUser({ balance: 1 }); - const guild = await generateGroup(user); + const guild = await generateGroup( + user, + {}, + { 'purchased.plan.customerId': 'group-unlimited' }, + ); const challenge = await generateChallenge(user, guild); await user.post(`/challenges/${challenge._id}/join`); diff --git a/test/api/v3/integration/tasks/groups/DELETE-group_tasks_id.test.js b/test/api/v3/integration/tasks/groups/DELETE-group_tasks_id.test.js index 45d2d918f8..b6eb29db11 100644 --- a/test/api/v3/integration/tasks/groups/DELETE-group_tasks_id.test.js +++ b/test/api/v3/integration/tasks/groups/DELETE-group_tasks_id.test.js @@ -19,6 +19,7 @@ describe('Groups DELETE /tasks/:id', () => { type: 'guild', }, members: 2, + upgradeToGroupPlan: true, }); guild = group; @@ -77,18 +78,18 @@ describe('Groups DELETE /tasks/:id', () => { await user.sync(); await member2.sync(); - expect(user.notifications.length).to.equal(2); - expect(user.notifications[1].type).to.equal('GROUP_TASK_APPROVAL'); - expect(member2.notifications.length).to.equal(2); - expect(member2.notifications[1].type).to.equal('GROUP_TASK_APPROVAL'); + expect(user.notifications.length).to.equal(3); // mystery items + expect(user.notifications[2].type).to.equal('GROUP_TASK_APPROVAL'); + expect(member2.notifications.length).to.equal(3); + expect(member2.notifications[2].type).to.equal('GROUP_TASK_APPROVAL'); await member2.del(`/tasks/${task._id}`); await user.sync(); await member2.sync(); - expect(user.notifications.length).to.equal(1); - expect(member2.notifications.length).to.equal(1); + expect(user.notifications.length).to.equal(2); + expect(member2.notifications.length).to.equal(2); }); it('deletes task from assigned user', async () => { diff --git a/test/api/v3/integration/tasks/groups/GET-approvals_group_id.test.js b/test/api/v3/integration/tasks/groups/GET-approvals_group_id.test.js index a80b33ed5f..520a322399 100644 --- a/test/api/v3/integration/tasks/groups/GET-approvals_group_id.test.js +++ b/test/api/v3/integration/tasks/groups/GET-approvals_group_id.test.js @@ -18,6 +18,7 @@ describe('GET /approvals/group/:groupId', () => { type: 'guild', }, members: 2, + upgradeToGroupPlan: true, }); guild = group; diff --git a/test/api/v3/integration/tasks/groups/GET-tasks_group_id.test.js b/test/api/v3/integration/tasks/groups/GET-tasks_group_id.test.js index 277d43a9b2..60d05d028d 100644 --- a/test/api/v3/integration/tasks/groups/GET-tasks_group_id.test.js +++ b/test/api/v3/integration/tasks/groups/GET-tasks_group_id.test.js @@ -36,7 +36,7 @@ describe('GET /tasks/group/:groupId', () => { before(async () => { user = await generateUser(); - group = await generateGroup(user); + group = await generateGroup(user, {}, { 'purchased.plan.customerId': 'group-unlimited' }); }); it('returns error when group is not found', async () => { diff --git a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_approve_userId.test.js b/test/api/v3/integration/tasks/groups/POST-group_tasks_id_approve_userId.test.js index 9c3288fa42..60eeaf4053 100644 --- a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_approve_userId.test.js +++ b/test/api/v3/integration/tasks/groups/POST-group_tasks_id_approve_userId.test.js @@ -19,6 +19,7 @@ describe('POST /tasks/:id/approve/:userId', () => { type: 'guild', }, members: 2, + upgradeToGroupPlan: true, }); guild = group; @@ -63,9 +64,9 @@ describe('POST /tasks/:id/approve/:userId', () => { await member.sync(); - expect(member.notifications.length).to.equal(2); - expect(member.notifications[1].type).to.equal('GROUP_TASK_APPROVED'); - expect(member.notifications[1].data.message).to.equal(t('yourTaskHasBeenApproved', { taskText: task.text })); + expect(member.notifications.length).to.equal(3); + expect(member.notifications[2].type).to.equal('GROUP_TASK_APPROVED'); + expect(member.notifications[2].data.message).to.equal(t('yourTaskHasBeenApproved', { taskText: task.text })); memberTasks = await member.get('/tasks/user'); syncedTask = find(memberTasks, findAssignedTask); @@ -89,9 +90,9 @@ describe('POST /tasks/:id/approve/:userId', () => { await member2.post(`/tasks/${task._id}/approve/${member._id}`); await member.sync(); - expect(member.notifications.length).to.equal(2); - expect(member.notifications[1].type).to.equal('GROUP_TASK_APPROVED'); - expect(member.notifications[1].data.message).to.equal(t('yourTaskHasBeenApproved', { taskText: task.text })); + expect(member.notifications.length).to.equal(3); + expect(member.notifications[2].type).to.equal('GROUP_TASK_APPROVED'); + expect(member.notifications[2].data.message).to.equal(t('yourTaskHasBeenApproved', { taskText: task.text })); memberTasks = await member.get('/tasks/user'); syncedTask = find(memberTasks, findAssignedTask); @@ -113,18 +114,18 @@ describe('POST /tasks/:id/approve/:userId', () => { await user.sync(); await member2.sync(); - expect(user.notifications.length).to.equal(2); - expect(user.notifications[1].type).to.equal('GROUP_TASK_APPROVAL'); - expect(member2.notifications.length).to.equal(1); - expect(member2.notifications[0].type).to.equal('GROUP_TASK_APPROVAL'); + expect(user.notifications.length).to.equal(3); + expect(user.notifications[2].type).to.equal('GROUP_TASK_APPROVAL'); + expect(member2.notifications.length).to.equal(2); + expect(member2.notifications[1].type).to.equal('GROUP_TASK_APPROVAL'); await member2.post(`/tasks/${task._id}/approve/${member._id}`); await user.sync(); await member2.sync(); - expect(user.notifications.length).to.equal(1); - expect(member2.notifications.length).to.equal(0); + expect(user.notifications.length).to.equal(2); + expect(member2.notifications.length).to.equal(1); }); it('prevents double approval on a task', async () => { diff --git a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_needs-work_userId.test.js b/test/api/v3/integration/tasks/groups/POST-group_tasks_id_needs-work_userId.test.js index 1299c75a16..72542aceba 100644 --- a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_needs-work_userId.test.js +++ b/test/api/v3/integration/tasks/groups/POST-group_tasks_id_needs-work_userId.test.js @@ -19,6 +19,7 @@ describe('POST /tasks/:id/needs-work/:userId', () => { type: 'guild', }, members: 2, + upgradeToGroupPlan: true, }); guild = group; @@ -72,7 +73,7 @@ describe('POST /tasks/:id/needs-work/:userId', () => { expect(syncedTask.group.approval.requestedDate).to.equal(undefined); // Check that the notification is correct - expect(member.notifications.length).to.equal(initialNotifications + 2); + expect(member.notifications.length).to.equal(initialNotifications + 3); const notification = member.notifications[member.notifications.length - 1]; expect(notification.type).to.equal('GROUP_TASK_NEEDS_WORK'); @@ -121,7 +122,7 @@ describe('POST /tasks/:id/needs-work/:userId', () => { expect(syncedTask.group.approval.requested).to.equal(false); expect(syncedTask.group.approval.requestedDate).to.equal(undefined); - expect(member.notifications.length).to.equal(initialNotifications + 2); + expect(member.notifications.length).to.equal(initialNotifications + 3); const notification = member.notifications[member.notifications.length - 1]; expect(notification.type).to.equal('GROUP_TASK_NEEDS_WORK'); diff --git a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_score_direction.test.js b/test/api/v3/integration/tasks/groups/POST-group_tasks_id_score_direction.test.js index a2ca7f8e42..eaa3cf6484 100644 --- a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_score_direction.test.js +++ b/test/api/v3/integration/tasks/groups/POST-group_tasks_id_score_direction.test.js @@ -19,6 +19,7 @@ describe('POST /tasks/:id/score/:direction', () => { type: 'guild', }, members: 2, + upgradeToGroupPlan: true, }); guild = group; @@ -53,15 +54,15 @@ describe('POST /tasks/:id/score/:direction', () => { await user.sync(); - expect(user.notifications.length).to.equal(2); - expect(user.notifications[1].type).to.equal('GROUP_TASK_APPROVAL'); - expect(user.notifications[1].data.message).to.equal(t('userHasRequestedTaskApproval', { + expect(user.notifications.length).to.equal(3); + expect(user.notifications[2].type).to.equal('GROUP_TASK_APPROVAL'); + expect(user.notifications[2].data.message).to.equal(t('userHasRequestedTaskApproval', { user: member.auth.local.username, taskName: updatedTask.text, taskId: updatedTask._id, direction, }, 'cs')); // This test only works if we have the notification translated - expect(user.notifications[1].data.groupId).to.equal(guild._id); + expect(user.notifications[2].data.groupId).to.equal(guild._id); expect(updatedTask.group.approval.requested).to.equal(true); expect(updatedTask.group.approval.requestedDate).to.be.a('string'); // date gets converted to a string as json doesn't have a Date type @@ -80,25 +81,25 @@ describe('POST /tasks/:id/score/:direction', () => { await user.sync(); await member2.sync(); - expect(user.notifications.length).to.equal(2); - expect(user.notifications[1].type).to.equal('GROUP_TASK_APPROVAL'); - expect(user.notifications[1].data.message).to.equal(t('userHasRequestedTaskApproval', { + expect(user.notifications.length).to.equal(3); + expect(user.notifications[2].type).to.equal('GROUP_TASK_APPROVAL'); + expect(user.notifications[2].data.message).to.equal(t('userHasRequestedTaskApproval', { user: member.auth.local.username, taskName: updatedTask.text, taskId: updatedTask._id, direction, })); - expect(user.notifications[1].data.groupId).to.equal(guild._id); + expect(user.notifications[2].data.groupId).to.equal(guild._id); - expect(member2.notifications.length).to.equal(1); - expect(member2.notifications[0].type).to.equal('GROUP_TASK_APPROVAL'); - expect(member2.notifications[0].data.message).to.equal(t('userHasRequestedTaskApproval', { + expect(member2.notifications.length).to.equal(2); + expect(member2.notifications[1].type).to.equal('GROUP_TASK_APPROVAL'); + expect(member2.notifications[1].data.message).to.equal(t('userHasRequestedTaskApproval', { user: member.auth.local.username, taskName: updatedTask.text, taskId: updatedTask._id, direction, })); - expect(member2.notifications[0].data.groupId).to.equal(guild._id); + expect(member2.notifications[1].data.groupId).to.equal(guild._id); }); it('errors when approval has already been requested', async () => { diff --git a/test/api/v3/integration/tasks/groups/POST-tasks_group_id.test.js b/test/api/v3/integration/tasks/groups/POST-tasks_group_id.test.js index 830852fcf6..1a85a71535 100644 --- a/test/api/v3/integration/tasks/groups/POST-tasks_group_id.test.js +++ b/test/api/v3/integration/tasks/groups/POST-tasks_group_id.test.js @@ -26,6 +26,7 @@ describe('POST /tasks/group/:groupid', () => { privacy: 'private', }, members: 1, + upgradeToGroupPlan: true, }); guild = group; diff --git a/test/api/v3/integration/tasks/groups/POST-tasks_group_id_assign_user_id.test.js b/test/api/v3/integration/tasks/groups/POST-tasks_group_id_assign_user_id.test.js index 044c58018d..71b29a1530 100644 --- a/test/api/v3/integration/tasks/groups/POST-tasks_group_id_assign_user_id.test.js +++ b/test/api/v3/integration/tasks/groups/POST-tasks_group_id_assign_user_id.test.js @@ -21,6 +21,7 @@ describe('POST /tasks/:taskId/assign/:memberId', () => { type: 'guild', }, members: 2, + upgradeToGroupPlan: true, }); guild = group; @@ -103,14 +104,14 @@ describe('POST /tasks/:taskId/assign/:memberId', () => { await member2.sync(); const groupTask = await user.get(`/tasks/group/${guild._id}`); - expect(user.notifications.length).to.equal(2); // includes Guild Joined achievement - expect(user.notifications[1].type).to.equal('GROUP_TASK_CLAIMED'); - expect(user.notifications[1].data.taskId).to.equal(groupTask[0]._id); - expect(user.notifications[1].data.groupId).to.equal(guild._id); - expect(member2.notifications.length).to.equal(1); - expect(member2.notifications[0].type).to.equal('GROUP_TASK_CLAIMED'); - expect(member2.notifications[0].data.taskId).to.equal(groupTask[0]._id); - expect(member2.notifications[0].data.groupId).to.equal(guild._id); + expect(user.notifications.length).to.equal(3); // includes Guild Joined achievement + expect(user.notifications[2].type).to.equal('GROUP_TASK_CLAIMED'); + expect(user.notifications[2].data.taskId).to.equal(groupTask[0]._id); + expect(user.notifications[2].data.groupId).to.equal(guild._id); + expect(member2.notifications.length).to.equal(2); + expect(member2.notifications[1].type).to.equal('GROUP_TASK_CLAIMED'); + expect(member2.notifications[1].data.taskId).to.equal(groupTask[0]._id); + expect(member2.notifications[1].data.groupId).to.equal(guild._id); }); it('assigns a task to a user', async () => { @@ -130,9 +131,9 @@ describe('POST /tasks/:taskId/assign/:memberId', () => { const groupTask = await user.get(`/tasks/group/${guild._id}`); - expect(member.notifications.length).to.equal(1); - expect(member.notifications[0].type).to.equal('GROUP_TASK_ASSIGNED'); - expect(member.notifications[0].taskId).to.equal(groupTask._id); + expect(member.notifications.length).to.equal(2); + expect(member.notifications[1].type).to.equal('GROUP_TASK_ASSIGNED'); + expect(member.notifications[1].taskId).to.equal(groupTask._id); }); it('assigns a task to multiple users', async () => { diff --git a/test/api/v3/integration/tasks/groups/POST-tasks_move_taskId_to_position.test.js b/test/api/v3/integration/tasks/groups/POST-tasks_move_taskId_to_position.test.js index 9dcc956e1b..3255f85206 100644 --- a/test/api/v3/integration/tasks/groups/POST-tasks_move_taskId_to_position.test.js +++ b/test/api/v3/integration/tasks/groups/POST-tasks_move_taskId_to_position.test.js @@ -9,7 +9,7 @@ describe('POST group-tasks/:taskId/move/to/:position', () => { beforeEach(async () => { user = await generateUser({ balance: 1 }); - guild = await generateGroup(user, { type: 'guild' }); + guild = await generateGroup(user, { type: 'guild' }, { 'purchased.plan.customerId': 'group-unlimited' }); }); it('can move task to new position', async () => { diff --git a/test/api/v3/integration/tasks/groups/POST-tasks_task_id_unassign.test.js b/test/api/v3/integration/tasks/groups/POST-tasks_task_id_unassign.test.js index 0a9a09cbe1..83d67246d6 100644 --- a/test/api/v3/integration/tasks/groups/POST-tasks_task_id_unassign.test.js +++ b/test/api/v3/integration/tasks/groups/POST-tasks_task_id_unassign.test.js @@ -21,6 +21,7 @@ describe('POST /tasks/:taskId/unassign/:memberId', () => { type: 'guild', }, members: 2, + upgradeToGroupPlan: true, }); guild = group; @@ -91,7 +92,7 @@ describe('POST /tasks/:taskId/unassign/:memberId', () => { await user.post(`/tasks/${task._id}/unassign/${member._id}`); await member.sync(); - expect(member.notifications.length).to.equal(0); + expect(member.notifications.length).to.equal(1); // mystery items }); it('unassigns a user and only that user from a task', async () => { diff --git a/test/api/v3/integration/tasks/groups/PUT-group_task_id.test.js b/test/api/v3/integration/tasks/groups/PUT-group_task_id.test.js index 44dc4fb162..abfd5ae629 100644 --- a/test/api/v3/integration/tasks/groups/PUT-group_task_id.test.js +++ b/test/api/v3/integration/tasks/groups/PUT-group_task_id.test.js @@ -22,6 +22,7 @@ describe('PUT /tasks/:id', () => { type: 'guild', }, members: 2, + upgradeToGroupPlan: true, }); guild = group; diff --git a/test/api/v3/integration/tasks/groups/checklists/DELETE-group_tasks_taskId_checklist_item.test.js b/test/api/v3/integration/tasks/groups/checklists/DELETE-group_tasks_taskId_checklist_item.test.js index 537b100363..b972a8a151 100644 --- a/test/api/v3/integration/tasks/groups/checklists/DELETE-group_tasks_taskId_checklist_item.test.js +++ b/test/api/v3/integration/tasks/groups/checklists/DELETE-group_tasks_taskId_checklist_item.test.js @@ -15,6 +15,7 @@ describe('DELETE group /tasks/:taskId/checklist/:itemId', () => { type: 'guild', }, members: 2, + upgradeToGroupPlan: true, }); guild = group; diff --git a/test/api/v3/integration/tasks/groups/checklists/POST-group_tasks_taskId_checklist.test.js b/test/api/v3/integration/tasks/groups/checklists/POST-group_tasks_taskId_checklist.test.js index 257dd3dfa4..76b1c810e1 100644 --- a/test/api/v3/integration/tasks/groups/checklists/POST-group_tasks_taskId_checklist.test.js +++ b/test/api/v3/integration/tasks/groups/checklists/POST-group_tasks_taskId_checklist.test.js @@ -15,6 +15,7 @@ describe('POST group /tasks/:taskId/checklist/', () => { type: 'guild', }, members: 2, + upgradeToGroupPlan: true, }); guild = group; diff --git a/test/api/v3/integration/tasks/groups/checklists/PUT-group_tasks_taskId_checklist_itemId.test.js b/test/api/v3/integration/tasks/groups/checklists/PUT-group_tasks_taskId_checklist_itemId.test.js index 2565da77e0..cb69d1c98c 100644 --- a/test/api/v3/integration/tasks/groups/checklists/PUT-group_tasks_taskId_checklist_itemId.test.js +++ b/test/api/v3/integration/tasks/groups/checklists/PUT-group_tasks_taskId_checklist_itemId.test.js @@ -15,6 +15,7 @@ describe('PUT group /tasks/:taskId/checklist/:itemId', () => { type: 'guild', }, members: 2, + upgradeToGroupPlan: true, }); guild = group; diff --git a/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js b/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js index f806574e6d..df7676b945 100644 --- a/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js +++ b/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js @@ -139,7 +139,7 @@ describe('POST /user/class/cast/:spellId', () => { }); it('returns an error if a group task was targeted', async () => { - const { group, groupLeader } = await createAndPopulateGroup(); + const { group, groupLeader } = await createAndPopulateGroup({ upgradeToGroupPlan: true }); const groupTask = await groupLeader.post(`/tasks/group/${group._id}`, { text: 'todo group', @@ -266,7 +266,7 @@ describe('POST /user/class/cast/:spellId', () => { }); it('searing brightness does not affect challenge or group tasks', async () => { - const guild = await generateGroup(user); + const guild = await generateGroup(user, {}, { 'purchased.plan.customerId': 'group-unlimited' }); const challenge = await generateChallenge(user, guild); await user.post(`/challenges/${challenge._id}/join`); await user.post(`/tasks/challenge/${challenge._id}`, { diff --git a/test/api/v3/integration/user/POST-user_reset.test.js b/test/api/v3/integration/user/POST-user_reset.test.js index 760c64df37..5d750fde98 100644 --- a/test/api/v3/integration/user/POST-user_reset.test.js +++ b/test/api/v3/integration/user/POST-user_reset.test.js @@ -88,7 +88,7 @@ describe('POST /user/reset', () => { }); it('does not delete challenge or group tasks', async () => { - const guild = await generateGroup(user); + const guild = await generateGroup(user, {}, { 'purchased.plan.customerId': 'group-unlimited' }); const challenge = await generateChallenge(user, guild); await user.post(`/challenges/${challenge._id}/join`); await user.post(`/tasks/challenge/${challenge._id}`, { diff --git a/test/api/v4/user/POST-user_class_cast_spellId.test.js b/test/api/v4/user/POST-user_class_cast_spellId.test.js index 851500b3e1..b9382bba3d 100644 --- a/test/api/v4/user/POST-user_class_cast_spellId.test.js +++ b/test/api/v4/user/POST-user_class_cast_spellId.test.js @@ -124,7 +124,7 @@ describe('POST /user/class/cast/:spellId', () => { }); it('returns an error if a group task was targeted', async () => { - const { group, groupLeader } = await createAndPopulateGroup(); + const { group, groupLeader } = await createAndPopulateGroup({ upgradeToGroupPlan: true }); const groupTask = await groupLeader.post(`/tasks/group/${group._id}`, { text: 'todo group', @@ -234,7 +234,7 @@ describe('POST /user/class/cast/:spellId', () => { }); it('searing brightness does not affect challenge or group tasks', async () => { - const guild = await generateGroup(user); + const guild = await generateGroup(user, {}, { 'purchased.plan.customerId': 'group-unlimited' }); const challenge = await generateChallenge(user, guild); await user.post(`/challenges/${challenge._id}/join`); await user.post(`/tasks/challenge/${challenge._id}`, { diff --git a/test/api/v4/user/POST-user_reset.test.js b/test/api/v4/user/POST-user_reset.test.js index 677bf193ce..ced9126eb2 100644 --- a/test/api/v4/user/POST-user_reset.test.js +++ b/test/api/v4/user/POST-user_reset.test.js @@ -88,7 +88,7 @@ describe('POST /user/reset', () => { }); it('does not delete challenge or group tasks', async () => { - const guild = await generateGroup(user); + const guild = await generateGroup(user, {}, { 'purchased.plan.customerId': 'group-unlimited' }); const challenge = await generateChallenge(user, guild); await user.post(`/challenges/${challenge._id}/join`); await user.post(`/tasks/challenge/${challenge._id}`, { diff --git a/test/helpers/api-integration/v4/object-generators.js b/test/helpers/api-integration/v4/object-generators.js index 99030f834f..59b0642b15 100644 --- a/test/helpers/api-integration/v4/object-generators.js +++ b/test/helpers/api-integration/v4/object-generators.js @@ -5,6 +5,8 @@ import { v4 as generateUUID } from 'uuid'; import { ApiUser, ApiGroup, ApiChallenge } from '../api-classes'; import { requester } from '../requester'; import * as Tasks from '../../../../website/server/models/task'; +import payments from '../../../../website/server/libs/payments/payments'; +import { model as User } from '../../../../website/server/models/user'; // Creates a new user and returns it // If you need the user to have specific requirements, @@ -77,6 +79,26 @@ export async function generateGroup (leader, details = {}, update = {}) { return apiGroup; } +async function _upgradeToGroupPlan (groupLeader, group) { + const groupLeaderModel = await User.findById(groupLeader._id).exec(); + + // Create subscription + const paymentData = { + user: groupLeaderModel, + groupId: group._id, + sub: { + key: 'basic_3mo', + }, + customerId: 'customer-id', + paymentMethod: 'Payment Method', + headers: { + 'x-client': 'habitica-web', + 'user-agent': '', + }, + }; + await payments.createSubscription(paymentData); +} + // This is generate group + the ability to create // real users to populate it. The settings object // takes in: @@ -95,6 +117,7 @@ export async function generateGroup (leader, details = {}, update = {}) { export async function createAndPopulateGroup (settings = {}) { const numberOfMembers = settings.members || 0; const numberOfInvites = settings.invites || 0; + const upgradeToGroupPlan = settings.upgradeToGroupPlan || false; const { groupDetails } = settings; const leaderDetails = settings.leaderDetails || { balance: 10 }; @@ -124,6 +147,10 @@ export async function createAndPopulateGroup (settings = {}) { await Promise.all(invitees.map(invitee => invitee.sync())); + if (upgradeToGroupPlan) { + await _upgradeToGroupPlan(groupLeader, group); + } + return { groupLeader, group, diff --git a/website/client/src/components/group-plans/taskInformation.vue b/website/client/src/components/group-plans/taskInformation.vue index e215d80212..ddee1d5826 100644 --- a/website/client/src/components/group-plans/taskInformation.vue +++ b/website/client/src/components/group-plans/taskInformation.vue @@ -225,6 +225,11 @@ export default { this.group = await this.$store.dispatch('guilds:getGroup', { groupId: this.searchId, }); + if (!this.group?.purchased?.active) { + if (this.group.type === 'guild') this.$router.push(`/groups/guild/${this.group._id}`); + if (this.group.type === 'party') this.$router.push('/party'); + return; + } this.$store.dispatch('common:setTitle', { subSection: this.group.name, section: this.$route.path.startsWith('/group-plans') ? this.$t('groupPlans') : this.$t('group'), diff --git a/website/client/src/components/tasks/taskModal.vue b/website/client/src/components/tasks/taskModal.vue index 40dce98644..3720543d0f 100644 --- a/website/client/src/components/tasks/taskModal.vue +++ b/website/client/src/components/tasks/taskModal.vue @@ -1280,12 +1280,17 @@ export default { createTag: 'tags:createTag', }), async syncTask () { - if (this.task && this.task.group && this.task.group.managerNotes) { + if (this.task?.group?.managerNotes) { this.managerNotes = this.task.group.managerNotes; } - if (this.groupId && this.task.group && this.task.group.approval) { + if (this.groupId && this.task.group?.approval) { this.requiresApproval = this.task.group.approval.required; } + if (this.task?.group?.sharedCompletion) { + this.sharedCompletion = this.task.group.sharedCompletion; + } else if (this.task.group) { + this.sharedCompletion = 'singleCompletion'; + } if (this.groupId) { const members = await this.$store.dispatch('members:getGroupMembers', { @@ -1306,9 +1311,6 @@ export default { if (this.task.group && this.task.group.assignedUsers) { this.assignedMembers = this.task.group.assignedUsers; } - if (this.task.group) { - this.sharedCompletion = this.task.group.sharedCompletion || 'singleCompletion'; - } } // @TODO: This whole component is mutating a prop diff --git a/website/server/controllers/api-v3/tasks/groups.js b/website/server/controllers/api-v3/tasks/groups.js index ab18f7faad..59cf9c2b9d 100644 --- a/website/server/controllers/api-v3/tasks/groups.js +++ b/website/server/controllers/api-v3/tasks/groups.js @@ -11,6 +11,7 @@ import { canNotEditTasks, createTasks, getTasks, + groupSubscriptionNotFound, } from '../../../libs/tasks'; import { moveTask, @@ -50,9 +51,9 @@ api.createGroupTasks = { const { user } = res.locals; - const fields = requiredGroupFields.concat(' managers'); + const fields = requiredGroupFields.concat(' purchased managers'); const group = await Group.getGroup({ user, groupId: req.params.groupId, fields }); - if (!group) throw new NotFound(res.t('groupNotFound')); + if (groupSubscriptionNotFound(group)) throw new NotFound(res.t('groupNotFound')); if (canNotEditTasks(group, user)) throw new NotAuthorized(res.t('onlyGroupLeaderCanEditTasks')); @@ -99,9 +100,9 @@ api.getGroupTasks = { const group = await Group.getGroup({ user, groupId: req.params.groupId, - fields: requiredGroupFields, + fields: requiredGroupFields.concat(' purchased'), }); - if (!group) throw new NotFound(res.t('groupNotFound')); + if (groupSubscriptionNotFound(group)) throw new NotFound(res.t('groupNotFound')); const tasks = await getTasks(req, res, { user, group }); res.respond(200, tasks); @@ -152,9 +153,9 @@ api.groupMoveTask = { const group = await Group.getGroup({ user, groupId: task.group.id, - fields: requiredGroupFields, + fields: requiredGroupFields.concat(' purchased'), }); - if (!group) throw new NotFound(res.t('groupNotFound')); + if (groupSubscriptionNotFound(group)) throw new NotFound(res.t('groupNotFound')); if (group.leader !== user._id) throw new NotAuthorized(res.t('onlyGroupLeaderCanEditTasks')); @@ -219,9 +220,9 @@ api.assignTask = { throw new NotAuthorized(res.t('onlyGroupTasksCanBeAssigned')); } - const groupFields = `${requiredGroupFields} chat managers`; + const groupFields = `${requiredGroupFields} purchased chat managers`; const group = await Group.getGroup({ user, groupId: task.group.id, fields: groupFields }); - if (!group) throw new NotFound(res.t('groupNotFound')); + if (groupSubscriptionNotFound(group)) throw new NotFound(res.t('groupNotFound')); if (canNotEditTasks(group, user, assignedUserId)) throw new NotAuthorized(res.t('onlyGroupLeaderCanEditTasks')); @@ -294,9 +295,9 @@ api.unassignTask = { throw new NotAuthorized(res.t('onlyGroupTasksCanBeAssigned')); } - const fields = requiredGroupFields.concat(' managers'); + const fields = requiredGroupFields.concat(' purchased managers'); const group = await Group.getGroup({ user, groupId: task.group.id, fields }); - if (!group) throw new NotFound(res.t('groupNotFound')); + if (groupSubscriptionNotFound(group)) throw new NotFound(res.t('groupNotFound')); if (canNotEditTasks(group, user, assignedUserId)) throw new NotAuthorized(res.t('onlyGroupLeaderCanEditTasks')); @@ -350,9 +351,9 @@ api.approveTask = { throw new NotFound(res.t('messageTaskNotFound')); } - const fields = requiredGroupFields.concat(' managers'); + const fields = requiredGroupFields.concat(' purchased managers'); const group = await Group.getGroup({ user, groupId: task.group.id, fields }); - if (!group) throw new NotFound(res.t('groupNotFound')); + if (groupSubscriptionNotFound(group)) throw new NotFound(res.t('groupNotFound')); if (canNotEditTasks(group, user)) throw new NotAuthorized(res.t('onlyGroupLeaderCanEditTasks')); if (task.group.approval.approved === true) throw new NotAuthorized(res.t('canOnlyApproveTaskOnce')); @@ -458,9 +459,9 @@ api.taskNeedsWork = { throw new NotFound(res.t('messageTaskNotFound')); } - const fields = requiredGroupFields.concat(' managers'); + const fields = requiredGroupFields.concat(' purchased managers'); const group = await Group.getGroup({ user, groupId: task.group.id, fields }); - if (!group) throw new NotFound(res.t('groupNotFound')); + if (groupSubscriptionNotFound(group)) throw new NotFound(res.t('groupNotFound')); if (canNotEditTasks(group, user)) throw new NotAuthorized(res.t('onlyGroupLeaderCanEditTasks')); if (task.group.approval.approved === true) throw new NotAuthorized(res.t('canOnlyApproveTaskOnce')); @@ -538,9 +539,9 @@ api.getGroupApprovals = { const { user } = res.locals; const { groupId } = req.params; - const fields = requiredGroupFields.concat(' managers'); + const fields = requiredGroupFields.concat(' purchased managers'); const group = await Group.getGroup({ user, groupId, fields }); - if (!group) throw new NotFound(res.t('groupNotFound')); + if (groupSubscriptionNotFound(group)) throw new NotFound(res.t('groupNotFound')); let approvals; if (canNotEditTasks(group, user)) { diff --git a/website/server/libs/tasks/index.js b/website/server/libs/tasks/index.js index 48a97ffa15..e743967137 100644 --- a/website/server/libs/tasks/index.js +++ b/website/server/libs/tasks/index.js @@ -245,6 +245,11 @@ function canNotEditTasks (group, user, assignedUserId) { return isNotGroupLeader && !isManager && !userIsAssigningToSelf; } +function groupSubscriptionNotFound (group) { + return !group || !group.purchased || !group.purchased.plan || !group.purchased.plan.customerId + || (group.purchased.plan.dateTerminated && group.purchased.plan.dateTerminated < new Date()); +} + async function getGroupFromTaskAndUser (task, user) { if (task.group.id && !task.userId) { const fields = requiredGroupFields.concat(' managers'); @@ -550,5 +555,6 @@ export { canNotEditTasks, getGroupFromTaskAndUser, getChallengeFromTask, + groupSubscriptionNotFound, verifyTaskModification, };