e9e4265545
commit 00affb306655a543f5d29b3af6361e686b577a97 Author: SabreCat <sabe@habitica.com> Date: Tue May 2 09:47:25 2023 -0500 fix(tests): account for invite limit changes commit 47661117f9fd661b8bc8f63b7cc7c8d5f8fa0fd7 Author: SabreCat <sabe@habitica.com> Date: Mon May 1 17:39:29 2023 -0500 fix(lfp): final polish commit 6a1e5af1db0dd90be3ced7e223f53c9183a206f5 Merge: 728ed2ddad9e0777bb42Author: SabreCat <sabe@habitica.com> Date: Mon May 1 16:54:12 2023 -0500 Merge branch 'release' into sabrecat/party-seeking commit 728ed2ddad7f0962d28f1ab0a271e3555b19296c Author: SabreCat <sabe@habitica.com> Date: Thu Apr 27 16:51:06 2023 -0500 fix(lfp): loading layout and page visit event commit 8a56ab329bff922e05963e3ef78fbc26ff273924 Author: SabreCat <sabe@habitica.com> Date: Wed Apr 26 16:54:46 2023 -0500 fix(faq): copy and style updates commit 6fd00d7f30150a1802e5a37edbb914ef120caf9a Author: SabreCat <sabe@habitica.com> Date: Fri Apr 21 17:12:52 2023 -0500 feat(lfp): fixes, analytics, FAQ commit 4b5d7304ad7cfc5f72320b23456ed2898e53caac Author: SabreCat <sabe@habitica.com> Date: Mon Apr 17 15:13:03 2023 -0500 fix(lfp): smol tweaks commit 9a5476a2558eb17a603f4aae1b5b2d35773be8b4 Author: SabreCat <sabe@habitica.com> Date: Thu Apr 13 16:03:33 2023 -0500 feat(lfp): refresh button commit aa58f5018469f38a9a9d31c3bffa26bb88a8c672 Merge: bbb03d006ec8adf20804Author: SabreCat <sabe@habitica.com> Date: Tue Apr 11 17:44:56 2023 -0500 Merge branch 'release' into sabrecat/party-seeking commit bbb03d006e8b122bb7206bdc778a31de422167bb Author: SabreCat <sabe@habitica.com> Date: Tue Apr 4 18:30:50 2023 -0500 fix(lint): whitespace and const commit 23683ad29a4cce0b0da061ad6c030982034c0a9c Author: SabreCat <sabe@habitica.com> Date: Tue Apr 4 17:02:57 2023 -0500 chore(LFP): add analytics also re-fix loading state commit 4477d84f5266c87f5583368029b72153f00f0568 Author: SabreCat <sabe@habitica.com> Date: Mon Apr 3 16:24:26 2023 -0500 fix(LFP): address issues with loading commit bdc5154f24bb5e50963376c3c0c9cc73c0b05ccc Merge: 81923eef6f229ed46425Author: SabreCat <sabe@habitica.com> Date: Mon Apr 3 15:58:12 2023 -0500 Merge branch 'release' into sabrecat/party-seeking commit 81923eef6f0c627d079475a28f9d93d8e4628934 Author: SabreCat <sabe@habitica.com> Date: Thu Mar 30 16:44:49 2023 -0500 feat(LFP): release candidate commit fe1f8939fc6b09d36cfaf0b6e5838df04e41009d Author: SabreCat <sabe@habitica.com> Date: Wed Mar 29 17:35:54 2023 -0500 WIP(LFP): fixes commit afc361f5a9f806cbd814ad910d1274e3a6609efd Merge: d6b5cbdebc7ede3acd01Author: SabreCat <sabe@habitica.com> Date: Wed Mar 29 16:24:39 2023 -0500 Merge branch 'release' into sabrecat/party-seeking commit d6b5cbdebc2829e9325ea57fb5deeccc128c1635 Author: SabreCat <sabe@habitica.com> Date: Tue Mar 28 16:13:18 2023 -0500 WIP(LFP): change copy, add close X, fix API response commit 4274a4625862351ef0ecf33c8a3249ca5ebec7cb Author: SabreCat <sabe@habitica.com> Date: Mon Mar 27 17:07:36 2023 -0500 fix(LFP): layout, unset when stopping commit 95abfcfa5f13c9cce6385206947a47f85b76d11d Merge: 4a360eedd853c536b525Author: SabreCat <sabe@habitica.com> Date: Mon Mar 27 16:32:46 2023 -0500 Merge branch 'release' into sabrecat/party-seeking commit 4a360eedd8b9cf41d3a0fe7a4cfaa72c5bd7bd26 Author: SabreCat <sabe@habitica.com> Date: Thu Mar 23 16:54:49 2023 -0500 feat(LFP): completed style and infinite scroll commit bbc439d9d03c9631a450236eb33af66f0428fa50 Author: SabreCat <sabe@habitica.com> Date: Tue Mar 21 10:40:26 2023 -0500 WIP(LFP): nicer layout, buffs fix commit 1658688597456663477ab19da61ae1b9bc85cf2a Merge: 664507434f027e61a93eAuthor: SabreCat <sabe@habitica.com> Date: Tue Mar 21 09:29:02 2023 -0500 Merge branch 'release' into sabrecat/party-seeking commit 664507434f2f76e6bf3b61cdc9e3daddb81204af Author: SabreCat <sabe@habitica.com> Date: Fri Mar 17 17:13:08 2023 -0500 WIP(LFP): API and client adjustments commit 2f0b6f2517f9e2d634cb23ee303cfb4542e998ce Merge: 0db1704325a16098ccdaAuthor: SabreCat <sabe@habitica.com> Date: Fri Mar 17 16:45:13 2023 -0500 Merge branch 'release' into sabrecat/party-seeking commit 0db1704325c3555f0b5d9c8d1dfc44177e90c093 Author: SabreCat <sabe@habitica.com> Date: Mon Mar 13 14:48:10 2023 -0500 fix(modal): scrollbar for squashed viewports commit 733c35192e0a4e31e1bebfdd7488cfc1f7587f36 Author: SabreCat <sabe@habitica.com> Date: Thu Mar 9 12:51:02 2023 -0600 WIP(party): seekers functional rough commit d4b854410b557db26eec6e6a26b6d174c02cee3a Merge: 7fe919825a0b6b967753Author: SabreCat <sabe@habitica.com> Date: Thu Mar 9 10:07:28 2023 -0600 Merge branch 'release' into sabrecat/party-seeking commit 7fe919825abfb6d518cb93b91f5997d3831bd0b5 Author: SabreCat <sabe@habitica.com> Date: Thu Mar 2 14:40:09 2023 -0600 feat(party): several adjustments to seeking feature commit c93900efcf925f7aaa4c4cb56b4451f19adfb1b3 Author: SabreCat <sabe@habitica.com> Date: Wed Mar 1 20:37:11 2023 -0600 feat(party): initial Seeking API commit 8bb784daeceb14c23992a6f3af1054a900fc26c1 Merge: e19a661a21f327795761Author: SabreCat <sabe@habitica.com> Date: Wed Mar 1 18:58:20 2023 -0600 Merge branch 'release' into sabrecat/party-seeking commit e19a661a2163a50307a286379bffb44201ed392e Author: SabreCat <sabe@habitica.com> Date: Fri Feb 24 15:51:42 2023 -0600 WIP(parties): add seeking flag and modal toggle
677 lines
22 KiB
JavaScript
677 lines
22 KiB
JavaScript
import { v4 as generateUUID } from 'uuid';
|
|
import nconf from 'nconf';
|
|
import {
|
|
createAndPopulateGroup,
|
|
generateUser,
|
|
generateGroup,
|
|
translate as t,
|
|
} from '../../../../helpers/api-integration/v3';
|
|
|
|
const INVITES_LIMIT = 100;
|
|
const PARTY_LIMIT_MEMBERS = 29;
|
|
const MAX_EMAIL_INVITES_BY_USER = 200;
|
|
|
|
describe('Post /groups/:groupId/invite', () => {
|
|
let inviter;
|
|
let group;
|
|
const groupName = 'Test Public Guild';
|
|
|
|
beforeEach(async () => {
|
|
inviter = await generateUser({ balance: 4 });
|
|
group = await inviter.post('/groups', {
|
|
name: groupName,
|
|
type: 'guild',
|
|
});
|
|
});
|
|
|
|
describe('username invites', () => {
|
|
it('returns an error when invited user is not found', async () => {
|
|
const fakeID = 'fakeuserid';
|
|
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
usernames: [fakeID],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 404,
|
|
error: 'NotFound',
|
|
message: t('userWithUsernameNotFound', { username: fakeID }),
|
|
});
|
|
});
|
|
|
|
it('returns an error when inviting yourself to a group', async () => {
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
usernames: [inviter.auth.local.lowerCaseUsername],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: t('cannotInviteSelfToGroup'),
|
|
});
|
|
});
|
|
|
|
it('returns error when recipient has blocked the senders', async () => {
|
|
const inviterNoBlocks = await inviter.update({ 'inbox.blocks': [] });
|
|
const userWithBlockedInviter = await generateUser({ 'inbox.blocks': [inviter._id] });
|
|
await expect(inviterNoBlocks.post(`/groups/${group._id}/invite`, {
|
|
usernames: [userWithBlockedInviter.auth.local.lowerCaseUsername],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 401,
|
|
error: 'NotAuthorized',
|
|
message: t('notAuthorizedToSendMessageToThisUser'),
|
|
});
|
|
});
|
|
|
|
it('invites a user to a group by username', async () => {
|
|
const userToInvite = await generateUser();
|
|
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
usernames: [userToInvite.auth.local.lowerCaseUsername],
|
|
})).to.eventually.deep.equal([{
|
|
id: group._id,
|
|
name: groupName,
|
|
inviter: inviter._id,
|
|
publicGuild: false,
|
|
}]);
|
|
|
|
await expect(userToInvite.get('/user'))
|
|
.to.eventually.have.nested.property('invitations.guilds[0].id', group._id);
|
|
});
|
|
|
|
it('invites multiple users to a group by uuid', async () => {
|
|
const userToInvite = await generateUser();
|
|
const userToInvite2 = await generateUser();
|
|
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
usernames: [
|
|
userToInvite.auth.local.lowerCaseUsername,
|
|
userToInvite2.auth.local.lowerCaseUsername,
|
|
],
|
|
})).to.eventually.deep.equal([
|
|
{
|
|
id: group._id,
|
|
name: groupName,
|
|
inviter: inviter._id,
|
|
publicGuild: false,
|
|
},
|
|
{
|
|
id: group._id,
|
|
name: groupName,
|
|
inviter: inviter._id,
|
|
publicGuild: false,
|
|
},
|
|
]);
|
|
|
|
await expect(userToInvite.get('/user')).to.eventually.have.nested.property('invitations.guilds[0].id', group._id);
|
|
await expect(userToInvite2.get('/user')).to.eventually.have.nested.property('invitations.guilds[0].id', group._id);
|
|
});
|
|
});
|
|
|
|
describe('user id invites', () => {
|
|
it('returns an error when inviter has no chat privileges', async () => {
|
|
const inviterMuted = await inviter.update({ 'flags.chatRevoked': true });
|
|
const userToInvite = await generateUser();
|
|
await expect(inviterMuted.post(`/groups/${group._id}/invite`, {
|
|
uuids: [userToInvite._id],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 401,
|
|
error: 'NotAuthorized',
|
|
message: t('chatPrivilegesRevoked'),
|
|
});
|
|
});
|
|
|
|
it('returns an error when invited user is not found', async () => {
|
|
const fakeID = generateUUID();
|
|
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
uuids: [fakeID],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 404,
|
|
error: 'NotFound',
|
|
message: t('userWithIDNotFound', { userId: fakeID }),
|
|
});
|
|
});
|
|
|
|
it('returns an error when inviting yourself to a group', async () => {
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
uuids: [inviter._id],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: t('cannotInviteSelfToGroup'),
|
|
});
|
|
});
|
|
|
|
it('returns an error when uuids is not an array', async () => {
|
|
const fakeID = generateUUID();
|
|
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
uuids: { fakeID },
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: t('uuidsMustBeAnArray'),
|
|
});
|
|
});
|
|
|
|
it('returns an error when uuids and emails are empty', async () => {
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
emails: [],
|
|
uuids: [],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: t('inviteMustNotBeEmpty'),
|
|
});
|
|
});
|
|
|
|
it('returns an error when uuids is empty and emails is not passed', async () => {
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
uuids: [],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: t('inviteMustNotBeEmpty'),
|
|
});
|
|
});
|
|
|
|
it('returns an error when there are more than INVITES_LIMIT uuids', async () => {
|
|
const uuids = [];
|
|
|
|
for (let i = 0; i < 101; i += 1) {
|
|
uuids.push(generateUUID());
|
|
}
|
|
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
uuids,
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: t('canOnlyInviteMaxInvites', { maxInvites: INVITES_LIMIT }),
|
|
});
|
|
});
|
|
|
|
it('returns error when recipient has blocked the senders', async () => {
|
|
const inviterNoBlocks = await inviter.update({ 'inbox.blocks': [] });
|
|
const userWithBlockedInviter = await generateUser({ 'inbox.blocks': [inviter._id] });
|
|
await expect(inviterNoBlocks.post(`/groups/${group._id}/invite`, {
|
|
uuids: [userWithBlockedInviter._id],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 401,
|
|
error: 'NotAuthorized',
|
|
message: t('notAuthorizedToSendMessageToThisUser'),
|
|
});
|
|
});
|
|
|
|
it('invites a user to a group by uuid', async () => {
|
|
const userToInvite = await generateUser();
|
|
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
uuids: [userToInvite._id],
|
|
})).to.eventually.deep.equal([{
|
|
id: group._id,
|
|
name: groupName,
|
|
inviter: inviter._id,
|
|
publicGuild: false,
|
|
}]);
|
|
|
|
await expect(userToInvite.get('/user'))
|
|
.to.eventually.have.nested.property('invitations.guilds[0].id', group._id);
|
|
});
|
|
|
|
it('invites multiple users to a group by uuid', async () => {
|
|
const userToInvite = await generateUser();
|
|
const userToInvite2 = await generateUser();
|
|
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
uuids: [userToInvite._id, userToInvite2._id],
|
|
})).to.eventually.deep.equal([
|
|
{
|
|
id: group._id,
|
|
name: groupName,
|
|
inviter: inviter._id,
|
|
publicGuild: false,
|
|
},
|
|
{
|
|
id: group._id,
|
|
name: groupName,
|
|
inviter: inviter._id,
|
|
publicGuild: false,
|
|
},
|
|
]);
|
|
|
|
await expect(userToInvite.get('/user')).to.eventually.have.nested.property('invitations.guilds[0].id', group._id);
|
|
await expect(userToInvite2.get('/user')).to.eventually.have.nested.property('invitations.guilds[0].id', group._id);
|
|
});
|
|
|
|
it('returns an error when inviting multiple users and a user is not found', async () => {
|
|
const userToInvite = await generateUser();
|
|
const fakeID = generateUUID();
|
|
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
uuids: [userToInvite._id, fakeID],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 404,
|
|
error: 'NotFound',
|
|
message: t('userWithIDNotFound', { userId: fakeID }),
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('email invites', () => {
|
|
const testInvite = { name: 'test', email: 'test@habitica.com' };
|
|
|
|
it('returns an error when inviter has no chat privileges', async () => {
|
|
const inviterMuted = await inviter.update({ 'flags.chatRevoked': true });
|
|
await expect(inviterMuted.post(`/groups/${group._id}/invite`, {
|
|
emails: [testInvite],
|
|
inviter: 'inviter name',
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 401,
|
|
error: 'NotAuthorized',
|
|
message: t('chatPrivilegesRevoked'),
|
|
});
|
|
});
|
|
|
|
it('returns an error when invite is missing an email', async () => {
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
emails: [{ name: 'test' }],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: t('inviteMissingEmail'),
|
|
});
|
|
});
|
|
|
|
it('returns an error when emails is not an array', async () => {
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
emails: { testInvite },
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: t('emailsMustBeAnArray'),
|
|
});
|
|
});
|
|
|
|
it('returns an error when emails is empty and uuids is not passed', async () => {
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
emails: [],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: t('inviteMustNotBeEmpty'),
|
|
});
|
|
});
|
|
|
|
it('returns an error when there are more than INVITES_LIMIT emails', async () => {
|
|
const emails = [];
|
|
|
|
for (let i = 0; i < 101; i += 1) {
|
|
emails.push(`${generateUUID()}@habitica.com`);
|
|
}
|
|
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
emails,
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: t('canOnlyInviteMaxInvites', { maxInvites: INVITES_LIMIT }),
|
|
});
|
|
});
|
|
|
|
it('returns an error when a user has sent the max number of email invites', async () => {
|
|
const inviterWithMax = await generateUser({
|
|
invitesSent: MAX_EMAIL_INVITES_BY_USER,
|
|
balance: 4,
|
|
});
|
|
const tmpGroup = await inviterWithMax.post('/groups', {
|
|
name: groupName,
|
|
type: 'guild',
|
|
});
|
|
|
|
await expect(inviterWithMax.post(`/groups/${tmpGroup._id}/invite`, {
|
|
emails: [testInvite],
|
|
inviter: 'inviter name',
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 401,
|
|
error: 'NotAuthorized',
|
|
message: t('inviteLimitReached', { techAssistanceEmail: nconf.get('EMAILS_TECH_ASSISTANCE_EMAIL') }),
|
|
});
|
|
});
|
|
|
|
it('invites a user to a group by email', async () => {
|
|
const res = await inviter.post(`/groups/${group._id}/invite`, {
|
|
emails: [testInvite],
|
|
inviter: 'inviter name',
|
|
});
|
|
|
|
const updatedUser = await inviter.sync();
|
|
|
|
expect(res).to.exist;
|
|
expect(updatedUser.invitesSent).to.eql(1);
|
|
});
|
|
|
|
it('invites multiple users to a group by email', async () => {
|
|
const res = await inviter.post(`/groups/${group._id}/invite`, {
|
|
emails: [testInvite, { name: 'test2', email: 'test2@habitica.com' }],
|
|
});
|
|
|
|
const updatedUser = await inviter.sync();
|
|
|
|
expect(res).to.exist;
|
|
expect(updatedUser.invitesSent).to.eql(2);
|
|
});
|
|
});
|
|
|
|
describe('user and email invites', () => {
|
|
it('returns an error when emails and uuids are not provided', async () => {
|
|
await expect(inviter.post(`/groups/${group._id}/invite`))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: t('canOnlyInviteEmailUuid'),
|
|
});
|
|
});
|
|
|
|
it('returns an error when there are more than INVITES_LIMIT uuids and emails', async () => {
|
|
const emails = [];
|
|
const uuids = [];
|
|
|
|
for (let i = 0; i < 50; i += 1) {
|
|
emails.push(`${generateUUID()}@habitica.com`);
|
|
}
|
|
|
|
for (let i = 0; i < 51; i += 1) {
|
|
uuids.push(generateUUID());
|
|
}
|
|
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
emails,
|
|
uuids,
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: t('canOnlyInviteMaxInvites', { maxInvites: INVITES_LIMIT }),
|
|
});
|
|
});
|
|
|
|
it('invites users to a group by uuid and email', async () => {
|
|
const newUser = await generateUser();
|
|
const invite = await inviter.post(`/groups/${group._id}/invite`, {
|
|
uuids: [newUser._id],
|
|
emails: [{ name: 'test', email: 'test@habitica.com' }],
|
|
});
|
|
const invitedUser = await newUser.get('/user');
|
|
|
|
expect(invitedUser.invitations.guilds[0].id).to.equal(group._id);
|
|
expect(invite).to.exist;
|
|
});
|
|
|
|
it('invites marks invite with cancelled plan', async () => {
|
|
const cancelledPlanGroup = await generateGroup(inviter, {
|
|
type: 'guild',
|
|
name: generateUUID(),
|
|
});
|
|
await cancelledPlanGroup.createCancelledSubscription();
|
|
|
|
const newUser = await generateUser();
|
|
const invite = await inviter.post(`/groups/${cancelledPlanGroup._id}/invite`, {
|
|
uuids: [newUser._id],
|
|
emails: [{ name: 'test', email: 'test@habitica.com' }],
|
|
});
|
|
const invitedUser = await newUser.get('/user');
|
|
|
|
expect(invitedUser.invitations.guilds[0].id).to.equal(cancelledPlanGroup._id);
|
|
expect(invitedUser.invitations.guilds[0].cancelledPlan).to.be.true;
|
|
expect(invite).to.exist;
|
|
});
|
|
});
|
|
|
|
describe('guild invites', () => {
|
|
it('returns an error when inviter has no chat privileges', async () => {
|
|
const inviterMuted = await inviter.update({ 'flags.chatRevoked': true });
|
|
const userToInvite = await generateUser();
|
|
await expect(inviterMuted.post(`/groups/${group._id}/invite`, {
|
|
uuids: [userToInvite._id],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 401,
|
|
error: 'NotAuthorized',
|
|
message: t('chatPrivilegesRevoked'),
|
|
});
|
|
});
|
|
|
|
it('returns an error when invited user is already invited to the group', async () => {
|
|
const userToInvite = await generateUser();
|
|
await inviter.post(`/groups/${group._id}/invite`, {
|
|
uuids: [userToInvite._id],
|
|
});
|
|
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
uuids: [userToInvite._id],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 401,
|
|
error: 'NotAuthorized',
|
|
message: t('userAlreadyInvitedToGroup', { userId: userToInvite._id, username: userToInvite.profile.name }),
|
|
});
|
|
});
|
|
|
|
it('returns an error when invited user is already in the group', async () => {
|
|
const userToInvite = await generateUser();
|
|
await inviter.post(`/groups/${group._id}/invite`, {
|
|
uuids: [userToInvite._id],
|
|
});
|
|
await userToInvite.post(`/groups/${group._id}/join`);
|
|
|
|
await expect(inviter.post(`/groups/${group._id}/invite`, {
|
|
uuids: [userToInvite._id],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 401,
|
|
error: 'NotAuthorized',
|
|
message: t('userAlreadyInGroup', { userId: userToInvite._id, username: userToInvite.profile.name }),
|
|
});
|
|
});
|
|
|
|
it('allows 30+ members in a guild', async () => {
|
|
const invitesToGenerate = [];
|
|
// Generate 30 users to invite (30 + leader = 31 members)
|
|
for (let i = 0; i < PARTY_LIMIT_MEMBERS; i += 1) {
|
|
invitesToGenerate.push(generateUser());
|
|
}
|
|
const generatedInvites = await Promise.all(invitesToGenerate);
|
|
// Invite users
|
|
expect(await inviter.post(`/groups/${group._id}/invite`, {
|
|
uuids: generatedInvites.map(invite => invite._id),
|
|
})).to.be.an('array');
|
|
}).timeout(10000);
|
|
|
|
// @TODO: Add this after we are able to mock the group plan route
|
|
xit('returns an error when a non-leader invites to a group plan', async () => {
|
|
const userToInvite = await generateUser();
|
|
|
|
const nonGroupLeader = await generateUser();
|
|
await inviter.post(`/groups/${group._id}/invite`, {
|
|
uuids: [nonGroupLeader._id],
|
|
});
|
|
await nonGroupLeader.post(`/groups/${group._id}/join`);
|
|
|
|
await expect(nonGroupLeader.post(`/groups/${group._id}/invite`, {
|
|
uuids: [userToInvite._id],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 401,
|
|
error: 'NotAuthorized',
|
|
message: t('onlyGroupLeaderCanInviteToGroupPlan'),
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('party invites', () => {
|
|
let party;
|
|
|
|
beforeEach(async () => {
|
|
party = await inviter.post('/groups', {
|
|
name: 'Test Party',
|
|
type: 'party',
|
|
});
|
|
});
|
|
|
|
it('returns an error when inviter has no chat privileges', async () => {
|
|
const inviterMuted = await inviter.update({ 'flags.chatRevoked': true });
|
|
const userToInvite = await generateUser();
|
|
await expect(inviterMuted.post(`/groups/${party._id}/invite`, {
|
|
uuids: [userToInvite._id],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 401,
|
|
error: 'NotAuthorized',
|
|
message: t('chatPrivilegesRevoked'),
|
|
});
|
|
});
|
|
|
|
it('returns an error when invited user has a pending invitation to the party', async () => {
|
|
const userToInvite = await generateUser();
|
|
await inviter.post(`/groups/${party._id}/invite`, {
|
|
uuids: [userToInvite._id],
|
|
});
|
|
|
|
await expect(inviter.post(`/groups/${party._id}/invite`, {
|
|
uuids: [userToInvite._id],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 401,
|
|
error: 'NotAuthorized',
|
|
message: t('userAlreadyPendingInvitation', { userId: userToInvite._id, username: userToInvite.profile.name }),
|
|
});
|
|
});
|
|
|
|
it('returns an error when invited user is already in a party of more than 1 member', async () => {
|
|
const userToInvite = await generateUser();
|
|
const userToInvite2 = await generateUser();
|
|
await inviter.post(`/groups/${party._id}/invite`, {
|
|
uuids: [userToInvite._id, userToInvite2._id],
|
|
});
|
|
await userToInvite.post(`/groups/${party._id}/join`);
|
|
await userToInvite2.post(`/groups/${party._id}/join`);
|
|
|
|
await expect(inviter.post(`/groups/${party._id}/invite`, {
|
|
uuids: [userToInvite._id],
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 401,
|
|
error: 'NotAuthorized',
|
|
message: t('userAlreadyInAParty', { userId: userToInvite._id, username: userToInvite.profile.name }),
|
|
});
|
|
});
|
|
|
|
it('allows inviting a user to 2 different parties', async () => {
|
|
// Create another inviter
|
|
const inviter2 = await generateUser();
|
|
|
|
// Create user to invite
|
|
const userToInvite = await generateUser();
|
|
|
|
// Create second group
|
|
const party2 = await inviter2.post('/groups', {
|
|
name: 'Test Party 2',
|
|
type: 'party',
|
|
});
|
|
|
|
// Invite to first party
|
|
await inviter.post(`/groups/${party._id}/invite`, {
|
|
uuids: [userToInvite._id],
|
|
});
|
|
|
|
// Invite to second party
|
|
await inviter2.post(`/groups/${party2._id}/invite`, {
|
|
uuids: [userToInvite._id],
|
|
});
|
|
|
|
// Get updated user
|
|
const invitedUser = await userToInvite.get('/user');
|
|
|
|
expect(invitedUser.invitations.parties.length).to.equal(2);
|
|
expect(invitedUser.invitations.parties[0].id).to.equal(party._id);
|
|
expect(invitedUser.invitations.parties[1].id).to.equal(party2._id);
|
|
});
|
|
|
|
it('allow inviting a user if party id is not associated with a real party', async () => {
|
|
const userToInvite = await generateUser({
|
|
party: { _id: generateUUID() },
|
|
});
|
|
|
|
await inviter.post(`/groups/${party._id}/invite`, {
|
|
uuids: [userToInvite._id],
|
|
});
|
|
expect((await userToInvite.get('/user')).invitations.parties[0].id).to.equal(party._id);
|
|
});
|
|
});
|
|
|
|
describe('party size limits', () => {
|
|
let party, partyLeader;
|
|
|
|
beforeEach(async () => {
|
|
group = await createAndPopulateGroup({
|
|
groupDetails: {
|
|
name: 'Test Party',
|
|
type: 'party',
|
|
privacy: 'private',
|
|
},
|
|
// Generate party with 20 members
|
|
members: PARTY_LIMIT_MEMBERS - 10,
|
|
});
|
|
party = group.group;
|
|
partyLeader = group.groupLeader;
|
|
});
|
|
|
|
it('allows 30 members in a party', async () => {
|
|
const invitesToGenerate = [];
|
|
// Generate 10 new invites
|
|
for (let i = 1; i < 10; i += 1) {
|
|
invitesToGenerate.push(generateUser());
|
|
}
|
|
const generatedInvites = await Promise.all(invitesToGenerate);
|
|
// Invite users
|
|
expect(await partyLeader.post(`/groups/${party._id}/invite`, {
|
|
uuids: generatedInvites.map(invite => invite._id),
|
|
})).to.be.an('array');
|
|
}).timeout(10000);
|
|
|
|
it('does not allow >30 members in a party', async () => {
|
|
const invitesToGenerate = [];
|
|
// Generate 11 invites
|
|
for (let i = 1; i < 11; i += 1) {
|
|
invitesToGenerate.push(generateUser());
|
|
}
|
|
const generatedInvites = await Promise.all(invitesToGenerate);
|
|
// Invite users
|
|
await expect(partyLeader.post(`/groups/${party._id}/invite`, {
|
|
uuids: generatedInvites.map(invite => invite._id),
|
|
}))
|
|
.to.eventually.be.rejected.and.eql({
|
|
code: 400,
|
|
error: 'BadRequest',
|
|
message: t('partyExceedsMembersLimit', { maxMembersParty: PARTY_LIMIT_MEMBERS + 1 }),
|
|
});
|
|
}).timeout(10000);
|
|
});
|
|
});
|