diff --git a/test/api-legacy/groups.coffee b/test/api-legacy/groups.coffee index 4111bf82e8..0927433138 100644 --- a/test/api-legacy/groups.coffee +++ b/test/api-legacy/groups.coffee @@ -6,134 +6,6 @@ Group = require("../../website/src/models/group").model app = require("../../website/src/server") describe.skip "Guilds", -> - context "leaving groups", -> - it "can leave a guild", (done) -> - guildToLeave = undefined - request.post(baseURL + "/groups").send( - name: "TestGroupToLeave" - type: "guild" - ).end (err, res) -> - guildToLeave = res.body - request.post(baseURL + "/groups/" + guildToLeave._id + "/leave") - .send() - .end (err, res) -> - expectCode res, 204 - done() - - it "deletes a group when the last member leaves", (done) -> - groupToDeleteAfterLeave = undefined - request.post(baseURL + "/groups").send( - name: "TestGroupToDeleteAfteLeave" - type: "guild" - privacy: "private" - ).end (err, res) -> - groupToDeleteAfterLeave = res.body - async.waterfall [ - (cb) -> - request.post(baseURL + "/groups/" + groupToDeleteAfterLeave._id + "/leave") - .end (err, res) -> - expectCode res, 204 - cb() - - (cb) -> - request.post(baseURL + "/groups/" + groupToDeleteAfterLeave._id) - .end (err, res) -> - expectCode res, 404 - cb() - ], done - - it "deletes all invites to a group (guild) when the last member leaves", (done) -> - groupToDeleteAfterLeave = undefined - userToRemoveInvite = undefined - request.post(baseURL + "/groups").send( - name: "TestGroupToDeleteAfterLeave" - type: "guild" - privacy: "private" - ).end (err, res) -> - groupToDeleteAfterLeave = res.body - async.waterfall [ - (cb) -> - registerManyUsers 1, cb - - (_members, cb) -> - userToRemoveInvite = _members[0] - inviteURL = baseURL + "/groups/" + groupToDeleteAfterLeave._id + "/invite" - request.post(inviteURL).send( - uuids: [userToRemoveInvite._id] - ) - .end -> - cb() - - (cb) -> - request.post(baseURL + "/groups/" + groupToDeleteAfterLeave._id + "/leave") - .end (err, res) -> - expectCode res, 204 - cb() - - (cb) -> - request.get(baseURL + '/user') - .set("X-API-User", userToRemoveInvite._id) - .set("X-API-Key", userToRemoveInvite.apiToken) - .end (err, res) -> - expectCode res, 200 - groupInvitation = _.find(res.body.invitations.guilds, {id: groupToDeleteAfterLeave._id}) - expect(groupInvitation).to.not.exist - cb() - - (cb) -> - request.post(baseURL + "/groups/" + groupToDeleteAfterLeave._id) - .end (err, res) -> - expectCode res, 404 - cb() - ], done - - it "deletes all invites to a group (party) when the last member leaves", (done) -> - partyToDeleteAfterLeave = undefined - userToRemovePartyInvite = undefined - request.post(baseURL + "/groups").send( - name: "TestPartyToDeleteAfterLeave" - type: "party" - ).end (err, res) -> - partyToDeleteAfterLeave = res.body - async.waterfall [ - (cb) -> - registerManyUsers 1, cb - - (_members, cb) -> - userToRemovePartyInvite = _members[0] - inviteURL = baseURL + "/groups/" + partyToDeleteAfterLeave._id + "/invite" - request.post(inviteURL).send( - uuids: [userToRemovePartyInvite._id] - ) - .end -> - cb() - - (cb) -> - request.post(baseURL + "/groups/" + partyToDeleteAfterLeave._id + "/leave") - .end (err, res) -> - expectCode res, 204 - cb() - - (cb) -> - request.get(baseURL + '/user') - .set("X-API-User", userToRemovePartyInvite._id) - .set("X-API-Key", userToRemovePartyInvite.apiToken) - .end (err, res) -> - expectCode res, 200 - party = partyToDeleteAfterLeave - partyInvitation = _.find(res.body.invitations.party, (invite) -> - return invite == party._id - ) - expect(partyInvitation).to.not.exist - cb() - - (cb) -> - request.post(baseURL + "/groups/" + partyToDeleteAfterLeave._id) - .end (err, res) -> - expectCode res, 404 - cb() - ], done - context "removing users groups", -> it "allows guild leaders to remove a member (but not themselves)", (done) -> guildToRemoveMember = undefined diff --git a/test/api/groups/groups_id_leave-post.js b/test/api/groups/groups_id_leave-post.js new file mode 100644 index 0000000000..ba008490a9 --- /dev/null +++ b/test/api/groups/groups_id_leave-post.js @@ -0,0 +1,169 @@ +import { + createAndPopulateGroup, + generateGroup, + generateUser, + requester, +} from '../../helpers/api.helper'; + +describe('POST /groups/:id/leave', () => { + + context('user is not member of the group', () => { + it('returns an error'); + }); + + context('user is a non-leader member of a guild', () => { + let api, user, group; + + beforeEach((done) => { + createAndPopulateGroup({ + members: 3, + groupDetails: { + name: 'test guild', + type: 'guild', + privacy: 'public', + }, + }).then((res) => { + user = res.members[0]; + api = requester(user); + group = res.group; + done(); + }).catch(done); + }); + + it('leaves the group', (done) => { + api.post(`/groups/${group._id}/leave`).then((result) => { + return api.get(`/groups/${group._id}`); + }).then((group) => { + expect(group.members).to.not.include(user._id); + done(); + }).catch(done); + }); + }); + + context('user is the last member of a public guild', () => { + let api, user, group; + + beforeEach((done) => { + createAndPopulateGroup({ + groupDetails: { + name: 'test guild', + type: 'guild', + privacy: 'public', + }, + }).then((res) => { + user = res.leader; + api = requester(user); + group = res.group; + done(); + }).catch(done); + }); + + it('leaves the group accessible', (done) => { + api.post(`/groups/${group._id}/leave`).then((result) => { + return api.get(`/groups/${group._id}`); + }).then((group) => { + expect(group._id).to.eql(group._id); + done(); + }).catch(done); + }); + }); + + context('user is the last member of a private group', () => { + let api, user, group; + + beforeEach((done) => { + createAndPopulateGroup({ + groupDetails: { + name: 'test guild', + type: 'guild', + privacy: 'private', + }, + }).then((res) => { + user = res.leader; + api = requester(user); + group = res.group; + done(); + }).catch(done); + }); + + it('group is not accessible after leaving', (done) => { + api.post(`/groups/${group._id}/leave`).then((result) => { + return api.get(`/groups/${group._id}`); + }).then(done).catch((err) => { + expect(err.code).to.eql(404); + expect(err.text).to.eql('Group not found or you don\'t have access.'); + done(); + }); + }); + }); + + context('user is the last member of a private group with pending invites', () => { + let api, user, inviteeRequest1, inviteeRequest2, group; + + beforeEach((done) => { + createAndPopulateGroup({ + invites: 2, + groupDetails: { + name: 'test guild', + type: 'guild', + privacy: 'private', + }, + }).then((res) => { + user = res.leader; + inviteeRequest1 = requester(res.invitees[0]); + inviteeRequest2 = requester(res.invitees[1]); + api = requester(user); + group = res.group; + done(); + }).catch(done); + }); + + xit('@TODO: private guilds are not being deleted. Figure out why. deletes the group invitations from users', (done) => { + api.post(`/groups/${group._id}/leave`).then((result) => { + return Promise.all([ + inviteeRequest1.get(`/user`), + inviteeRequest2.get(`/user`), + ]); + }).then((users) => { + expect(users[0].invitations.guilds[0]).to.not.exist; + expect(users[1].invitations.guilds[0]).to.not.exist; + done(); + }).catch(done); + }); + }); + + context('user is the last member of a party with pending invites', () => { + let api, user, inviteeRequest1, inviteeRequest2, group; + + beforeEach((done) => { + createAndPopulateGroup({ + invites: 2, + groupDetails: { + name: 'test party', + type: 'party', + privacy: 'private', + }, + }).then((res) => { + user = res.leader; + inviteeRequest1 = requester(res.invitees[0]); + inviteeRequest2 = requester(res.invitees[1]); + api = requester(user); + group = res.group; + done(); + }).catch(done); + }); + + xit('@TODO: private guilds are not being deleted. Figure out why. deletes the group invitations from users', (done) => { + api.post(`/groups/${group._id}/leave`).then((result) => { + return Promise.all([ + inviteeRequest1.get(`/user`), + inviteeRequest2.get(`/user`), + ]); + }).then((users) => { + expect(users[0].invitations.party).to.be.empty; + expect(users[1].invitations.party).to.be.empty; + done(); + }).catch(done); + }); + }); +}); diff --git a/test/helpers/api.helper.js b/test/helpers/api.helper.js index 546e21a234..4c6d35b16a 100644 --- a/test/helpers/api.helper.js +++ b/test/helpers/api.helper.js @@ -1,6 +1,8 @@ import { assign, + each, isEmpty, + times, } from 'lodash'; import {MongoClient as mongo} from 'mongodb'; import {v4 as generateUUID} from 'uuid'; @@ -50,6 +52,69 @@ export function generateGroup(leader, update={}) { }); }; +export function createAndPopulateGroup(settings={}) { + let request, leader, members, invitees, group; + + let numberOfMembers = settings.members || 0; + let numberOfInvites = settings.invites || 0; + let groupDetails = settings.groupDetails; + let leaderDetails = settings.leaderDetails || { balance: 10 }; + + let leaderPromise = generateUser(leaderDetails); + + let memberPromises = Promise.all( + times(numberOfMembers, () => { + return generateUser(); + }) + ); + + let invitePromises = Promise.all( + times(numberOfInvites, () => { + return generateUser(); + }) + ); + + return new Promise((resolve, reject) => { + return leaderPromise.then((user) => { + leader = user; + request = _requestMaker(leader, 'post'); + return memberPromises; + }).then((users) => { + members = users; + groupDetails.members = groupDetails.members || []; + + each(members, (member) => { + groupDetails.members.push(member._id); + }); + + return generateGroup(leader, groupDetails); + }).then((createdGroup) => { + group = createdGroup; + return invitePromises; + }).then((users) => { + invitees = users; + + let invitePromises = []; + + each(invitees, (invitee) => { + let invitePromise = request(`/groups/${group._id}/invite`, { + uuids: [invitee._id] + }); + invitePromises.push(invitePromise); + }); + + return Promise.all(invitePromises); + }).then((inviteResults) => { + resolve({ + leader: leader, + group: group, + members: members, + invitees: invitees, + }); + }).catch(reject); + }); +}; + export function resetHabiticaDB() { return new Promise((resolve, reject) => { mongo.connect('mongodb://localhost/habitrpg_test', (err, db) => {