From 707170ec7e78141c35c5c7b2db91d61cebb62877 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Sat, 30 Jan 2016 13:35:05 -0600 Subject: [PATCH] feat(api-v3): Add failure conditions for quest invite route --- .../POST-groups_groupId_quests_invite.test.js | 54 ++++++++++++------- website/src/controllers/api-v3/groups.js | 39 ++++++++++++++ 2 files changed, 74 insertions(+), 19 deletions(-) diff --git a/test/api/v3/integration/groups/POST-groups_groupId_quests_invite.test.js b/test/api/v3/integration/groups/POST-groups_groupId_quests_invite.test.js index 7f43168b95..7fbbfa2ca6 100644 --- a/test/api/v3/integration/groups/POST-groups_groupId_quests_invite.test.js +++ b/test/api/v3/integration/groups/POST-groups_groupId_quests_invite.test.js @@ -3,8 +3,9 @@ import { translate as t, } from '../../../../helpers/api-v3-integration.helper'; import { v4 as generateUUID } from 'uuid'; +import { quests as questScrolls } from '../../../../../common/script/content'; -describe.skip('POST /groups/:groupId/quests/invite', () => { +describe('POST /groups/:groupId/quests/invite/:questKey', () => { let questingGroup; let leader; let member; @@ -31,11 +32,13 @@ describe.skip('POST /groups/:groupId/quests/invite', () => { }); it('does not issue invites for a group in which user is not a member', async () => { - let { alternateGroup } = await createAndPopulateGroup({ + let { group } = await createAndPopulateGroup({ groupDetails: { type: 'party', privacy: 'private' }, members: 1, }); + let alternateGroup = group; + await expect(leader.post(`/groups/${alternateGroup._id}/quests/invite/${PET_QUEST}`)).to.eventually.be.rejected.and.eql({ code: 404, error: 'NotFound', @@ -44,11 +47,13 @@ describe.skip('POST /groups/:groupId/quests/invite', () => { }); it('does not issue invites for Guilds', async () => { - let { alternateGroup } = await createAndPopulateGroup({ + let { group } = await createAndPopulateGroup({ groupDetails: { type: 'guild', privacy: 'public' }, members: 1, }); + let alternateGroup = group; + await expect(leader.post(`/groups/${alternateGroup._id}/quests/invite/${PET_QUEST}`)).to.eventually.be.rejected.and.eql({ code: 401, error: 'NotAuthorized', @@ -76,8 +81,12 @@ describe.skip('POST /groups/:groupId/quests/invite', () => { it('does not issue invites if the user is of insufficient Level', async () => { const LEVELED_QUEST = 'atom1'; - const LEVELED_QUEST_REQ = 15; - leader.items.quests[LEVELED_QUEST] = 1; + const LEVELED_QUEST_REQ = questScrolls[LEVELED_QUEST].lvl; + const leaderUpdate = {}; + leaderUpdate[`items.quests.${LEVELED_QUEST}`] = 1; + leaderUpdate['stats.lvl'] = LEVELED_QUEST_REQ - 1; + + await leader.update(leaderUpdate); await expect(leader.post(`/groups/${questingGroup._id}/quests/invite/${LEVELED_QUEST}`)).to.eventually.be.rejected.and.eql({ code: 401, @@ -87,9 +96,12 @@ describe.skip('POST /groups/:groupId/quests/invite', () => { }); it('does not issue invites if a quest is already underway', async () => { - leader.items.quests[PET_QUEST] = 2; + const QUEST_IN_PROGRESS = 'atom1'; + const leaderUpdate = {}; + leaderUpdate[`items.quests.${PET_QUEST}`] = 1; - await leader.post(`/groups/${questingGroup._id}/quests/invite/${PET_QUEST}`); + await leader.update(leaderUpdate); + await questingGroup.update({ 'quest.key': QUEST_IN_PROGRESS }); await expect(leader.post(`/groups/${questingGroup._id}/quests/invite/${PET_QUEST}`)).to.eventually.be.rejected.and.eql({ code: 401, @@ -99,18 +111,22 @@ describe.skip('POST /groups/:groupId/quests/invite', () => { }); }); - context('successfully issuing a quest invitation', () => { - let inviteResponse = { - key: PET_QUEST, - active: false, - leader: leader._id, - members: {}, - progress: { - collect: {}, - }, - }; - inviteResponse.members[member._id] = null; - inviteResponse.members[leader._id] = null; + context.skip('successfully issuing a quest invitation', () => { + let inviteResponse; + + beforeEach(() => { + inviteResponse = { + key: PET_QUEST, + active: false, + leader: leader._id, + members: {}, + progress: { + collect: {}, + }, + }; + inviteResponse.members[member._id] = null; + inviteResponse.members[leader._id] = null; + }); it('sends an invite to all party members', async () => { leader.items.quests[PET_QUEST] = 1; diff --git a/website/src/controllers/api-v3/groups.js b/website/src/controllers/api-v3/groups.js index b9b633c111..628d31f1f2 100644 --- a/website/src/controllers/api-v3/groups.js +++ b/website/src/controllers/api-v3/groups.js @@ -17,6 +17,7 @@ import { removeFromArray } from '../../libs/api-v3/collectionManipulators'; import * as firebase from '../../libs/api-v3/firebase'; import { sendTxn as sendTxnEmail } from '../../libs/api-v3/email'; import { encrypt } from '../../libs/api-v3/encryption'; +import { quests as questScrolls } from '../../../../common/script/content'; let api = {}; @@ -616,4 +617,42 @@ api.inviteToGroup = { }, }; +/** + * @api {post} /groups/:groupId/quests/invite Invite users to a quest + * @apiVersion 3.0.0 + * @apiName InviteToQuest + * @apiGroup Group + * + * @apiParam {string} groupId The group _id (or 'party') + * + * @apiSuccess {Object} Quest Object + */ +api.inviteToQuest = { + method: 'POST', + url: '/groups/:groupId/quests/invite/:questKey', + middlewares: [authWithHeaders(), cron], + async handler (req, res) { + let user = res.locals.user; + let questKey = req.params.questKey; + let quest = questScrolls[questKey]; + + req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + + let validationErrors = req.validationErrors(); + if (validationErrors) throw validationErrors; + + let group = await Group.getGroup({user, groupId: req.params.groupId, fields: 'type quest'}); + + if (!group) throw new NotFound(res.t('groupNotFound')); + if (group.type !== 'party') throw new NotAuthorized(res.t('guildQuestsNotSupported')); + if (!quest) throw new NotFound(res.t('questNotFound', { key: questKey })); + if (!user.items.quests[questKey]) throw new NotAuthorized(res.t('questNotOwned')); + if (user.stats.lvl < quest.lvl) throw new NotAuthorized(res.t('questLevelTooHigh', { level: quest.lvl })); + if (group.quest.key) throw new NotAuthorized(res.t('questAlreadyUnderway')); + + // TODO Logic for quest invite and send back quest object + res.respond(200, {}); + }, +}; + export default api;