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 1689e30437..7dfce6d6cc 100644 --- a/test/api/v3/integration/tasks/POST-tasks_clearCompletedTodos.test.js +++ b/test/api/v3/integration/tasks/POST-tasks_clearCompletedTodos.test.js @@ -5,7 +5,7 @@ import { } from '../../../../helpers/api-integration/v3'; describe('POST /tasks/clearCompletedTodos', () => { - it('deletes all completed todos except the ones from a challenge', async () => { + it('deletes all completed todos except the ones from a challenge and group', async () => { let user = await generateUser({balance: 1}); let guild = await generateGroup(user); let challenge = await generateChallenge(user, guild); @@ -24,8 +24,14 @@ describe('POST /tasks/clearCompletedTodos', () => { type: 'todo', }); + let groupTask = await user.post(`/tasks/group/${guild._id}`, { + text: 'todo 7', + type: 'todo', + }); + await user.post(`/tasks/${groupTask._id}/assign/${user._id}`); + let tasks = await user.get('/tasks/user?type=todos'); - expect(tasks.length).to.equal(initialTodoCount + 6); + expect(tasks.length).to.equal(initialTodoCount + 7); for (let task of tasks) { if (['todo 2', 'todo 3', 'todo 6'].indexOf(task.text) !== -1) { @@ -38,6 +44,6 @@ describe('POST /tasks/clearCompletedTodos', () => { let todos = await user.get('/tasks/user?type=todos'); let allTodos = todos.concat(completedTodos); expect(allTodos.length).to.equal(initialTodoCount + 4); // + 6 - 3 completed (but one is from challenge) - expect(allTodos[allTodos.length - 1].text).to.equal('todo 6'); + expect(allTodos[allTodos.length - 1].text).to.equal('todo 7'); }); }); 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 91c6ab3649..ccad5c24e8 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 @@ -7,6 +7,7 @@ import { } from '../../../../helpers/api-integration/v3'; import { v4 as generateUUID } from 'uuid'; +import { find } from 'lodash'; describe('POST /user/class/cast/:spellId', () => { let user; @@ -120,6 +121,31 @@ describe('POST /user/class/cast/:spellId', () => { }); }); + it('returns an error if a group task was targeted', async () => { + let {group, groupLeader} = await createAndPopulateGroup(); + + let groupTask = await groupLeader.post(`/tasks/group/${group._id}`, { + text: 'todo group', + type: 'todo', + }); + await groupLeader.post(`/tasks/${groupTask._id}/assign/${groupLeader._id}`); + let memberTasks = await groupLeader.get('/tasks/user'); + let syncedGroupTask = find(memberTasks, function findAssignedTask (memberTask) { + return memberTask.group.id === group._id; + }); + + await groupLeader.update({'stats.class': 'rogue', 'stats.lvl': 11}); + await sleep(0.5); + await groupLeader.sync(); + + await expect(groupLeader.post(`/user/class/cast/pickPocket?targetId=${syncedGroupTask._id}`)) + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('groupTasksNoCast'), + }); + }); + it('returns an error if targeted party member doesn\'t exist', async () => { let {groupLeader} = await createAndPopulateGroup({ groupDetails: { type: 'party', privacy: 'private' }, 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 2baf7bd083..cac12d6d9c 100644 --- a/test/api/v3/integration/user/POST-user_reset.test.js +++ b/test/api/v3/integration/user/POST-user_reset.test.js @@ -4,6 +4,7 @@ import { generateChallenge, translate as t, } from '../../../../helpers/api-integration/v3'; +import { find } from 'lodash'; describe('POST /user/reset', () => { let user; @@ -86,19 +87,34 @@ describe('POST /user/reset', () => { expect(user.tasksOrder.rewards).to.be.empty; }); - it('does not delete challenge tasks', async () => { + it('does not delete challenge or group tasks', async () => { let guild = await generateGroup(user); let challenge = await generateChallenge(user, guild); - let task = await user.post(`/tasks/challenge/${challenge._id}`, { + await user.post(`/tasks/challenge/${challenge._id}`, { text: 'test challenge habit', type: 'habit', }); + let groupTask = await user.post(`/tasks/group/${guild._id}`, { + text: 'todo group', + type: 'todo', + }); + await user.post(`/tasks/${groupTask._id}/assign/${user._id}`); + await user.post('/user/reset'); await user.sync(); - let userChallengeTask = await user.get(`/tasks/${task._id}`); + let memberTasks = await user.get('/tasks/user'); - expect(userChallengeTask).to.eql(task); + let syncedGroupTask = find(memberTasks, function findAssignedTask (memberTask) { + return memberTask.group.id === guild._id; + }); + + let userChallengeTask = find(memberTasks, function findAssignedTask (memberTask) { + return memberTask.challenge.id === challenge._id; + }); + + expect(userChallengeTask).to.exist; + expect(syncedGroupTask).to.exist; }); }); diff --git a/website/common/locales/en/spells.json b/website/common/locales/en/spells.json index 4be7778964..d1e41ca926 100644 --- a/website/common/locales/en/spells.json +++ b/website/common/locales/en/spells.json @@ -75,6 +75,7 @@ "partyNotFound": "Party not found", "targetIdUUID": "\"targetId\" must be a valid User ID.", "challengeTasksNoCast": "Casting a skill on challenge tasks is not allowed.", + "groupTasksNoCast": "Casting a skill on group tasks is not allowed.", "spellNotOwned": "You don't own this skill.", "spellLevelTooHigh": "You must be level <%= level %> to use this skill." } diff --git a/website/common/script/ops/reset.js b/website/common/script/ops/reset.js index a973a019c7..4108d08e9e 100644 --- a/website/common/script/ops/reset.js +++ b/website/common/script/ops/reset.js @@ -9,7 +9,10 @@ module.exports = function reset (user, tasks = []) { let tasksToRemove = []; tasks.forEach(task => { - if (!task.challenge || !task.challenge.id || task.challenge.broken) { + let isNotChallengeTask = !task.challenge || !task.challenge.id || task.challenge.broken; + let isNotGroupTask = !task.group || !task.group.id || task.group.broken; + + if (isNotChallengeTask && isNotGroupTask) { tasksToRemove.push(task._id); let i = user.tasksOrder[`${task.type}s`].indexOf(task._id); if (i !== -1) user.tasksOrder[`${task.type}s`].splice(i, 1); diff --git a/website/server/controllers/api-v3/tasks.js b/website/server/controllers/api-v3/tasks.js index 557243793e..c5cd6a5cd7 100644 --- a/website/server/controllers/api-v3/tasks.js +++ b/website/server/controllers/api-v3/tasks.js @@ -917,6 +917,8 @@ api.clearCompletedTodos = { $or: [ {'challenge.id': {$exists: false}}, {'challenge.broken': {$exists: true}}, + {'group.id': {$exists: false}}, + {'group.broken': {$exists: true}}, ], }).exec(); diff --git a/website/server/controllers/api-v3/user.js b/website/server/controllers/api-v3/user.js index 44576bc8d0..e980a9b055 100644 --- a/website/server/controllers/api-v3/user.js +++ b/website/server/controllers/api-v3/user.js @@ -372,6 +372,7 @@ api.castSpell = { }).exec(); if (!task) throw new NotFound(res.t('taskNotFound')); if (task.challenge.id) throw new BadRequest(res.t('challengeTasksNoCast')); + if (task.group.id) throw new BadRequest(res.t('groupTasksNoCast')); spell.cast(user, task, req); @@ -394,6 +395,8 @@ api.castSpell = { $or: [ // exclude challenge tasks {'challenge.id': {$exists: false}}, {'challenge.broken': {$exists: true}}, + {'group.id': {$exists: false}}, + {'group.broken': {$exists: true}}, ], }).exec(); @@ -1055,6 +1058,8 @@ api.userRebirth = { $or: [ // exclude challenge tasks {'challenge.id': {$exists: false}}, {'challenge.broken': {$exists: true}}, + {'group.id': {$exists: false}}, + {'group.broken': {$exists: true}}, ], }).exec(); @@ -1171,6 +1176,8 @@ api.userReroll = { $or: [ // exclude challenge tasks {'challenge.id': {$exists: false}}, {'challenge.broken': {$exists: true}}, + {'group.id': {$exists: false}}, + {'group.broken': {$exists: true}}, ], }; let tasks = await Tasks.Task.find(query).exec(); @@ -1206,8 +1213,10 @@ api.userReset = { $or: [ // exclude challenge tasks {'challenge.id': {$exists: false}}, {'challenge.broken': {$exists: true}}, + {'group.id': {$exists: false}}, + {'group.broken': {$exists: true}}, ], - }).select('_id type challenge').exec(); + }).select('_id type challenge group').exec(); let resetRes = common.ops.reset(user, tasks);