Files
habitica/test/api/v3/integration/groups/POST-groups_invite.test.js
Keith Holliday be60fb0635 Group plans subs to all (#8394)
* Added subscriptions to all members when group subs

* Added unsub when group cancels

* Give user a subscription when they join a subbed group

* Removed subscription when user leaves or is removed from group

* Fixed linting issues:

* Added tests for users with a subscription being upgraded to group plan

* Added tests for checking if existing recurring user sub gets updated during group plan. Added better merging for plans

* Added test for existing gift subscriptions

* Added additional months to user when they have an existing recurring subscription and get upgraded to group sub

* Adds test for user who has cancelled with date termined in the future

* Added test to ensure date termined is reset

* Added tests for extra months carrying over

* Added test for gems bought field

* Add tests to for fields that should remain when upgrading

* Added test for all payment methods

* Added prevention for when a user joins a second group plan

* Fixed subscribing tests

* Separated group plan payment tests

* Added prevention of editing a user with a unlimited sub

* Add tests to ensure group keeps plan if they are in two and leave one

* Ensured users with two group plans do not get cancelled when on group plan is cancelled

* Ensured users without group sub are untouched when group cancels

* Fixed lint issues

* Added new emails

* Added fix for cron tests

* Add restore to stubbed methods

* Ensured cancelled group subscriptions are updated

* Changed group plan exist check to check for date terminated

* Updated you cannont delete active group message

* Removed description requirement

* Added upgrade group plan for Amazon payments

* Fixed lint issues

* Fixed broken tests

* Fixed user delete tests

* Fixed function calls

* Hid cancel button if user has group plan

* Hide difficulty from rewards

* Prevented add user functions to be called when group plan is cancelled

* Fixed merge issue

* Correctly displayed group price

* Added message when you are about to join canclled group plan

* Fixed linting issues

* Updated tests to have no redirect to homes

* Allowed leaving a group with a canceld subscription

* Fixed spelling issues

* Prevented user from changing leader with active sub

* Added payment details title to replace subscription title

* Ensured we do not count leader when displaying upcoming cost

* Prevented party tasks from being displayed twice

* Prevented cancelling and already cancelled sub

* Fixed styles of subscriptions

* Added more specific mystery item tests

* Fixed test to refer to leader

* Extended test range to account for short months

* Fixed merge conflicts

* Updated yarn file

* Added missing locales

* Trigger notification

* Removed yarn

* Fixed locales

* Fixed scope mispelling

* Fixed line endings

* Removed extra advanced options from rewards

* Prevent group leader from leaving an active group plan

* Fixed issue with extra months applied to cancelled group plan

* Ensured member count is calculated when updatedGroupPlan

* Updated amazon payment method constant name

* Added comment to cancel sub user method

* Fixed smantic issues

* Added unite test for user isSubscribed and hasNotCancelled

* Add tests for isSubscribed and hasNotCanceled

* Changed default days remaining to 2 days for group plans

* Fixed logic with adding canceled notice to group invite
2017-03-06 15:09:50 -07:00

415 lines
12 KiB
JavaScript

import {
generateUser,
generateGroup,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
import { v4 as generateUUID } from 'uuid';
const INVITES_LIMIT = 100;
describe('Post /groups/:groupId/invite', () => {
let inviter;
let group;
let groupName = 'Test Public Guild';
beforeEach(async () => {
inviter = await generateUser({balance: 4});
group = await inviter.post('/groups', {
name: groupName,
type: 'guild',
});
});
describe('user id invites', () => {
it('returns an error when invited user is not found', async () => {
let 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 () => {
let 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('inviteMissingUuid'),
});
});
it('returns an error when there are more than INVITES_LIMIT uuids', async () => {
let 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('invites a user to a group by uuid', async () => {
let 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,
}]);
await expect(userToInvite.get('/user'))
.to.eventually.have.deep.property('invitations.guilds[0].id', group._id);
});
it('invites multiple users to a group by uuid', async () => {
let userToInvite = await generateUser();
let 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,
},
{
id: group._id,
name: groupName,
inviter: inviter._id,
},
]);
await expect(userToInvite.get('/user')).to.eventually.have.deep.property('invitations.guilds[0].id', group._id);
await expect(userToInvite2.get('/user')).to.eventually.have.deep.property('invitations.guilds[0].id', group._id);
});
it('returns an error when inviting multiple users and a user is not found', async () => {
let userToInvite = await generateUser();
let 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', () => {
let testInvite = {name: 'test', email: 'test@habitica.com'};
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('inviteMissingEmail'),
});
});
it('returns an error when there are more than INVITES_LIMIT emails', async () => {
let 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('invites a user to a group by email', async () => {
let res = await inviter.post(`/groups/${group._id}/invite`, {
emails: [testInvite],
inviter: 'inviter name',
});
expect(res).to.exist;
});
it('invites multiple users to a group by email', async () => {
let res = await inviter.post(`/groups/${group._id}/invite`, {
emails: [testInvite, {name: 'test2', email: 'test2@habitica.com'}],
});
expect(res).to.exist;
});
});
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 () => {
let emails = [];
let 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 () => {
let newUser = await generateUser();
let invite = await inviter.post(`/groups/${group._id}/invite`, {
uuids: [newUser._id],
emails: [{name: 'test', email: 'test@habitica.com'}],
});
let 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 () => {
let cancelledPlanGroup = await generateGroup(inviter, {
type: 'guild',
name: generateUUID(),
});
await cancelledPlanGroup.createCancelledSubscription();
let newUser = await generateUser();
let invite = await inviter.post(`/groups/${cancelledPlanGroup._id}/invite`, {
uuids: [newUser._id],
emails: [{name: 'test', email: 'test@habitica.com'}],
});
let 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 invited user is already invited to the group', async () => {
let userToInivite = await generateUser();
await inviter.post(`/groups/${group._id}/invite`, {
uuids: [userToInivite._id],
});
await expect(inviter.post(`/groups/${group._id}/invite`, {
uuids: [userToInivite._id],
}))
.to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
message: t('userAlreadyInvitedToGroup'),
});
});
it('returns an error when invited user is already in the group', async () => {
let 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'),
});
});
// @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 () => {
let userToInvite = await generateUser();
let 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 invited user has a pending invitation to the party', async () => {
let 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'),
});
});
it('returns an error when invited user is already in a party of more than 1 member', async () => {
let userToInvite = await generateUser();
let 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'),
});
});
it('allow inviting a user to a party if they are partying solo', async () => {
let userToInvite = await generateUser();
await userToInvite.post('/groups', { // add user to a party
name: 'Another Test Party',
type: 'party',
});
await inviter.post(`/groups/${party._id}/invite`, {
uuids: [userToInvite._id],
});
expect((await userToInvite.get('/user')).invitations.party.id).to.equal(party._id);
});
it('allow inviting a user if party id is not associated with a real party', async () => {
let userToInvite = await generateUser({
party: { _id: generateUUID() },
});
await inviter.post(`/groups/${party._id}/invite`, {
uuids: [userToInvite._id],
});
expect((await userToInvite.get('/user')).invitations.party.id).to.equal(party._id);
});
});
});