Merge branch 'api-v3-groups' into sabrecat/quest-accept
This commit is contained in:
+5
-3
@@ -1,5 +1,7 @@
|
||||
# So you want to write API integration tests?
|
||||
|
||||
@TODO rewrite
|
||||
|
||||
That's great! This README will serve as a quick primer for style conventions and practices for these tests.
|
||||
|
||||
## What is this?
|
||||
@@ -73,7 +75,7 @@ POST-groups_id_leave.test.js
|
||||
To mitigate [callback hell](http://callbackhell.com/) :imp:, we've written a helper method to generate a user object that can make http requests that [return promises](https://babeljs.io/docs/learn-es2015/#promises). This makes it very easy to chain together commands. All you need to do to make a subsequent request is return another promise and then call `.then((result) => {})` on the surrounding block, like so:
|
||||
|
||||
```js
|
||||
it('does something', () => {
|
||||
it('does something', () => {
|
||||
let user;
|
||||
|
||||
return generateUser().then((_user) => { // We return the initial promise so this test can be run asyncronously
|
||||
@@ -97,7 +99,7 @@ it('does something', () => {
|
||||
If the test is simple, you can use the [chai-as-promised](http://chaijs.com/plugins/chai-as-promised) `return expect(somePromise).to.eventually` syntax to make your assertion.
|
||||
|
||||
```js
|
||||
it('makes the party creator the leader automatically', () => {
|
||||
it('makes the party creator the leader automatically', () => {
|
||||
return expect(user.post('/groups', {
|
||||
type: 'party',
|
||||
})).to.eventually.have.deep.property('leader._id', user._id);
|
||||
@@ -107,7 +109,7 @@ it('makes the party creator the leader automatically', () => {
|
||||
If the test is checking that the request returns an error, use the `.eventually.be.rejected.and.eql` syntax.
|
||||
|
||||
```js
|
||||
it('returns an error', () => {
|
||||
it('returns an error', () => {
|
||||
return expect(user.get('/groups/id-of-a-party-that-user-does-not-belong-to'))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# How to run tests:
|
||||
|
||||
1. `npm test` is equivalent to `gulp test:api-v3` which will run, in order, `gulp lint`, `gulp test:api-v3:unit` and `gulp test:api-v3:integration`. If one of these fails, the whole `npm test` command blocks and fails. Each of these commands can also be run as a standalone command.
|
||||
2. To run the server and the integrations tests in two different terminals (to better inspect the output in the server) run `npm start` in one and `npm test:api-v3:integration:separate-server` in the other
|
||||
@@ -0,0 +1,95 @@
|
||||
import {
|
||||
generateUser,
|
||||
generateChallenge,
|
||||
createAndPopulateGroup,
|
||||
sleep,
|
||||
checkExistence,
|
||||
translate as t,
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
import { v4 as generateUUID } from 'uuid';
|
||||
|
||||
describe('DELETE /challenges/:challengeId', () => {
|
||||
it('returns error when challengeId is not a valid UUID', async () => {
|
||||
let user = await generateUser();
|
||||
|
||||
await expect(user.del(`/challenges/test`)).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: t('invalidReqParams'),
|
||||
});
|
||||
});
|
||||
|
||||
it('returns error when challengeId is not for a valid challenge', async () => {
|
||||
let user = await generateUser();
|
||||
|
||||
await expect(user.del(`/challenges/${generateUUID()}`)).to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('challengeNotFound'),
|
||||
});
|
||||
});
|
||||
|
||||
context('Deleting a valid challenge', () => {
|
||||
let groupLeader;
|
||||
let group;
|
||||
let challenge;
|
||||
let taskText = 'A challenge task text';
|
||||
|
||||
beforeEach(async () => {
|
||||
let populatedGroup = await createAndPopulateGroup();
|
||||
|
||||
groupLeader = populatedGroup.groupLeader;
|
||||
group = populatedGroup.group;
|
||||
|
||||
challenge = await generateChallenge(groupLeader, group);
|
||||
|
||||
await groupLeader.post(`/tasks/challenge/${challenge._id}`, [
|
||||
{type: 'habit', text: taskText},
|
||||
]);
|
||||
|
||||
await challenge.sync();
|
||||
});
|
||||
|
||||
it('returns an error when user doesn\'t have permissions to delete the challenge', async () => {
|
||||
let user = await generateUser();
|
||||
|
||||
await expect(user.del(`/challenges/${challenge._id}`)).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('onlyLeaderDeleteChal'),
|
||||
});
|
||||
});
|
||||
|
||||
it('deletes challenge', async () => {
|
||||
await groupLeader.del(`/challenges/${challenge._id}`);
|
||||
|
||||
await sleep(0.5);
|
||||
|
||||
await expect(checkExistence('challenges', challenge._id)).to.eventually.equal(false);
|
||||
});
|
||||
|
||||
it('refunds gems to group leader', async () => {
|
||||
let oldBalance = (await groupLeader.sync()).balance;
|
||||
|
||||
await groupLeader.del(`/challenges/${challenge._id}`);
|
||||
|
||||
await sleep(0.5);
|
||||
|
||||
await expect(groupLeader.sync()).to.eventually.have.property('balance', oldBalance + challenge.prize / 4);
|
||||
});
|
||||
|
||||
it('sets broken and doesn\'t set winner flags for user\'s challenge tasks', async () => {
|
||||
await groupLeader.del(`/challenges/${challenge._id}`);
|
||||
|
||||
await sleep(0.5);
|
||||
|
||||
let tasks = await groupLeader.get('/tasks/user');
|
||||
let testTask = _.find(tasks, (task) => {
|
||||
return task.text === taskText;
|
||||
});
|
||||
|
||||
expect(testTask.challenge.broken).to.eql('CHALLENGE_DELETED');
|
||||
expect(testTask.challenge.winner).to.be.null;
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,71 @@
|
||||
import {
|
||||
generateUser,
|
||||
createAndPopulateGroup,
|
||||
generateChallenge,
|
||||
translate as t,
|
||||
sleep,
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
import { v4 as generateUUID } from 'uuid';
|
||||
|
||||
describe('GET /challenges/:challengeId/export/csv', () => {
|
||||
let groupLeader;
|
||||
let group;
|
||||
let challenge;
|
||||
let members;
|
||||
let user;
|
||||
|
||||
beforeEach(async () => {
|
||||
user = await generateUser();
|
||||
|
||||
let populatedGroup = await createAndPopulateGroup({
|
||||
members: 3,
|
||||
});
|
||||
|
||||
groupLeader = populatedGroup.groupLeader;
|
||||
group = populatedGroup.group;
|
||||
members = populatedGroup.members;
|
||||
|
||||
challenge = await generateChallenge(groupLeader, group);
|
||||
await members[0].post(`/challenges/${challenge._id}/join`);
|
||||
await members[1].post(`/challenges/${challenge._id}/join`);
|
||||
await members[2].post(`/challenges/${challenge._id}/join`);
|
||||
|
||||
await groupLeader.post(`/tasks/challenge/${challenge._id}`, [
|
||||
{type: 'habit', text: 'Task 1'},
|
||||
{type: 'todo', text: 'Task 2'},
|
||||
]);
|
||||
await sleep(0.5); // Make sure tasks are synced to the users
|
||||
await members[0].sync();
|
||||
await members[1].sync();
|
||||
await members[2].sync();
|
||||
});
|
||||
|
||||
it('fails if challenge doesn\'t exists', async () => {
|
||||
await expect(user.get(`/challenges/${generateUUID()}/export/csv`)).to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('challengeNotFound'),
|
||||
});
|
||||
});
|
||||
|
||||
it('fails if user doesn\'t have access to the challenge', async () => {
|
||||
await expect(user.get(`/challenges/${challenge._id}/export/csv`)).to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('challengeNotFound'),
|
||||
});
|
||||
});
|
||||
|
||||
it('should return a valid CSV file with export data', async () => {
|
||||
let res = await members[0].get(`/challenges/${challenge._id}/export/csv`);
|
||||
let sortedMembers = _.sortBy([members[0], members[1], members[2], groupLeader], '_id');
|
||||
let splitRes = res.split('\n');
|
||||
|
||||
expect(splitRes[0]).to.equal('UUID,name,Task,Value,Notes,Task,Value,Notes');
|
||||
expect(splitRes[1]).to.equal(`${sortedMembers[0]._id},${sortedMembers[0].profile.name},habit:Task 1,0,,todo:Task 2,0,`);
|
||||
expect(splitRes[2]).to.equal(`${sortedMembers[1]._id},${sortedMembers[1].profile.name},habit:Task 1,0,,todo:Task 2,0,`);
|
||||
expect(splitRes[3]).to.equal(`${sortedMembers[2]._id},${sortedMembers[2].profile.name},habit:Task 1,0,,todo:Task 2,0,`);
|
||||
expect(splitRes[4]).to.equal(`${sortedMembers[3]._id},${sortedMembers[3].profile.name},habit:Task 1,0,,todo:Task 2,0,`);
|
||||
expect(splitRes[5]).to.equal('');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,123 @@
|
||||
import {
|
||||
generateUser,
|
||||
generateChallenge,
|
||||
createAndPopulateGroup,
|
||||
translate as t,
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
import { v4 as generateUUID } from 'uuid';
|
||||
|
||||
describe('POST /challenges/:challengeId/leave', () => {
|
||||
it('returns error when challengeId is not a valid UUID', async () => {
|
||||
let user = await generateUser();
|
||||
|
||||
await expect(user.post('/challenges/test/leave')).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: t('invalidReqParams'),
|
||||
});
|
||||
});
|
||||
|
||||
it('returns error when challengeId is not for a valid challenge', async () => {
|
||||
let user = await generateUser();
|
||||
|
||||
await expect(user.post(`/challenges/${generateUUID()}/leave`)).to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('challengeNotFound'),
|
||||
});
|
||||
});
|
||||
|
||||
context('Leaving a valid challenge', () => {
|
||||
let groupLeader;
|
||||
let group;
|
||||
let challenge;
|
||||
let notInChallengeUser;
|
||||
let leavingUser;
|
||||
let taskText;
|
||||
|
||||
beforeEach(async () => {
|
||||
let populatedGroup = await createAndPopulateGroup({
|
||||
members: 2,
|
||||
});
|
||||
|
||||
groupLeader = populatedGroup.groupLeader;
|
||||
group = populatedGroup.group;
|
||||
leavingUser = populatedGroup.members[0];
|
||||
notInChallengeUser = populatedGroup.members[1];
|
||||
|
||||
challenge = await generateChallenge(groupLeader, group);
|
||||
|
||||
taskText = 'A challenge task text';
|
||||
|
||||
await groupLeader.post(`/tasks/challenge/${challenge._id}`, [
|
||||
{type: 'habit', text: taskText},
|
||||
]);
|
||||
|
||||
await leavingUser.post(`/challenges/${challenge._id}/join`);
|
||||
|
||||
await challenge.sync();
|
||||
});
|
||||
|
||||
it('returns an error when user doesn\'t have permissions to view the challenge', async () => {
|
||||
let unauthorizedUser = await generateUser();
|
||||
|
||||
await expect(unauthorizedUser.post(`/challenges/${challenge._id}/leave`)).to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('challengeNotFound'),
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an error when user isn\'t a member of the challenge', async () => {
|
||||
await expect(notInChallengeUser.post(`/challenges/${challenge._id}/leave`)).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('challengeMemberNotFound'),
|
||||
});
|
||||
});
|
||||
|
||||
it('removes challenge from user challenges', async () => {
|
||||
await leavingUser.post(`/challenges/${challenge._id}/leave`);
|
||||
|
||||
await leavingUser.sync();
|
||||
|
||||
expect(leavingUser).to.have.property('challenges').to.not.include(challenge._id);
|
||||
});
|
||||
|
||||
it('decreases memberCount of challenge', async () => {
|
||||
let oldMemberCount = challenge.memberCount;
|
||||
|
||||
await leavingUser.post(`/challenges/${challenge._id}/leave`);
|
||||
|
||||
await challenge.sync();
|
||||
|
||||
expect(challenge).to.have.property('memberCount', oldMemberCount - 1);
|
||||
});
|
||||
|
||||
it('unlinks challenge tasks from leaving user when remove-all is passed', async () => {
|
||||
await leavingUser.post(`/challenges/${challenge._id}/leave`, {
|
||||
keep: 'remove-all',
|
||||
});
|
||||
let tasks = await leavingUser.get('/tasks/user');
|
||||
let tasksTexts = tasks.map((task) => {
|
||||
return task.text;
|
||||
});
|
||||
|
||||
expect(tasksTexts).to.not.include(taskText);
|
||||
});
|
||||
|
||||
it('doesn\'t unlink challenge tasks from leaving user when remove-all isn\'t passed', async () => {
|
||||
await leavingUser.post(`/challenges/${challenge._id}/leave`, {
|
||||
keep: 'test',
|
||||
});
|
||||
|
||||
let tasks = await leavingUser.get('/tasks/user');
|
||||
let testTask = _.find(tasks, (task) => {
|
||||
return task.text === taskText;
|
||||
});
|
||||
|
||||
expect(testTask).to.not.be.undefined;
|
||||
expect(testTask.challenge).to.be.undefined;
|
||||
});
|
||||
});
|
||||
});
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
import {
|
||||
generateUser,
|
||||
generateChallenge,
|
||||
createAndPopulateGroup,
|
||||
sleep,
|
||||
checkExistence,
|
||||
translate as t,
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
import { v4 as generateUUID } from 'uuid';
|
||||
|
||||
describe('POST /challenges/:challengeId/winner/:winnerId', () => {
|
||||
it('returns error when challengeId is not a valid UUID', async () => {
|
||||
let user = await generateUser();
|
||||
|
||||
await expect(user.post(`/challenges/test/selectWinner/${user._id}`)).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: t('invalidReqParams'),
|
||||
});
|
||||
});
|
||||
|
||||
it('returns error when winnerId is not a valid UUID', async () => {
|
||||
let user = await generateUser();
|
||||
|
||||
await expect(user.post(`/challenges/${generateUUID()}/selectWinner/test`)).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: t('invalidReqParams'),
|
||||
});
|
||||
});
|
||||
|
||||
it('returns error when challengeId is not for a valid challenge', async () => {
|
||||
let user = await generateUser();
|
||||
|
||||
await expect(user.post(`/challenges/${generateUUID()}/selectWinner/${user._id}`)).to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('challengeNotFound'),
|
||||
});
|
||||
});
|
||||
|
||||
context('Selecting winner for a valid challenge', () => {
|
||||
let groupLeader;
|
||||
let group;
|
||||
let challenge;
|
||||
let winningUser;
|
||||
let taskText = 'A challenge task text';
|
||||
|
||||
beforeEach(async () => {
|
||||
let populatedGroup = await createAndPopulateGroup({
|
||||
members: 1,
|
||||
});
|
||||
|
||||
groupLeader = populatedGroup.groupLeader;
|
||||
group = populatedGroup.group;
|
||||
winningUser = populatedGroup.members[0];
|
||||
|
||||
challenge = await generateChallenge(groupLeader, group, {
|
||||
prize: 1,
|
||||
});
|
||||
|
||||
await groupLeader.post(`/tasks/challenge/${challenge._id}`, [
|
||||
{type: 'habit', text: taskText},
|
||||
]);
|
||||
|
||||
await winningUser.post(`/challenges/${challenge._id}/join`);
|
||||
|
||||
await challenge.sync();
|
||||
});
|
||||
|
||||
it('returns an error when user doesn\'t have permissions to select winner', async () => {
|
||||
await expect(winningUser.post(`/challenges/${challenge._id}/selectWinner/${winningUser._id}`)).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('onlyLeaderDeleteChal'),
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an error when winning user isn\'t part of the challenge', async () => {
|
||||
let notInChallengeUser = await generateUser();
|
||||
|
||||
await expect(groupLeader.post(`/challenges/${challenge._id}/selectWinner/${notInChallengeUser._id}`)).to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('winnerNotFound', {userId: notInChallengeUser._id}),
|
||||
});
|
||||
});
|
||||
|
||||
it('deletes challenge after winner is selected', async () => {
|
||||
await groupLeader.post(`/challenges/${challenge._id}/selectWinner/${winningUser._id}`);
|
||||
|
||||
await sleep(0.5);
|
||||
|
||||
await expect(checkExistence('challenges', challenge._id)).to.eventually.equal(false);
|
||||
});
|
||||
|
||||
it('adds challenge to winner\'s achievements', async () => {
|
||||
await groupLeader.post(`/challenges/${challenge._id}/selectWinner/${winningUser._id}`);
|
||||
|
||||
await sleep(0.5);
|
||||
|
||||
await expect(winningUser.sync()).to.eventually.have.deep.property('achievements.challenges').to.include(challenge.name);
|
||||
});
|
||||
|
||||
it('gives winner gems as reward', async () => {
|
||||
let oldBalance = winningUser.balance;
|
||||
|
||||
await groupLeader.post(`/challenges/${challenge._id}/selectWinner/${winningUser._id}`);
|
||||
|
||||
await sleep(0.5);
|
||||
|
||||
await expect(winningUser.sync()).to.eventually.have.property('balance', oldBalance + challenge.prize / 4);
|
||||
});
|
||||
|
||||
it('doesn\'t refund gems to group leader', async () => {
|
||||
let oldBalance = (await groupLeader.sync()).balance;
|
||||
|
||||
await groupLeader.post(`/challenges/${challenge._id}/selectWinner/${winningUser._id}`);
|
||||
|
||||
await sleep(0.5);
|
||||
|
||||
await expect(groupLeader.sync()).to.eventually.have.property('balance', oldBalance);
|
||||
});
|
||||
|
||||
it('sets broken and winner flags for user\'s challenge tasks', async () => {
|
||||
await groupLeader.post(`/challenges/${challenge._id}/selectWinner/${winningUser._id}`);
|
||||
|
||||
await sleep(0.5);
|
||||
|
||||
let tasks = await winningUser.get('/tasks/user');
|
||||
let testTask = _.find(tasks, (task) => {
|
||||
return task.text === taskText;
|
||||
});
|
||||
|
||||
expect(testTask.challenge.broken).to.eql('CHALLENGE_CLOSED');
|
||||
expect(testTask.challenge.winner).to.eql(winningUser.profile.name);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,76 @@
|
||||
import {
|
||||
generateUser,
|
||||
generateChallenge,
|
||||
createAndPopulateGroup,
|
||||
translate as t,
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
|
||||
describe('PUT /challenges/:challengeId', () => {
|
||||
let privateGuild, user, nonMember, challenge, member;
|
||||
|
||||
beforeEach(async () => {
|
||||
let { group, groupLeader, members } = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
name: 'TestPrivateGuild',
|
||||
type: 'guild',
|
||||
privacy: 'private',
|
||||
},
|
||||
members: 1,
|
||||
});
|
||||
|
||||
privateGuild = group;
|
||||
user = groupLeader;
|
||||
|
||||
nonMember = await generateUser();
|
||||
member = members[0];
|
||||
|
||||
challenge = await generateChallenge(user, group);
|
||||
await member.post(`/challenges/${challenge._id}/join`);
|
||||
});
|
||||
|
||||
it('fails if the user can\'t view the challenge', async () => {
|
||||
await expect(nonMember.put(`/challenges/${challenge._id}`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('challengeNotFound'),
|
||||
});
|
||||
});
|
||||
|
||||
it('should only allow the leader or an admin to update the challenge', async () => {
|
||||
await expect(member.put(`/challenges/${challenge._id}`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('onlyLeaderUpdateChal'),
|
||||
});
|
||||
});
|
||||
|
||||
it('only updates allowed fields', async () => {
|
||||
let res = await user.put(`/challenges/${challenge._id}`, {
|
||||
// ignored
|
||||
prize: 33,
|
||||
groupId: 'blabla',
|
||||
memberCount: 33,
|
||||
tasksOrder: 'new order',
|
||||
official: true,
|
||||
shortName: 'new short name',
|
||||
|
||||
// applied
|
||||
name: 'New Challenge Name',
|
||||
description: 'New challenge description.',
|
||||
leader: member._id,
|
||||
});
|
||||
|
||||
expect(res.prize).to.equal(0);
|
||||
expect(res.groupId).to.equal(privateGuild._id);
|
||||
expect(res.memberCount).to.equal(2);
|
||||
expect(res.tasksOrder).not.to.equal('new order');
|
||||
expect(res.official).to.equal(false);
|
||||
expect(res.shortName).not.to.equal('new short name');
|
||||
|
||||
expect(res.leader).to.equal(member._id);
|
||||
expect(res.name).to.equal('New Challenge Name');
|
||||
expect(res.description).to.equal('New challenge description.');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
import {
|
||||
createAndPopulateGroup,
|
||||
generateUser,
|
||||
translate as t,
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
import { v4 as generateUUID } from 'uuid';
|
||||
|
||||
describe('DELETE /groups/:groupId/chat/:chatId', () => {
|
||||
let groupWithChat, message, user, userThatDidNotCreateChat, admin;
|
||||
|
||||
before(async () => {
|
||||
let { group, groupLeader } = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
type: 'guild',
|
||||
privacy: 'public',
|
||||
},
|
||||
});
|
||||
|
||||
groupWithChat = group;
|
||||
user = groupLeader;
|
||||
message = await user.post(`/groups/${groupWithChat._id}/chat`, { message: 'Some message' });
|
||||
message = message.message;
|
||||
userThatDidNotCreateChat = await generateUser();
|
||||
admin = await generateUser({'contributor.admin': true});
|
||||
});
|
||||
|
||||
context('Chat errors', () => {
|
||||
it('returns an error is message does not exist', async () => {
|
||||
let fakeChatId = generateUUID();
|
||||
await expect(user.del(`/groups/${groupWithChat._id}/chat/${fakeChatId}`)).to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('messageGroupChatNotFound'),
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an error when user does not have permission to delete', async () => {
|
||||
await expect(userThatDidNotCreateChat.del(`/groups/${groupWithChat._id}/chat/${message.id}`)).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('onlyCreatorOrAdminCanDeleteChat'),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('Chat success', () => {
|
||||
let nextMessage;
|
||||
|
||||
beforeEach(async () => {
|
||||
nextMessage = await user.post(`/groups/${groupWithChat._id}/chat`, { message: 'Some new message' });
|
||||
nextMessage = nextMessage.message;
|
||||
});
|
||||
|
||||
it('allows creator to delete a their message', async () => {
|
||||
await user.del(`/groups/${groupWithChat._id}/chat/${nextMessage.id}`);
|
||||
let messages = await user.get(`/groups/${groupWithChat._id}/chat/`);
|
||||
expect(messages).is.an('array');
|
||||
expect(messages).to.not.include(nextMessage);
|
||||
});
|
||||
|
||||
it('allows admin to delete another user\'s message', async () => {
|
||||
await admin.del(`/groups/${groupWithChat._id}/chat/${nextMessage.id}`);
|
||||
let messages = await user.get(`/groups/${groupWithChat._id}/chat/`);
|
||||
expect(messages).is.an('array');
|
||||
expect(messages).to.not.include(nextMessage);
|
||||
});
|
||||
|
||||
it('returns empty when previous message parameter is passed and the last message was deleted', async () => {
|
||||
await expect(user.del(`/groups/${groupWithChat._id}/chat/${nextMessage.id}?previousMsg=${nextMessage.id}`))
|
||||
.to.eventually.be.empty;
|
||||
});
|
||||
|
||||
it('returns the update chat when previous message parameter is passed and the chat is updated', async () => {
|
||||
await expect(user.del(`/groups/${groupWithChat._id}/chat/${nextMessage.id}?previousMsg=${message.id}`))
|
||||
.eventually
|
||||
.is.an('array')
|
||||
.to.include(message)
|
||||
.to.be.lengthOf(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -5,11 +5,14 @@ import {
|
||||
import { find } from 'lodash';
|
||||
|
||||
describe('POST /chat/:chatId/flag', () => {
|
||||
let user, group;
|
||||
let user, admin, anotherUser, group;
|
||||
const TEST_MESSAGE = 'Test Message';
|
||||
|
||||
before(async () => {
|
||||
user = await generateUser({balance: 1});
|
||||
admin = await generateUser({balance: 1, 'contributor.admin': true});
|
||||
anotherUser = await generateUser();
|
||||
|
||||
group = await user.post('/groups', {
|
||||
name: 'Test Guild',
|
||||
type: 'guild',
|
||||
@@ -18,7 +21,7 @@ describe('POST /chat/:chatId/flag', () => {
|
||||
});
|
||||
|
||||
it('Returns an error when chat message is not found', async () => {
|
||||
return expect(user.post(`/groups/${group._id}/chat/incorrectMessage/flag`))
|
||||
await expect(user.post(`/groups/${group._id}/chat/incorrectMessage/flag`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
@@ -27,79 +30,55 @@ describe('POST /chat/:chatId/flag', () => {
|
||||
});
|
||||
|
||||
it('Returns an error when user tries to flag their own message', async () => {
|
||||
return user.post(`/groups/${group._id}/chat`, { message: TEST_MESSAGE})
|
||||
.then((result) => {
|
||||
return expect(user.post(`/groups/${group._id}/chat/${result.message.id}/flag`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('messageGroupChatFlagOwnMessage'),
|
||||
});
|
||||
});
|
||||
let message = await user.post(`/groups/${group._id}/chat`, { message: TEST_MESSAGE });
|
||||
await expect(user.post(`/groups/${group._id}/chat/${message.message.id}/flag`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('messageGroupChatFlagOwnMessage'),
|
||||
});
|
||||
});
|
||||
|
||||
it('Flags a chat', async () => {
|
||||
let message;
|
||||
let message = await anotherUser.post(`/groups/${group._id}/chat`, { message: TEST_MESSAGE});
|
||||
message = message.message;
|
||||
|
||||
return generateUser().then((anotherUser) => {
|
||||
return anotherUser.post(`/groups/${group._id}/chat`, { message: TEST_MESSAGE});
|
||||
})
|
||||
.then((result) => {
|
||||
message = result.message;
|
||||
return user.post(`/groups/${group._id}/chat/${message.id}/flag`);
|
||||
})
|
||||
.then((result) => {
|
||||
expect(result.flags[user._id]).to.equal(true);
|
||||
expect(result.flagCount).to.equal(1);
|
||||
return user.get(`/groups/${group._id}`);
|
||||
})
|
||||
.then((updatedGroup) => {
|
||||
let messageToCheck = find(updatedGroup.chat, {id: message.id});
|
||||
expect(messageToCheck.flags[user._id]).to.equal(true);
|
||||
});
|
||||
let flagResult = await user.post(`/groups/${group._id}/chat/${message.id}/flag`);
|
||||
expect(flagResult.flags[user._id]).to.equal(true);
|
||||
expect(flagResult.flagCount).to.equal(1);
|
||||
|
||||
let groupWithFlags = await admin.get(`/groups/${group._id}`);
|
||||
|
||||
let messageToCheck = find(groupWithFlags.chat, {id: message.id});
|
||||
expect(messageToCheck.flags[user._id]).to.equal(true);
|
||||
});
|
||||
|
||||
it('Flags a chat with a higher flag acount when an admin flags the message', async () => {
|
||||
let secondUser;
|
||||
let message;
|
||||
let message = await user.post(`/groups/${group._id}/chat`, { message: TEST_MESSAGE});
|
||||
message = message.message;
|
||||
|
||||
return generateUser({'contributor.admin': true}).then((generatedUser) => {
|
||||
secondUser = generatedUser;
|
||||
return user.post(`/groups/${group._id}/chat`, { message: TEST_MESSAGE});
|
||||
})
|
||||
.then((result) => {
|
||||
message = result.message;
|
||||
return secondUser.post(`/groups/${group._id}/chat/${message.id}/flag`);
|
||||
})
|
||||
.then((result) => {
|
||||
expect(result.flags[secondUser._id]).to.equal(true);
|
||||
expect(result.flagCount).to.equal(5);
|
||||
return user.get(`/groups/${group._id}`);
|
||||
})
|
||||
.then((updatedGroup) => {
|
||||
let messageToCheck = find(updatedGroup.chat, {id: message.id});
|
||||
expect(messageToCheck.flags[secondUser._id]).to.equal(true);
|
||||
expect(messageToCheck.flagCount).to.equal(5);
|
||||
});
|
||||
let flagResult = await admin.post(`/groups/${group._id}/chat/${message.id}/flag`);
|
||||
expect(flagResult.flags[admin._id]).to.equal(true);
|
||||
expect(flagResult.flagCount).to.equal(5);
|
||||
|
||||
let groupWithFlags = await admin.get(`/groups/${group._id}`);
|
||||
|
||||
let messageToCheck = find(groupWithFlags.chat, {id: message.id});
|
||||
expect(messageToCheck.flags[admin._id]).to.equal(true);
|
||||
expect(messageToCheck.flagCount).to.equal(5);
|
||||
});
|
||||
|
||||
it('Returns an error when user tries to flag a message that is already flagged', async () => {
|
||||
let message;
|
||||
let message = await anotherUser.post(`/groups/${group._id}/chat`, { message: TEST_MESSAGE});
|
||||
message = message.message;
|
||||
|
||||
return generateUser().then((anotherUser) => {
|
||||
return anotherUser.post(`/groups/${group._id}/chat`, { message: TEST_MESSAGE});
|
||||
})
|
||||
.then((result) => {
|
||||
message = result.message;
|
||||
return user.post(`/groups/${group._id}/chat/${message.id}/flag`);
|
||||
})
|
||||
.then(() => {
|
||||
return expect(user.post(`/groups/${group._id}/chat/${message.id}/flag`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('messageGroupChatFlagAlreadyReported'),
|
||||
});
|
||||
});
|
||||
await user.post(`/groups/${group._id}/chat/${message.id}/flag`);
|
||||
|
||||
await expect(user.post(`/groups/${group._id}/chat/${message.id}/flag`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('messageGroupChatFlagAlreadyReported'),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,36 +1,32 @@
|
||||
import {
|
||||
generateUser,
|
||||
createAndPopulateGroup,
|
||||
translate as t,
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
import { find } from 'lodash';
|
||||
|
||||
describe('POST /chat/:chatId/like', () => {
|
||||
let user;
|
||||
let group;
|
||||
let groupWithChat;
|
||||
let testMessage = 'Test Message';
|
||||
let anotherUser;
|
||||
|
||||
before(() => {
|
||||
let groupName = 'Test Guild';
|
||||
let groupType = 'guild';
|
||||
let groupPrivacy = 'public';
|
||||
|
||||
return generateUser({balance: 1}).then((generatedUser) => {
|
||||
user = generatedUser;
|
||||
})
|
||||
.then(() => {
|
||||
return user.post('/groups', {
|
||||
name: groupName,
|
||||
type: groupType,
|
||||
privacy: groupPrivacy,
|
||||
});
|
||||
})
|
||||
.then((generatedGroup) => {
|
||||
group = generatedGroup;
|
||||
before(async () => {
|
||||
let { group, groupLeader, members } = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
name: 'Test Guild',
|
||||
type: 'guild',
|
||||
privacy: 'public',
|
||||
},
|
||||
members: 1,
|
||||
});
|
||||
|
||||
user = groupLeader;
|
||||
groupWithChat = group;
|
||||
anotherUser = members[0];
|
||||
});
|
||||
|
||||
it('Returns an error when chat message is not found', () => {
|
||||
return expect(user.post(`/groups/${group._id}/chat/incorrectMessage/like`))
|
||||
it('Returns an error when chat message is not found', async () => {
|
||||
await expect(user.post(`/groups/${groupWithChat._id}/chat/incorrectMessage/like`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
@@ -38,59 +34,42 @@ describe('POST /chat/:chatId/like', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('Returns an error when user tries to like their own message', () => {
|
||||
return user.post(`/groups/${group._id}/chat`, { message: testMessage})
|
||||
.then((result) => {
|
||||
return expect(user.post(`/groups/${group._id}/chat/${result.message.id}/like`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('messageGroupChatLikeOwnMessage'),
|
||||
});
|
||||
});
|
||||
it('Returns an error when user tries to like their own message', async () => {
|
||||
let message = await user.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage});
|
||||
|
||||
await expect(user.post(`/groups/${groupWithChat._id}/chat/${message.message.id}/like`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('messageGroupChatLikeOwnMessage'),
|
||||
});
|
||||
});
|
||||
|
||||
it('Likes a chat', () => {
|
||||
let message;
|
||||
it('Likes a chat', async () => {
|
||||
let message = await anotherUser.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage});
|
||||
|
||||
return generateUser().then((anotherUser) => {
|
||||
return anotherUser.post(`/groups/${group._id}/chat`, { message: testMessage});
|
||||
})
|
||||
.then((result) => {
|
||||
message = result.message;
|
||||
return user.post(`/groups/${group._id}/chat/${message.id}/like`);
|
||||
})
|
||||
.then((result) => {
|
||||
expect(result.likes[user._id]).to.equal(true);
|
||||
return user.get(`/groups/${group._id}`);
|
||||
})
|
||||
.then((updatedGroup) => {
|
||||
let messageToCheck = find(updatedGroup.chat, {id: message.id});
|
||||
expect(messageToCheck.likes[user._id]).to.equal(true);
|
||||
});
|
||||
let likeResult = await user.post(`/groups/${groupWithChat._id}/chat/${message.message.id}/like`);
|
||||
|
||||
expect(likeResult.likes[user._id]).to.equal(true);
|
||||
|
||||
let groupWithChatLikes = await user.get(`/groups/${groupWithChat._id}`);
|
||||
|
||||
let messageToCheck = find(groupWithChatLikes.chat, {id: message.message.id});
|
||||
expect(messageToCheck.likes[user._id]).to.equal(true);
|
||||
});
|
||||
|
||||
it('Unlikes a chat', () => {
|
||||
let message;
|
||||
it('Unlikes a chat', async () => {
|
||||
let message = await anotherUser.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage});
|
||||
|
||||
return generateUser().then((anotherUser) => {
|
||||
return anotherUser.post(`/groups/${group._id}/chat`, { message: testMessage});
|
||||
})
|
||||
.then((result) => {
|
||||
message = result.message;
|
||||
return user.post(`/groups/${group._id}/chat/${message.id}/like`);
|
||||
})
|
||||
.then((result) => {
|
||||
expect(result.likes[user._id]).to.equal(true);
|
||||
return user.post(`/groups/${group._id}/chat/${message.id}/like`);
|
||||
})
|
||||
.then((result) => {
|
||||
expect(result.likes[user._id]).to.equal(false);
|
||||
return user.get(`/groups/${group._id}`);
|
||||
})
|
||||
.then((updatedGroup) => {
|
||||
let messageToCheck = find(updatedGroup.chat, {id: message.id});
|
||||
expect(messageToCheck.likes[user._id]).to.equal(false);
|
||||
});
|
||||
let likeResult = await user.post(`/groups/${groupWithChat._id}/chat/${message.message.id}/like`);
|
||||
expect(likeResult.likes[user._id]).to.equal(true);
|
||||
|
||||
let unlikeResult = await user.post(`/groups/${groupWithChat._id}/chat/${message.message.id}/like`);
|
||||
expect(unlikeResult.likes[user._id]).to.equal(false);
|
||||
|
||||
let groupWithoutChatLikes = await user.get(`/groups/${groupWithChat._id}`);
|
||||
|
||||
let messageToCheck = find(groupWithoutChatLikes.chat, {id: message.message.id});
|
||||
expect(messageToCheck.likes[user._id]).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,95 +1,81 @@
|
||||
import {
|
||||
generateUser,
|
||||
createAndPopulateGroup,
|
||||
translate as t,
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
|
||||
describe('POST /chat', () => {
|
||||
let user;
|
||||
let user, groupWithChat, userWithChatRevoked, member;
|
||||
let testMessage = 'Test Message';
|
||||
|
||||
before(() => {
|
||||
return generateUser().then((generatedUser) => {
|
||||
user = generatedUser;
|
||||
before(async () => {
|
||||
let { group, groupLeader, members } = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
name: 'Test Guild',
|
||||
type: 'guild',
|
||||
privacy: 'public',
|
||||
},
|
||||
members: 2,
|
||||
});
|
||||
|
||||
user = groupLeader;
|
||||
groupWithChat = group;
|
||||
userWithChatRevoked = await members[0].update({'flags.chatRevoked': true});
|
||||
member = members[0];
|
||||
});
|
||||
|
||||
it('Returns an error when no message is provided', () => {
|
||||
let groupName = 'Test Guild';
|
||||
let groupType = 'guild';
|
||||
let groupPrivacy = 'public';
|
||||
let testMessage = '';
|
||||
|
||||
return generateUser({balance: 1}).then((anotherUser) => {
|
||||
return anotherUser.post('/groups', {
|
||||
name: groupName,
|
||||
type: groupType,
|
||||
privacy: groupPrivacy,
|
||||
it('Returns an error when no message is provided', async () => {
|
||||
await expect(user.post(`/groups/${groupWithChat._id}/chat`, { message: ''}))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: t('invalidReqParams'),
|
||||
});
|
||||
})
|
||||
.then((group) => {
|
||||
return expect(user.post(`/groups/${group._id}/chat`, { message: testMessage}))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: t('invalidReqParams'),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Returns an error when group is not found', () => {
|
||||
let testMessage = 'Test Message';
|
||||
return expect(user.post('/groups/nvalidID/chat', { message: testMessage})).to.eventually.be.rejected.and.eql({
|
||||
it('Returns an error when group is not found', async () => {
|
||||
await expect(user.post('/groups/invalidID/chat', { message: testMessage})).to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('groupNotFound'),
|
||||
});
|
||||
});
|
||||
|
||||
it('Returns an error when chat privileges are revoked', () => {
|
||||
let groupName = 'Test Guild';
|
||||
let groupType = 'guild';
|
||||
let groupPrivacy = 'public';
|
||||
let testMessage = 'Test Message';
|
||||
let userWithoutChat;
|
||||
|
||||
return generateUser({balance: 1, 'flags.chatRevoked': true}).then((generatedUser) => {
|
||||
userWithoutChat = generatedUser;
|
||||
|
||||
return userWithoutChat.post('/groups', {
|
||||
name: groupName,
|
||||
type: groupType,
|
||||
privacy: groupPrivacy,
|
||||
});
|
||||
})
|
||||
.then((group) => {
|
||||
return expect(userWithoutChat.post(`/groups/${group._id}/chat`, { message: testMessage})).to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: 'Your chat privileges have been revoked.',
|
||||
});
|
||||
it('Returns an error when chat privileges are revoked', async () => {
|
||||
await expect(userWithChatRevoked.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage})).to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: 'Your chat privileges have been revoked.',
|
||||
});
|
||||
});
|
||||
|
||||
it('creates a chat', () => {
|
||||
let groupName = 'Test Guild';
|
||||
let groupType = 'guild';
|
||||
let groupPrivacy = 'public';
|
||||
let testMessage = 'Test Message';
|
||||
let anotherUser;
|
||||
it('creates a chat', async () => {
|
||||
let message = await user.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage});
|
||||
|
||||
return generateUser({balance: 1}).then((generatedUser) => {
|
||||
anotherUser = generatedUser;
|
||||
expect(message.message.id).to.exist;
|
||||
});
|
||||
|
||||
return anotherUser.post('/groups', {
|
||||
name: groupName,
|
||||
type: groupType,
|
||||
privacy: groupPrivacy,
|
||||
});
|
||||
})
|
||||
.then((group) => {
|
||||
return anotherUser.post(`/groups/${group._id}/chat`, { message: testMessage});
|
||||
})
|
||||
.then((result) => {
|
||||
expect(result.message.id).to.exist;
|
||||
it('notifies other users of new messages for a guild', async () => {
|
||||
let message = await user.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage});
|
||||
let memberWithNotification = await member.get('/user');
|
||||
|
||||
expect(message.message.id).to.exist;
|
||||
expect(memberWithNotification.newMessages[`${groupWithChat._id}`]).to.exist;
|
||||
});
|
||||
|
||||
it('notifies other users of new messages for a party', async () => {
|
||||
let { group, groupLeader, members } = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
name: 'Test Party',
|
||||
type: 'party',
|
||||
privacy: 'private',
|
||||
},
|
||||
members: 1,
|
||||
});
|
||||
|
||||
let message = await groupLeader.post(`/groups/${group._id}/chat`, { message: testMessage});
|
||||
let memberWithNotification = await members[0].get('/user');
|
||||
|
||||
expect(message.message.id).to.exist;
|
||||
expect(memberWithNotification.newMessages[`${group._id}`]).to.exist;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import {
|
||||
createAndPopulateGroup,
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
|
||||
describe('POST /groups/:id/chat/seen', () => {
|
||||
context('Guild', () => {
|
||||
let guild, guildLeader, guildMember, guildMessage;
|
||||
|
||||
before(async () => {
|
||||
let { group, groupLeader, members } = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
type: 'guild',
|
||||
privacy: 'public',
|
||||
},
|
||||
members: 1,
|
||||
});
|
||||
|
||||
guild = group;
|
||||
guildLeader = groupLeader;
|
||||
guildMember = members[0];
|
||||
|
||||
guildMessage = await guildLeader.post(`/groups/${guild._id}/chat`, { message: 'Some guild message' });
|
||||
guildMessage = guildMessage.message;
|
||||
});
|
||||
|
||||
it('clears new messages for a guild', async () => {
|
||||
await guildMember.post(`/groups/${guild._id}/chat/seen`);
|
||||
|
||||
let guildThatHasSeenChat = await guildMember.get('/user');
|
||||
|
||||
expect(guildThatHasSeenChat.newMessages).to.be.empty;
|
||||
});
|
||||
});
|
||||
|
||||
context('Party', () => {
|
||||
let party, partyLeader, partyMember, partyMessage;
|
||||
|
||||
before(async () => {
|
||||
let { group, groupLeader, members } = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
type: 'party',
|
||||
privacy: 'private',
|
||||
},
|
||||
members: 1,
|
||||
});
|
||||
|
||||
party = group;
|
||||
partyLeader = groupLeader;
|
||||
partyMember = members[0];
|
||||
|
||||
partyMessage = await partyLeader.post(`/groups/${party._id}/chat`, { message: 'Some party message' });
|
||||
partyMessage = partyMessage.message;
|
||||
});
|
||||
|
||||
it('clears new messages for a party', async () => {
|
||||
await partyMember.post(`/groups/${party._id}/chat/seen`);
|
||||
|
||||
let partyMemberThatHasSeenChat = await partyMember.get('/user');
|
||||
|
||||
expect(partyMemberThatHasSeenChat.newMessages).to.be.empty;
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,101 @@
|
||||
import {
|
||||
createAndPopulateGroup,
|
||||
generateUser,
|
||||
translate as t,
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
import { v4 as generateUUID } from 'uuid';
|
||||
|
||||
describe('POST /groups/:id/chat/:id/clearflags', () => {
|
||||
let groupWithChat, message, author, nonAdmin, admin;
|
||||
|
||||
before(async () => {
|
||||
let { group, groupLeader, members } = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
type: 'guild',
|
||||
privacy: 'public',
|
||||
},
|
||||
members: 1,
|
||||
});
|
||||
|
||||
groupWithChat = group;
|
||||
author = groupLeader;
|
||||
nonAdmin = members[0];
|
||||
admin = await generateUser({'contributor.admin': true});
|
||||
|
||||
message = await author.post(`/groups/${groupWithChat._id}/chat`, { message: 'Some message' });
|
||||
message = message.message;
|
||||
admin.post(`/groups/${groupWithChat._id}/chat/${message.id}/flag`);
|
||||
});
|
||||
|
||||
context('Single Message', () => {
|
||||
it('returns error when non-admin attempts to clear flags', async () => {
|
||||
return expect(nonAdmin.post(`/groups/${groupWithChat._id}/chat/${message.id}/clearflags`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('messageGroupChatAdminClearFlagCount'),
|
||||
});
|
||||
});
|
||||
|
||||
it('returns error if message does not exist', async () => {
|
||||
let fakeMessageID = generateUUID();
|
||||
|
||||
await expect(admin.post(`/groups/${groupWithChat._id}/chat/${fakeMessageID}/clearflags`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('messageGroupChatNotFound'),
|
||||
});
|
||||
});
|
||||
|
||||
it('clears flags and leaves old flags on the flag object', async () => {
|
||||
await admin.post(`/groups/${groupWithChat._id}/chat/${message.id}/clearflags`);
|
||||
let messages = await admin.get(`/groups/${groupWithChat._id}/chat`);
|
||||
expect(messages[0].flagCount).to.eql(0);
|
||||
expect(messages[0].flags).to.have.property(admin._id, true);
|
||||
});
|
||||
});
|
||||
|
||||
context('admin user, group with multiple messages', () => {
|
||||
let message2, message3, message4;
|
||||
|
||||
before(async () => {
|
||||
message2 = await author.post(`/groups/${groupWithChat._id}/chat`, { message: 'Some message 2' });
|
||||
message2 = message2.message;
|
||||
await admin.post(`/groups/${groupWithChat._id}/chat/${message2.id}/flag`);
|
||||
|
||||
message3 = await author.post(`/groups/${groupWithChat._id}/chat`, { message: 'Some message 3' });
|
||||
message3 = message3.message;
|
||||
await admin.post(`/groups/${groupWithChat._id}/chat/${message3.id}/flag`);
|
||||
await nonAdmin.post(`/groups/${groupWithChat._id}/chat/${message3.id}/flag`);
|
||||
|
||||
message4 = await author.post(`/groups/${groupWithChat._id}/chat`, { message: 'Some message 4' });
|
||||
message4 = message4.message;
|
||||
});
|
||||
|
||||
it('changes only the message that is flagged', async () => {
|
||||
await admin.post(`/groups/${groupWithChat._id}/chat/${message.id}/clearflags`);
|
||||
let messages = await admin.get(`/groups/${groupWithChat._id}/chat`);
|
||||
|
||||
expect(messages).to.have.lengthOf(4);
|
||||
|
||||
let messageThatWasUnflagged = messages[3];
|
||||
let messageWith1Flag = messages[2];
|
||||
let messageWith2Flag = messages[1];
|
||||
let messageWithoutFlags = messages[0];
|
||||
|
||||
expect(messageThatWasUnflagged.flagCount).to.eql(0);
|
||||
expect(messageThatWasUnflagged.flags).to.have.property(admin._id, true);
|
||||
|
||||
expect(messageWith1Flag.flagCount).to.eql(5);
|
||||
expect(messageWith1Flag.flags).to.have.property(admin._id, true);
|
||||
|
||||
expect(messageWith2Flag.flagCount).to.eql(6);
|
||||
expect(messageWith2Flag.flags).to.have.property(admin._id, true);
|
||||
expect(messageWith2Flag.flags).to.have.property(nonAdmin._id, true);
|
||||
|
||||
expect(messageWithoutFlags.flagCount).to.eql(0);
|
||||
expect(messageWithoutFlags.flags).to.eql({});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,96 @@
|
||||
import {
|
||||
generateUser,
|
||||
resetHabiticaDB,
|
||||
generateGroup,
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
|
||||
describe('GET /groups', () => {
|
||||
let user;
|
||||
const NUMBER_OF_PUBLIC_GUILDS = 3;
|
||||
const NUMBER_OF_USERS_PRIVATE_GUILDS = 1;
|
||||
const NUMBER_OF_GROUPS_USER_CAN_VIEW = 5;
|
||||
|
||||
before(async () => {
|
||||
await resetHabiticaDB();
|
||||
|
||||
let leader = await generateUser({ balance: 10 });
|
||||
user = await generateUser({balance: 4});
|
||||
|
||||
let publicGuildUserIsMemberOf = await generateGroup(leader, {
|
||||
name: 'public guild - is member',
|
||||
type: 'guild',
|
||||
privacy: 'public',
|
||||
});
|
||||
await leader.post(`/groups/${publicGuildUserIsMemberOf._id}/invite`, { uuids: [user._id]});
|
||||
await user.post(`/groups/${publicGuildUserIsMemberOf._id}/join`);
|
||||
|
||||
await generateGroup(leader, {
|
||||
name: 'public guild - is not member',
|
||||
type: 'guild',
|
||||
privacy: 'public',
|
||||
});
|
||||
|
||||
let privateGuildUserIsMemberOf = await generateGroup(leader, {
|
||||
name: 'private guild - is member',
|
||||
type: 'guild',
|
||||
privacy: 'private',
|
||||
});
|
||||
await leader.post(`/groups/${privateGuildUserIsMemberOf._id}/invite`, { uuids: [user._id]});
|
||||
await user.post(`/groups/${privateGuildUserIsMemberOf._id}/join`);
|
||||
|
||||
await generateGroup(leader, {
|
||||
name: 'private guild - is not member',
|
||||
type: 'guild',
|
||||
privacy: 'private',
|
||||
});
|
||||
|
||||
await generateGroup(leader, {
|
||||
name: 'party - is not member',
|
||||
type: 'party',
|
||||
privacy: 'private',
|
||||
});
|
||||
|
||||
await user.post('/groups', {
|
||||
name: 'party - is member',
|
||||
type: 'party',
|
||||
privacy: 'private',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns error when no query passed in', async () => {
|
||||
await expect(user.get('/groups'))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: 'Invalid request parameters.',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns only the tavern when tavern passed in as query', async () => {
|
||||
await expect(user.get('/groups?type=tavern'))
|
||||
.to.eventually.have.a.lengthOf(1)
|
||||
.and.to.have.deep.property('[0]')
|
||||
.and.to.have.property('_id', 'habitrpg');
|
||||
});
|
||||
|
||||
it('returns only the user\'s party when party passed in as query', async () => {
|
||||
await expect(user.get('/groups?type=party'))
|
||||
.to.eventually.have.a.lengthOf(1)
|
||||
.and.to.have.deep.property('[0]');
|
||||
});
|
||||
|
||||
it('returns all public guilds when publicGuilds passed in as query', async () => {
|
||||
await expect(user.get('/groups?type=publicGuilds'))
|
||||
.to.eventually.have.a.lengthOf(NUMBER_OF_PUBLIC_GUILDS);
|
||||
});
|
||||
|
||||
it('returns all private guilds user is a part of when privateGuilds passed in as query', async () => {
|
||||
await expect(user.get('/groups?type=privateGuilds'))
|
||||
.to.eventually.have.a.lengthOf(NUMBER_OF_USERS_PRIVATE_GUILDS);
|
||||
});
|
||||
|
||||
it('returns a list of groups user has access to', async () => {
|
||||
await expect(user.get('/groups?type=privateGuilds,publicGuilds,party,tavern'))
|
||||
.to.eventually.have.lengthOf(NUMBER_OF_GROUPS_USER_CAN_VIEW);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,302 @@
|
||||
import {
|
||||
generateUser,
|
||||
createAndPopulateGroup,
|
||||
translate as t,
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
|
||||
import {
|
||||
each,
|
||||
} from 'lodash';
|
||||
|
||||
describe('GET /groups/:id', () => {
|
||||
let typesOfGroups = {};
|
||||
typesOfGroups['public guild'] = { type: 'guild', privacy: 'public' };
|
||||
typesOfGroups['private guild'] = { type: 'guild', privacy: 'private' };
|
||||
typesOfGroups.party = { type: 'party', privacy: 'private' };
|
||||
|
||||
each(typesOfGroups, (groupDetails, groupType) => {
|
||||
context(`Member of a ${groupType}`, () => {
|
||||
let leader, member, createdGroup;
|
||||
|
||||
before(async () => {
|
||||
let groupData = await createAndPopulateGroup({
|
||||
members: 30,
|
||||
groupDetails,
|
||||
});
|
||||
|
||||
leader = groupData.groupLeader;
|
||||
member = groupData.members[0];
|
||||
createdGroup = groupData.group;
|
||||
});
|
||||
|
||||
it('returns the group object', async () => {
|
||||
let group = await member.get(`/groups/${createdGroup._id}`);
|
||||
|
||||
expect(group._id).to.eql(createdGroup._id);
|
||||
expect(group.name).to.eql(createdGroup.name);
|
||||
expect(group.type).to.eql(createdGroup.type);
|
||||
expect(group.privacy).to.eql(createdGroup.privacy);
|
||||
});
|
||||
|
||||
it('transforms leader id to leader object', async () => {
|
||||
let group = await member.get(`/groups/${createdGroup._id}`);
|
||||
|
||||
expect(group.leader._id).to.eql(leader._id);
|
||||
expect(group.leader.profile.name).to.eql(leader.profile.name);
|
||||
expect(group.leader.items).to.exist;
|
||||
expect(group.leader.stats).to.exist;
|
||||
expect(group.leader.achievements).to.exist;
|
||||
expect(group.leader.contributor).to.exist;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('Non-member of a public guild', () => {
|
||||
let nonMember, createdGroup;
|
||||
|
||||
before(async () => {
|
||||
let groupData = await createAndPopulateGroup({
|
||||
members: 1,
|
||||
groupDetails: {
|
||||
name: 'test guild',
|
||||
type: 'guild',
|
||||
privacy: 'public',
|
||||
},
|
||||
});
|
||||
|
||||
createdGroup = groupData.group;
|
||||
nonMember = await generateUser();
|
||||
});
|
||||
|
||||
it('returns the group object for a non-member', async () => {
|
||||
let group = await nonMember.get(`/groups/${createdGroup._id}`);
|
||||
|
||||
expect(group._id).to.eql(createdGroup._id);
|
||||
expect(group.name).to.eql(createdGroup.name);
|
||||
expect(group.type).to.eql(createdGroup.type);
|
||||
expect(group.privacy).to.eql(createdGroup.privacy);
|
||||
});
|
||||
});
|
||||
|
||||
context('Non-member of a private guild', () => {
|
||||
let nonMember, createdGroup;
|
||||
|
||||
before(async () => {
|
||||
let groupData = await createAndPopulateGroup({
|
||||
members: 1,
|
||||
groupDetails: {
|
||||
name: 'test guild',
|
||||
type: 'guild',
|
||||
privacy: 'private',
|
||||
},
|
||||
});
|
||||
|
||||
createdGroup = groupData.group;
|
||||
nonMember = await generateUser();
|
||||
});
|
||||
|
||||
it('does not return the group object for a non-member', async () => {
|
||||
await expect(nonMember.get(`/groups/${createdGroup._id}`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('groupNotFound'),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('Non-member of a party', () => {
|
||||
let nonMember, createdGroup;
|
||||
|
||||
before(async () => {
|
||||
let groupData = await createAndPopulateGroup({
|
||||
members: 1,
|
||||
groupDetails: {
|
||||
name: 'test party',
|
||||
type: 'party',
|
||||
privacy: 'private',
|
||||
},
|
||||
});
|
||||
|
||||
createdGroup = groupData.group;
|
||||
nonMember = await generateUser();
|
||||
});
|
||||
|
||||
it('does not return the group object for a non-member', async () => {
|
||||
await expect(nonMember.get(`/groups/${createdGroup._id}`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('groupNotFound'),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('Member of a party', () => {
|
||||
let member, createdGroup;
|
||||
|
||||
before(async () => {
|
||||
let groupData = await createAndPopulateGroup({
|
||||
members: 1,
|
||||
groupDetails: {
|
||||
name: 'test party',
|
||||
type: 'party',
|
||||
privacy: 'private',
|
||||
},
|
||||
});
|
||||
|
||||
createdGroup = groupData.group;
|
||||
member = groupData.members[0];
|
||||
});
|
||||
|
||||
it('returns the user\'s party if an id of "party" is passed in', async () => {
|
||||
let group = await member.get('/groups/party');
|
||||
|
||||
expect(group._id).to.eql(createdGroup._id);
|
||||
expect(group.name).to.eql(createdGroup.name);
|
||||
expect(group.type).to.eql(createdGroup.type);
|
||||
expect(group.privacy).to.eql(createdGroup.privacy);
|
||||
});
|
||||
});
|
||||
|
||||
context('Non-existent group', () => {
|
||||
let user;
|
||||
|
||||
beforeEach(async () => {
|
||||
user = await generateUser();
|
||||
});
|
||||
|
||||
it('returns error if group does not exist', async () => {
|
||||
await expect(user.get('/groups/group-that-does-not-exist'))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 404,
|
||||
error: 'NotFound',
|
||||
message: t('groupNotFound'),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('Flagged messages', () => {
|
||||
let group;
|
||||
|
||||
let chat1 = {
|
||||
id: 'chat1',
|
||||
text: 'chat 1',
|
||||
flags: {},
|
||||
};
|
||||
|
||||
let chat2 = {
|
||||
id: 'chat2',
|
||||
text: 'chat 2',
|
||||
flags: {},
|
||||
flagCount: 0,
|
||||
};
|
||||
|
||||
let chat3 = {
|
||||
id: 'chat3',
|
||||
text: 'chat 3',
|
||||
flags: {
|
||||
'user-id': true,
|
||||
},
|
||||
flagCount: 1,
|
||||
};
|
||||
|
||||
let chat4 = {
|
||||
id: 'chat4',
|
||||
text: 'chat 4',
|
||||
flags: {
|
||||
'user-id': true,
|
||||
'other-user-id': true,
|
||||
},
|
||||
flagCount: 2,
|
||||
};
|
||||
|
||||
let chat5 = {
|
||||
id: 'chat5',
|
||||
text: 'chat 5',
|
||||
flags: {
|
||||
'user-id': true,
|
||||
'other-user-id': true,
|
||||
'yet-another-user-id': true,
|
||||
},
|
||||
flagCount: 3,
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
let groupData = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
name: 'test guild',
|
||||
type: 'guild',
|
||||
privacy: 'public',
|
||||
chat: [
|
||||
chat1,
|
||||
chat2,
|
||||
chat3,
|
||||
chat4,
|
||||
chat5,
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
group = groupData.group;
|
||||
|
||||
await group.addChat([chat1, chat2, chat3, chat4, chat5]);
|
||||
});
|
||||
|
||||
context('non-admin', () => {
|
||||
let nonAdmin;
|
||||
|
||||
beforeEach(async () => {
|
||||
nonAdmin = await generateUser();
|
||||
});
|
||||
|
||||
it('does not include messages with a flag count of 2 or greater', async () => {
|
||||
let fetchedGroup = await nonAdmin.get(`/groups/${group._id}`);
|
||||
|
||||
expect(fetchedGroup.chat).to.have.lengthOf(3);
|
||||
expect(fetchedGroup.chat[0].id).to.eql(chat1.id);
|
||||
expect(fetchedGroup.chat[1].id).to.eql(chat2.id);
|
||||
expect(fetchedGroup.chat[2].id).to.eql(chat3.id);
|
||||
});
|
||||
|
||||
it('does not include user ids in flags object', async () => {
|
||||
let fetchedGroup = await nonAdmin.get(`/groups/${group._id}`);
|
||||
let chatWithOneFlag = fetchedGroup.chat[2];
|
||||
|
||||
expect(chatWithOneFlag.id).to.eql(chat3.id);
|
||||
expect(chat3.flags).to.eql({ 'user-id': true });
|
||||
expect(chatWithOneFlag.flags).to.eql({});
|
||||
});
|
||||
});
|
||||
|
||||
context('admin', () => {
|
||||
let admin;
|
||||
|
||||
beforeEach(async () => {
|
||||
admin = await generateUser({
|
||||
'contributor.admin': true,
|
||||
});
|
||||
});
|
||||
|
||||
it('includes all messages', async () => {
|
||||
let fetchedGroup = await admin.get(`/groups/${group._id}`);
|
||||
|
||||
expect(fetchedGroup.chat).to.have.lengthOf(5);
|
||||
expect(fetchedGroup.chat[0].id).to.eql(chat1.id);
|
||||
expect(fetchedGroup.chat[1].id).to.eql(chat2.id);
|
||||
expect(fetchedGroup.chat[2].id).to.eql(chat3.id);
|
||||
expect(fetchedGroup.chat[3].id).to.eql(chat4.id);
|
||||
expect(fetchedGroup.chat[4].id).to.eql(chat5.id);
|
||||
});
|
||||
|
||||
it('includes user ids in flags object', async () => {
|
||||
let fetchedGroup = await admin.get(`/groups/${group._id}`);
|
||||
let chatWithOneFlag = fetchedGroup.chat[2];
|
||||
|
||||
expect(chatWithOneFlag.id).to.eql(chat3.id);
|
||||
expect(chat3.flags).to.eql({ 'user-id': true });
|
||||
expect(chatWithOneFlag.flags).to.eql(chat3.flags);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
generateUser,
|
||||
createAndPopulateGroup,
|
||||
checkExistence,
|
||||
translate as t,
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
import { v4 as generateUUID } from 'uuid';
|
||||
@@ -16,7 +17,47 @@ describe('POST /group/:groupId/join', () => {
|
||||
});
|
||||
});
|
||||
|
||||
context('Accepting invitation to a private guild', () => {
|
||||
context('Joining a public guild', () => {
|
||||
let user, joiningUser, publicGuild;
|
||||
|
||||
beforeEach(async () => {
|
||||
let {group, groupLeader} = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
name: 'Test Guild',
|
||||
type: 'guild',
|
||||
privacy: 'public',
|
||||
},
|
||||
});
|
||||
|
||||
publicGuild = group;
|
||||
user = groupLeader;
|
||||
joiningUser = await generateUser();
|
||||
});
|
||||
|
||||
it('allows non-invited users to join public guilds', async () => {
|
||||
await joiningUser.post(`/groups/${publicGuild._id}/join`);
|
||||
|
||||
await expect(joiningUser.get('/user')).to.eventually.have.property('guilds').to.include(publicGuild._id);
|
||||
});
|
||||
|
||||
it('promotes joining member in a public empty guild to leader', async () => {
|
||||
await user.post(`/groups/${publicGuild._id}/leave`);
|
||||
|
||||
await joiningUser.post(`/groups/${publicGuild._id}/join`);
|
||||
|
||||
await expect(joiningUser.get(`/groups/${publicGuild._id}`)).to.eventually.have.deep.property('leader._id', joiningUser._id);
|
||||
});
|
||||
|
||||
it('increments memberCount when joining guilds', async () => {
|
||||
let oldMemberCount = publicGuild.memberCount;
|
||||
|
||||
await joiningUser.post(`/groups/${publicGuild._id}/join`);
|
||||
|
||||
await expect(joiningUser.get(`/groups/${publicGuild._id}`)).to.eventually.have.property('memberCount', oldMemberCount + 1);
|
||||
});
|
||||
});
|
||||
|
||||
context('Joining a private guild', () => {
|
||||
let user, invitedUser, guild;
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -44,21 +85,6 @@ describe('POST /group/:groupId/join', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('allows non-invited users to join public guilds', async () => {
|
||||
let publicGuild = (await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
name: 'Test Guild',
|
||||
type: 'guild',
|
||||
privacy: 'public',
|
||||
},
|
||||
})).group;
|
||||
|
||||
let joiningUser = await generateUser();
|
||||
await joiningUser.post(`/groups/${publicGuild._id}/join`);
|
||||
|
||||
await expect(joiningUser.get('/user')).to.eventually.have.property('guilds').and.to.include(publicGuild._id);
|
||||
});
|
||||
|
||||
context('User is invited', () => {
|
||||
it('allows invited user to join private guilds', async () => {
|
||||
await invitedUser.post(`/groups/${guild._id}/join`);
|
||||
@@ -74,6 +100,14 @@ describe('POST /group/:groupId/join', () => {
|
||||
.to.not.include({id: guild._id});
|
||||
});
|
||||
|
||||
it('increments memberCount when joining guilds', async () => {
|
||||
let oldMemberCount = guild.memberCount;
|
||||
|
||||
await invitedUser.post(`/groups/${guild._id}/join`);
|
||||
|
||||
await expect(invitedUser.get(`/groups/${guild._id}`)).to.eventually.have.property('memberCount', oldMemberCount + 1);
|
||||
});
|
||||
|
||||
it('does not give basilist quest to inviter when joining a guild', async () => {
|
||||
await invitedUser.post(`/groups/${guild._id}/join`);
|
||||
|
||||
@@ -90,7 +124,7 @@ describe('POST /group/:groupId/join', () => {
|
||||
});
|
||||
});
|
||||
|
||||
context('Accepting invitation to a party', () => {
|
||||
context('Joining a party', () => {
|
||||
let user, invitedUser, party;
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -130,6 +164,14 @@ describe('POST /group/:groupId/join', () => {
|
||||
await expect(invitedUser.get('/user')).to.eventually.not.have.deep.property('invitations.party.id');
|
||||
});
|
||||
|
||||
it('increments memberCount when joining party', async () => {
|
||||
let oldMemberCount = party.memberCount;
|
||||
|
||||
await invitedUser.post(`/groups/${party._id}/join`);
|
||||
|
||||
await expect(invitedUser.get(`/groups/${party._id}`)).to.eventually.have.property('memberCount', oldMemberCount + 1);
|
||||
});
|
||||
|
||||
it('gives basilist quest item to the inviter when joining a party', async () => {
|
||||
await invitedUser.post(`/groups/${party._id}/join`);
|
||||
|
||||
@@ -143,6 +185,37 @@ describe('POST /group/:groupId/join', () => {
|
||||
|
||||
await expect(user.get('/user')).to.eventually.have.deep.property('items.quests.basilist', 2);
|
||||
});
|
||||
|
||||
it('deletes previous party where the user was the only member', async () => {
|
||||
let userToInvite = await generateUser();
|
||||
let oldParty = await userToInvite.post('/groups', { // add user to a party
|
||||
name: 'Another Test Party',
|
||||
type: 'party',
|
||||
});
|
||||
|
||||
await expect(checkExistence('groups', oldParty._id)).to.eventually.equal(true);
|
||||
await user.post(`/groups/${party._id}/invite`, {
|
||||
uuids: [userToInvite._id],
|
||||
});
|
||||
await userToInvite.post(`/groups/${party._id}/join`);
|
||||
|
||||
await expect(user.get('/user')).to.eventually.have.deep.property('party._id', party._id);
|
||||
await expect(checkExistence('groups', oldParty._id)).to.eventually.equal(false);
|
||||
});
|
||||
|
||||
xit('invites joining member to active quest', async () => {
|
||||
// TODO start quest
|
||||
|
||||
await invitedUser.post(`/groups/${party._id}/join`);
|
||||
|
||||
invitedUser = await user.get('/user');
|
||||
party = await user.get(`/groups/${party._id}`);
|
||||
|
||||
expect(user).to.have.deep.property('party.quest.RSVPNeeded', true);
|
||||
expect(user).to.have.deep.property('party.quest.key', party.quest.key);
|
||||
|
||||
expect(party.quest.members[invitedUser._id]).to.be.undefined;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
import {
|
||||
generateUser,
|
||||
createAndPopulateGroup,
|
||||
translate as t,
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
|
||||
describe('POST /groups/:groupId/removeMember/:memberId', () => {
|
||||
let leader;
|
||||
let invitedUser;
|
||||
let guild;
|
||||
let member;
|
||||
let member2;
|
||||
|
||||
beforeEach(async () => {
|
||||
let { group, groupLeader, invitees, members } = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
name: 'Test Guild',
|
||||
type: 'guild',
|
||||
privacy: 'private',
|
||||
},
|
||||
invites: 1,
|
||||
members: 2,
|
||||
});
|
||||
|
||||
guild = group;
|
||||
leader = groupLeader;
|
||||
invitedUser = invitees[0];
|
||||
member = members[0];
|
||||
member2 = members[1];
|
||||
});
|
||||
|
||||
context('All Groups', () => {
|
||||
it('returns an error when user is not member of the group', async () => {
|
||||
let nonMember = await generateUser();
|
||||
|
||||
expect(nonMember.post(`/groups/${guild._id}/removeMember/${member._id}`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
type: 'NotAuthorized',
|
||||
message: t('onlyLeaderCanRemoveMember'),
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an error when user is a non-leader member of a group', async () => {
|
||||
expect(member2.post(`/groups/${guild._id}/removeMember/${member._id}`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
type: 'NotAuthorized',
|
||||
message: t('onlyLeaderCanRemoveMember'),
|
||||
});
|
||||
});
|
||||
|
||||
it('does not allow leader to remove themselves', async () => {
|
||||
expect(leader.post(`/groups/${guild._id}/removeMember/${leader._id}`))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
text: t('messageGroupCannotRemoveSelf'),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('Guilds', () => {
|
||||
it('can remove other members', async () => {
|
||||
await leader.post(`/groups/${guild._id}/removeMember/${member._id}`);
|
||||
let memberRemoved = await member.get('/user');
|
||||
|
||||
expect(memberRemoved.guilds.indexOf(guild._id)).eql(-1);
|
||||
});
|
||||
|
||||
it('updates memberCount', async () => {
|
||||
let oldMemberCount = guild.memberCount;
|
||||
await leader.post(`/groups/${guild._id}/removeMember/${member._id}`);
|
||||
await expect(leader.get(`/groups/${guild._id}`)).to.eventually.have.property('memberCount', oldMemberCount - 1);
|
||||
});
|
||||
|
||||
it('can remove other invites', async () => {
|
||||
await leader.post(`/groups/${guild._id}/removeMember/${invitedUser._id}`);
|
||||
|
||||
let invitedUserWithoutInvite = await invitedUser.get('/user');
|
||||
|
||||
expect(_.findIndex(invitedUserWithoutInvite.invitations.guilds, {id: guild._id})).eql(-1);
|
||||
});
|
||||
});
|
||||
|
||||
context('Party', () => {
|
||||
let party;
|
||||
let partyleader;
|
||||
let partyInvitedUser;
|
||||
let partyMember;
|
||||
|
||||
beforeEach(async () => {
|
||||
let { group, groupLeader, invitees, members } = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
name: 'Test Party',
|
||||
type: 'party',
|
||||
privacy: 'private',
|
||||
},
|
||||
invites: 1,
|
||||
members: 1,
|
||||
});
|
||||
|
||||
party = group;
|
||||
partyleader = groupLeader;
|
||||
partyInvitedUser = invitees[0];
|
||||
partyMember = members[0];
|
||||
});
|
||||
|
||||
it('can remove other members', async () => {
|
||||
await partyleader.post(`/groups/${party._id}/removeMember/${partyMember._id}`);
|
||||
|
||||
let memberRemoved = await partyMember.get('/user');
|
||||
|
||||
expect(memberRemoved.party._id).eql(undefined);
|
||||
});
|
||||
|
||||
it('updates memberCount', async () => {
|
||||
let oldMemberCount = party.memberCount;
|
||||
await partyleader.post(`/groups/${party._id}/removeMember/${partyMember._id}`);
|
||||
await expect(partyleader.get(`/groups/${party._id}`)).to.eventually.have.property('memberCount', oldMemberCount - 1);
|
||||
});
|
||||
|
||||
it('can remove other invites', async () => {
|
||||
await partyleader.post(`/groups/${party._id}/removeMember/${partyInvitedUser._id}`);
|
||||
|
||||
let invitedUserWithoutInvite = await partyInvitedUser.get('/user');
|
||||
|
||||
expect(_.findIndex(invitedUserWithoutInvite.invitations.party, {id: party._id})).eql(-1);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -290,12 +290,14 @@ describe('Post /groups/:groupId/invite', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an error when invited user is already in the party', async () => {
|
||||
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],
|
||||
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],
|
||||
@@ -306,5 +308,18 @@ describe('Post /groups/:groupId/invite', () => {
|
||||
message: t('userAlreadyInAParty'),
|
||||
});
|
||||
});
|
||||
|
||||
it('allow inviting an user to a party if he\'s 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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -22,6 +22,21 @@ describe('GET /tasks/user', () => {
|
||||
expect(tasks[0]._id).to.equal(createdTasks[0]._id);
|
||||
});
|
||||
|
||||
// TODO complete after task scoring is done
|
||||
it('returns completed todos sorted by creation date if req.query.includeCompletedTodos is specified');
|
||||
it('returns completed todos sorted by completion date if req.query.includeCompletedTodos is specified', async () => {
|
||||
let todo1 = await user.post('/tasks/user', {text: 'todo to complete 1', type: 'todo'});
|
||||
let todo2 = await user.post('/tasks/user', {text: 'todo to complete 2', type: 'todo'});
|
||||
|
||||
await user.sync();
|
||||
let initialTodoCount = user.tasksOrder.todos.length;
|
||||
|
||||
await user.post(`/tasks/${todo2._id}/score/up`);
|
||||
await user.post(`/tasks/${todo1._id}/score/up`);
|
||||
await user.sync();
|
||||
|
||||
expect(user.tasksOrder.todos.length).to.equal(initialTodoCount - 2);
|
||||
|
||||
let allTodos = await user.get('/tasks/user?type=todo&includeCompletedTodos=true');
|
||||
expect(allTodos.length).to.equal(initialTodoCount);
|
||||
expect(allTodos[allTodos.length - 1].text).to.equal('todo to complete 1'); // last is the todo that was completed later
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import {
|
||||
generateUser,
|
||||
generateGroup,
|
||||
generateChallenge,
|
||||
} from '../../../../helpers/api-integration/v3';
|
||||
|
||||
describe('POST /tasks/clearCompletedTodos', () => {
|
||||
it('deletes all completed todos except the ones from a challenge', async () => {
|
||||
let user = await generateUser({balance: 1});
|
||||
let guild = await generateGroup(user);
|
||||
let challenge = await generateChallenge(user, guild);
|
||||
|
||||
let initialTodoCount = user.tasksOrder.todos.length;
|
||||
await user.post('/tasks/user', [
|
||||
{text: 'todo 1', type: 'todo'},
|
||||
{text: 'todo 2', type: 'todo'},
|
||||
{text: 'todo 3', type: 'todo'},
|
||||
{text: 'todo 4', type: 'todo'},
|
||||
{text: 'todo 5', type: 'todo'},
|
||||
]);
|
||||
|
||||
await user.post(`/tasks/challenge/${challenge._id}`, {
|
||||
text: 'todo 6',
|
||||
type: 'todo',
|
||||
});
|
||||
|
||||
let tasks = await user.get('/tasks/user?type=todo');
|
||||
expect(tasks.length).to.equal(initialTodoCount + 6);
|
||||
|
||||
for (let task of tasks) {
|
||||
if (['todo 2', 'todo 3', 'todo 6'].indexOf(task.text) !== -1) {
|
||||
await user.post(`/tasks/${task._id}/score/up`); // eslint-disable-line babel/no-await-in-loop
|
||||
}
|
||||
}
|
||||
|
||||
await user.post('/tasks/clearCompletedTodos');
|
||||
let tasksUpdated = await user.get('/tasks/user?type=todo&includeCompletedTodos=true');
|
||||
expect(tasksUpdated.length).to.equal(initialTodoCount + 4); // + 6 - 3 completed (but one is from challenge)
|
||||
expect(tasksUpdated[tasksUpdated.length - 1].text).to.equal('todo 6');
|
||||
});
|
||||
});
|
||||
@@ -1,23 +1,16 @@
|
||||
import baseModel from '../../../../../website/src/libs/api-v3/baseModel';
|
||||
import mongoose from 'mongoose';
|
||||
|
||||
describe('Base model plugin', () => {
|
||||
let schema = {
|
||||
add () {
|
||||
return true;
|
||||
},
|
||||
statics: {},
|
||||
options: {},
|
||||
pre () {
|
||||
return true;
|
||||
},
|
||||
};
|
||||
let schema;
|
||||
|
||||
beforeEach(() => {
|
||||
schema = new mongoose.Schema();
|
||||
sandbox.stub(schema, 'add');
|
||||
});
|
||||
|
||||
it('adds a _id field to the schema', () => {
|
||||
baseModel(schema);
|
||||
schema.plugin(baseModel);
|
||||
|
||||
expect(schema.add).to.be.calledWith(sinon.match({
|
||||
_id: sinon.match.object,
|
||||
@@ -25,13 +18,13 @@ describe('Base model plugin', () => {
|
||||
});
|
||||
|
||||
it('can add timestamps fields', () => {
|
||||
baseModel(schema, {timestamps: true});
|
||||
schema.plugin(baseModel, {timestamps: true});
|
||||
|
||||
expect(schema.add).to.be.calledTwice;
|
||||
});
|
||||
|
||||
it('can sanitize input objects', () => {
|
||||
baseModel(schema, {
|
||||
schema.plugin(baseModel, {
|
||||
noSet: ['noUpdateForMe'],
|
||||
});
|
||||
|
||||
@@ -44,7 +37,7 @@ describe('Base model plugin', () => {
|
||||
});
|
||||
|
||||
it('accepts an array of additional fields to sanitize at runtime', () => {
|
||||
baseModel(schema, {
|
||||
schema.plugin(baseModel, {
|
||||
noSet: ['noUpdateForMe'],
|
||||
});
|
||||
|
||||
@@ -58,7 +51,7 @@ describe('Base model plugin', () => {
|
||||
|
||||
|
||||
it('can make fields private', () => {
|
||||
baseModel(schema, {
|
||||
schema.plugin(baseModel, {
|
||||
private: ['amPrivate'],
|
||||
});
|
||||
|
||||
@@ -76,7 +69,7 @@ describe('Base model plugin', () => {
|
||||
toJSONTransform: sandbox.stub().returns(true),
|
||||
};
|
||||
|
||||
baseModel(schema, options);
|
||||
schema.plugin(baseModel, options);
|
||||
|
||||
let objToTransform = {ok: true, amPrivate: true};
|
||||
let privatized = schema.options.toJSON.transform({}, objToTransform);
|
||||
@@ -91,7 +84,7 @@ describe('Base model plugin', () => {
|
||||
sanitizeTransform: sandbox.stub().returns(true),
|
||||
};
|
||||
|
||||
baseModel(schema, options);
|
||||
schema.plugin(baseModel, options);
|
||||
|
||||
expect(schema.options.toJSON.transform).to.exist;
|
||||
let objToSanitize = {ok: true, noUpdateForMe: true};
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import mongoose from 'mongoose';
|
||||
import {
|
||||
removeFromArray,
|
||||
} from '../../../../../website/src/libs/api-v3/collectionManipulators';
|
||||
|
||||
describe('Collection Manipulators', () => {
|
||||
describe('removeFromArray', () => {
|
||||
it('removes element from array', () => {
|
||||
let array = ['a', 'b', 'c', 'd'];
|
||||
|
||||
removeFromArray(array, 'c');
|
||||
|
||||
expect(array).to.not.include('c');
|
||||
});
|
||||
|
||||
it('removes object from array', () => {
|
||||
let array = [
|
||||
{ id: 'a', foo: 'bar' },
|
||||
{ id: 'b', foo: 'bar' },
|
||||
{ id: 'c', foo: 'bar' },
|
||||
{ id: 'd', foo: 'bar' },
|
||||
{ id: 'e', foo: 'bar' },
|
||||
];
|
||||
|
||||
removeFromArray(array, { id: 'c' });
|
||||
|
||||
expect(array).to.not.include({ id: 'c', foo: 'bar' });
|
||||
});
|
||||
|
||||
it('does not change array if value is not found', () => {
|
||||
let array = ['a', 'b', 'c', 'd'];
|
||||
|
||||
removeFromArray(array, 'z');
|
||||
|
||||
expect(array).to.have.a.lengthOf(4);
|
||||
expect(array[0]).to.eql('a');
|
||||
expect(array[1]).to.eql('b');
|
||||
expect(array[2]).to.eql('c');
|
||||
expect(array[3]).to.eql('d');
|
||||
});
|
||||
|
||||
it('returns the removed element', () => {
|
||||
let array = ['a', 'b', 'c'];
|
||||
|
||||
let result = removeFromArray(array, 'b');
|
||||
|
||||
expect(result).to.eql('b');
|
||||
});
|
||||
|
||||
it('returns the removed object element', () => {
|
||||
let array = [
|
||||
{ id: 'a', foo: 'bar' },
|
||||
{ id: 'b', foo: 'bar' },
|
||||
{ id: 'c', foo: 'bar' },
|
||||
{ id: 'd', foo: 'bar' },
|
||||
{ id: 'e', foo: 'bar' },
|
||||
];
|
||||
|
||||
let result = removeFromArray(array, { id: 'c' });
|
||||
|
||||
expect(result).to.eql({ id: 'c', foo: 'bar' });
|
||||
});
|
||||
|
||||
it('returns false if item is not found', () => {
|
||||
let array = ['a', 'b', 'c'];
|
||||
|
||||
let result = removeFromArray(array, 'z');
|
||||
|
||||
expect(result).to.eql(false);
|
||||
});
|
||||
|
||||
it('persists removal of element when mongoose document is saved', async () => {
|
||||
let schema = new mongoose.Schema({
|
||||
array: Array,
|
||||
});
|
||||
let Model = mongoose.model('ModelToTestRemoveFromArray', schema);
|
||||
let model = await new Model({
|
||||
array: ['a', 'b', 'c'],
|
||||
}).save(); // Initial creation
|
||||
|
||||
removeFromArray(model.array, 'b');
|
||||
|
||||
let savedModel = await model.save();
|
||||
|
||||
expect(savedModel.array).to.not.include('b');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -31,13 +31,6 @@ describe('i18n', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('localePath', () => {
|
||||
it('is an absolute path to common/locales/', () => {
|
||||
expect(localePath).to.match(/.*\/common\/locales\//);
|
||||
expect(localePath);
|
||||
});
|
||||
});
|
||||
|
||||
describe('langCodes', () => {
|
||||
it('is a list of all the language codes', () => {
|
||||
expect(langCodes.sort()).to.eql(listOfLocales);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import setupNconf from '../../../../../website/src/libs/api-v3/setupNconf';
|
||||
|
||||
import path from 'path';
|
||||
import nconf from 'nconf';
|
||||
|
||||
describe('setupNconf', () => {
|
||||
@@ -19,7 +20,9 @@ describe('setupNconf', () => {
|
||||
expect(nconf.argv).to.be.calledOnce;
|
||||
expect(nconf.env).to.be.calledOnce;
|
||||
expect(nconf.file).to.be.calledOnce;
|
||||
expect(nconf.file).to.be.calledWithMatch('user', /\/config.json$/);
|
||||
|
||||
let regexString = `\\${path.sep}config.json$`;
|
||||
expect(nconf.file).to.be.calledWithMatch('user', new RegExp(regexString));
|
||||
});
|
||||
|
||||
it('sets IS_PROD variable', () => {
|
||||
|
||||
@@ -53,4 +53,3 @@ describe('analytics middleware', () => {
|
||||
expect(res.analytics.trackPurchase).to.eql(analyticsService.trackPurchase);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user