mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-16 22:27:26 +01:00
Merge branch 'develop' of https://github.com/HabitRPG/habitica into autocomplete-username
# Conflicts: # package.json # website/client/components/chat/autoComplete.vue # website/client/components/chat/chatCard.vue # website/client/components/groups/chat.vue # website/server/controllers/api-v3/chat.js # website/server/controllers/api-v3/members.js # website/server/controllers/api-v4/members.js
This commit is contained in:
@@ -335,14 +335,13 @@ describe('analyticsService', () => {
|
||||
let data, itemSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
Visitor.prototype.event.yields();
|
||||
|
||||
itemSpy = sandbox.stub().returnsThis();
|
||||
|
||||
Visitor.prototype.event.returns({
|
||||
send: sandbox.stub(),
|
||||
});
|
||||
Visitor.prototype.transaction.returns({
|
||||
item: itemSpy,
|
||||
send: sandbox.stub().returnsThis(),
|
||||
send: sandbox.stub().yields(),
|
||||
});
|
||||
|
||||
data = {
|
||||
|
||||
@@ -1232,7 +1232,7 @@ describe('cron', () => {
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
|
||||
expect(user.history.exp).to.have.lengthOf(1);
|
||||
expect(user.history.exp[0].value).to.equal(150);
|
||||
expect(user.history.exp[0].value).to.equal(25);
|
||||
});
|
||||
|
||||
it('increments perfect day achievement if all (at least 1) due dailies were completed', () => {
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
/* eslint-disable global-require */
|
||||
import got from 'got';
|
||||
import nconf from 'nconf';
|
||||
import nodemailer from 'nodemailer';
|
||||
import requireAgain from 'require-again';
|
||||
import logger from '../../../../website/server/libs/logger';
|
||||
import { TAVERN_ID } from '../../../../website/server/models/group';
|
||||
import { defer } from '../../../helpers/api-unit.helper';
|
||||
|
||||
@@ -35,42 +33,6 @@ function getUser () {
|
||||
describe('emails', () => {
|
||||
let pathToEmailLib = '../../../../website/server/libs/email';
|
||||
|
||||
describe('sendEmail', () => {
|
||||
let sendMailSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
sendMailSpy = sandbox.stub().returns(defer().promise);
|
||||
sandbox.stub(nodemailer, 'createTransport').returns({
|
||||
sendMail: sendMailSpy,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('can send an email using the default transport', () => {
|
||||
let attachEmail = requireAgain(pathToEmailLib);
|
||||
attachEmail.send();
|
||||
expect(sendMailSpy).to.be.calledOnce;
|
||||
});
|
||||
|
||||
it('logs errors', (done) => {
|
||||
sandbox.stub(logger, 'error');
|
||||
|
||||
let attachEmail = requireAgain(pathToEmailLib);
|
||||
attachEmail.send();
|
||||
expect(sendMailSpy).to.be.calledOnce;
|
||||
defer().reject();
|
||||
|
||||
// wait for unhandledRejection event to fire
|
||||
setTimeout(() => {
|
||||
expect(logger.error).to.be.calledOnce;
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUserInfo', () => {
|
||||
it('returns an empty object if no field request', () => {
|
||||
let attachEmail = requireAgain(pathToEmailLib);
|
||||
@@ -84,7 +46,7 @@ describe('emails', () => {
|
||||
let user = getUser();
|
||||
let data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
|
||||
|
||||
expect(data).to.have.property('name', user.profile.name);
|
||||
expect(data).to.have.property('name', user.auth.local.username);
|
||||
expect(data).to.have.property('email', user.auth.local.email);
|
||||
expect(data).to.have.property('_id', user._id);
|
||||
expect(data).to.have.property('canSend', true);
|
||||
@@ -95,11 +57,11 @@ describe('emails', () => {
|
||||
let getUserInfo = attachEmail.getUserInfo;
|
||||
let user = getUser();
|
||||
delete user.profile.name;
|
||||
delete user.auth.local;
|
||||
delete user.auth.local.email;
|
||||
|
||||
let data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
|
||||
|
||||
expect(data).to.have.property('name', user.profile.name);
|
||||
expect(data).to.have.property('name', user.auth.local.username);
|
||||
expect(data).to.have.property('email', user.auth.facebook.emails[0].value);
|
||||
expect(data).to.have.property('_id', user._id);
|
||||
expect(data).to.have.property('canSend', true);
|
||||
@@ -114,7 +76,7 @@ describe('emails', () => {
|
||||
|
||||
let data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
|
||||
|
||||
expect(data).to.have.property('name', user.profile.name);
|
||||
expect(data).to.have.property('name', user.auth.local.username);
|
||||
expect(data).not.to.have.property('email');
|
||||
expect(data).to.have.property('_id', user._id);
|
||||
expect(data).to.have.property('canSend', true);
|
||||
|
||||
113
test/api/unit/libs/items/utils.test.js
Normal file
113
test/api/unit/libs/items/utils.test.js
Normal file
@@ -0,0 +1,113 @@
|
||||
/* eslint-disable camelcase */
|
||||
import {
|
||||
validateItemPath,
|
||||
getDefaultOwnedGear,
|
||||
castItemVal,
|
||||
} from '../../../../../website/server/libs/items/utils';
|
||||
|
||||
describe('Items Utils', () => {
|
||||
describe('getDefaultOwnedGear', () => {
|
||||
it('clones the result object', () => {
|
||||
const res1 = getDefaultOwnedGear();
|
||||
res1.extraProperty = true;
|
||||
|
||||
const res2 = getDefaultOwnedGear();
|
||||
expect(res2).not.to.have.property('extraProperty');
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateItemPath', () => {
|
||||
it('returns false if not an item path', () => {
|
||||
expect(validateItemPath('notitems.gear.owned.item')).to.equal(false);
|
||||
});
|
||||
|
||||
it('returns true if a valid schema path', () => {
|
||||
expect(validateItemPath('items.gear.equipped.weapon')).to.equal(true);
|
||||
expect(validateItemPath('items.currentPet')).to.equal(true);
|
||||
expect(validateItemPath('items.special.snowball')).to.equal(true);
|
||||
});
|
||||
|
||||
it('works with owned gear paths', () => {
|
||||
expect(validateItemPath('items.gear.owned.head_armoire_crownOfHearts')).to.equal(true);
|
||||
expect(validateItemPath('items.gear.owned.head_invalid')).to.equal(false);
|
||||
});
|
||||
|
||||
it('works with pets paths', () => {
|
||||
expect(validateItemPath('items.pets.Wolf-CottonCandyPink')).to.equal(true);
|
||||
expect(validateItemPath('items.pets.Wolf-Invalid')).to.equal(false);
|
||||
});
|
||||
|
||||
it('works with eggs paths', () => {
|
||||
expect(validateItemPath('items.eggs.LionCub')).to.equal(true);
|
||||
expect(validateItemPath('items.eggs.Armadillo')).to.equal(true);
|
||||
expect(validateItemPath('items.eggs.NotAnArmadillo')).to.equal(false);
|
||||
});
|
||||
|
||||
it('works with hatching potions paths', () => {
|
||||
expect(validateItemPath('items.hatchingPotions.Base')).to.equal(true);
|
||||
expect(validateItemPath('items.hatchingPotions.StarryNight')).to.equal(true);
|
||||
expect(validateItemPath('items.hatchingPotions.Invalid')).to.equal(false);
|
||||
});
|
||||
|
||||
it('works with food paths', () => {
|
||||
expect(validateItemPath('items.food.Cake_Base')).to.equal(true);
|
||||
expect(validateItemPath('items.food.Cake_Invalid')).to.equal(false);
|
||||
});
|
||||
|
||||
it('works with mounts paths', () => {
|
||||
expect(validateItemPath('items.mounts.Cactus-Base')).to.equal(true);
|
||||
expect(validateItemPath('items.mounts.Aether-Invisible')).to.equal(true);
|
||||
expect(validateItemPath('items.mounts.Aether-Invalid')).to.equal(false);
|
||||
});
|
||||
|
||||
it('works with quests paths', () => {
|
||||
expect(validateItemPath('items.quests.atom3')).to.equal(true);
|
||||
expect(validateItemPath('items.quests.invalid')).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('castItemVal', () => {
|
||||
it('returns the item val untouched if not an item path', () => {
|
||||
expect(castItemVal('notitems.gear.owned.item', 'a string')).to.equal('a string');
|
||||
});
|
||||
|
||||
it('returns the item val untouched if an unsupported path', () => {
|
||||
expect(castItemVal('items.gear.equipped.weapon', 'a string')).to.equal('a string');
|
||||
expect(castItemVal('items.currentPet', 'a string')).to.equal('a string');
|
||||
expect(castItemVal('items.special.snowball', 'a string')).to.equal('a string');
|
||||
});
|
||||
|
||||
it('converts values for pets paths to numbers', () => {
|
||||
expect(castItemVal('items.pets.Wolf-CottonCandyPink', '5')).to.equal(5);
|
||||
expect(castItemVal('items.pets.Wolf-Invalid', '5')).to.equal(5);
|
||||
});
|
||||
|
||||
it('converts values for eggs paths to numbers', () => {
|
||||
expect(castItemVal('items.eggs.LionCub', '5')).to.equal(5);
|
||||
expect(castItemVal('items.eggs.Armadillo', '5')).to.equal(5);
|
||||
expect(castItemVal('items.eggs.NotAnArmadillo', '5')).to.equal(5);
|
||||
});
|
||||
|
||||
it('converts values for hatching potions paths to numbers', () => {
|
||||
expect(castItemVal('items.hatchingPotions.Base', '5')).to.equal(5);
|
||||
expect(castItemVal('items.hatchingPotions.StarryNight', '5')).to.equal(5);
|
||||
expect(castItemVal('items.hatchingPotions.Invalid', '5')).to.equal(5);
|
||||
});
|
||||
|
||||
it('converts values for food paths to numbers', () => {
|
||||
expect(castItemVal('items.food.Cake_Base', '5')).to.equal(5);
|
||||
expect(castItemVal('items.food.Cake_Invalid', '5')).to.equal(5);
|
||||
});
|
||||
|
||||
it('converts values for mounts paths to numbers', () => {
|
||||
expect(castItemVal('items.mounts.Cactus-Base', '5')).to.equal(5);
|
||||
expect(castItemVal('items.mounts.Aether-Invisible', '5')).to.equal(5);
|
||||
expect(castItemVal('items.mounts.Aether-Invalid', '5')).to.equal(5);
|
||||
});
|
||||
|
||||
it('converts values for quests paths to numbers', () => {
|
||||
expect(castItemVal('items.quests.atom3', '5')).to.equal(5);
|
||||
expect(castItemVal('items.quests.invalid', '5')).to.equal(5);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -16,6 +16,7 @@ describe('payments/index', () => {
|
||||
beforeEach(async () => {
|
||||
user = new User();
|
||||
user.profile.name = 'sender';
|
||||
user.auth.local.username = 'sender';
|
||||
await user.save();
|
||||
|
||||
group = generateGroup({
|
||||
|
||||
@@ -32,6 +32,7 @@ describe('slack', () => {
|
||||
},
|
||||
message: {
|
||||
id: 'chat-id',
|
||||
username: 'author',
|
||||
user: 'Author',
|
||||
uuid: 'author-id',
|
||||
text: 'some text',
|
||||
@@ -50,11 +51,11 @@ describe('slack', () => {
|
||||
|
||||
expect(IncomingWebhook.prototype.send).to.be.calledOnce;
|
||||
expect(IncomingWebhook.prototype.send).to.be.calledWith({
|
||||
text: 'flagger (flagger-id; language: flagger-lang) flagged a message',
|
||||
text: 'flagger (flagger-id; language: flagger-lang) flagged a group message',
|
||||
attachments: [{
|
||||
fallback: 'Flag Message',
|
||||
color: 'danger',
|
||||
author_name: `Author - author@example.com - author-id\n${timestamp}`,
|
||||
author_name: `@author Author (author@example.com; author-id)\n${timestamp}`,
|
||||
title: 'Flag in Some group - (private guild)',
|
||||
title_link: undefined,
|
||||
text: 'some text',
|
||||
|
||||
@@ -16,7 +16,7 @@ describe('auth middleware', () => {
|
||||
describe('auth with headers', () => {
|
||||
it('allows to specify a list of user field that we do not want to load', (done) => {
|
||||
const authWithHeaders = authWithHeadersFactory({
|
||||
userFieldsToExclude: ['items', 'flags', 'auth.timestamps'],
|
||||
userFieldsToExclude: ['items'],
|
||||
});
|
||||
|
||||
req.headers['x-api-user'] = user._id;
|
||||
@@ -27,11 +27,34 @@ describe('auth middleware', () => {
|
||||
|
||||
const userToJSON = res.locals.user.toJSON();
|
||||
expect(userToJSON.items).to.not.exist;
|
||||
expect(userToJSON.flags).to.not.exist;
|
||||
expect(userToJSON.auth.timestamps).to.not.exist;
|
||||
expect(userToJSON.auth).to.exist;
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('makes sure some fields are always included', (done) => {
|
||||
const authWithHeaders = authWithHeadersFactory({
|
||||
userFieldsToExclude: [
|
||||
'items', 'auth.timestamps',
|
||||
'preferences', 'notifications', '_id', 'flags', 'auth', // these are always loaded
|
||||
],
|
||||
});
|
||||
|
||||
req.headers['x-api-user'] = user._id;
|
||||
req.headers['x-api-key'] = user.apiToken;
|
||||
|
||||
authWithHeaders(req, res, (err) => {
|
||||
if (err) return done(err);
|
||||
|
||||
const userToJSON = res.locals.user.toJSON();
|
||||
expect(userToJSON.items).to.not.exist;
|
||||
expect(userToJSON.auth.timestamps).to.exist;
|
||||
expect(userToJSON.auth).to.exist;
|
||||
expect(userToJSON.notifications).to.exist;
|
||||
expect(userToJSON.preferences).to.exist;
|
||||
expect(userToJSON._id).to.exist;
|
||||
expect(userToJSON.flags).to.exist;
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import moment from 'moment';
|
||||
import { v4 as generateUUID } from 'uuid';
|
||||
import validator from 'validator';
|
||||
import { sleep } from '../../../helpers/api-unit.helper';
|
||||
import { sleep, translationCheck } from '../../../helpers/api-unit.helper';
|
||||
import {
|
||||
SPAM_MESSAGE_LIMIT,
|
||||
SPAM_MIN_EXEMPT_CONTRIB_LEVEL,
|
||||
@@ -271,7 +271,16 @@ describe('Group Model', () => {
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledOnce;
|
||||
expect(Group.prototype.sendChat).to.be.calledWith('`Participating Member attacks Wailing Whale for 5.0 damage.` `Wailing Whale attacks party for 7.5 damage.`');
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: '`Participating Member attacks Wailing Whale for 5.0 damage. Wailing Whale attacks party for 7.5 damage.`',
|
||||
info: {
|
||||
bossDamage: '7.5',
|
||||
quest: 'whale',
|
||||
type: 'boss_damage',
|
||||
user: 'Participating Member',
|
||||
userDamage: '5.0',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('applies damage only to participating members of party', async () => {
|
||||
@@ -344,7 +353,10 @@ describe('Group Model', () => {
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledTwice;
|
||||
expect(Group.prototype.sendChat).to.be.calledWith('`You defeated Wailing Whale! Questing party members receive the rewards of victory.`');
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: '`You defeated Wailing Whale! Questing party members receive the rewards of victory.`',
|
||||
info: { quest: 'whale', type: 'boss_defeated' },
|
||||
});
|
||||
});
|
||||
|
||||
it('calls finishQuest when boss has <= 0 hp', async () => {
|
||||
@@ -387,7 +399,10 @@ describe('Group Model', () => {
|
||||
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledWith(quest.boss.rage.effect('en'));
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: quest.boss.rage.effect('en'),
|
||||
info: { quest: 'trex_undead', type: 'boss_rage' },
|
||||
});
|
||||
expect(party.quest.progress.hp).to.eql(383.5);
|
||||
expect(party.quest.progress.rage).to.eql(0);
|
||||
});
|
||||
@@ -437,7 +452,10 @@ describe('Group Model', () => {
|
||||
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledWith(quest.boss.rage.effect('en'));
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: quest.boss.rage.effect('en'),
|
||||
info: { quest: 'lostMasterclasser4', type: 'boss_rage' },
|
||||
});
|
||||
expect(party.quest.progress.rage).to.eql(0);
|
||||
|
||||
let drainedUser = await User.findById(participatingMember._id);
|
||||
@@ -488,7 +506,15 @@ describe('Group Model', () => {
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledOnce;
|
||||
expect(Group.prototype.sendChat).to.be.calledWith('`Participating Member found 5 Bars of Soap.`');
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: '`Participating Member found 5 Bars of Soap.`',
|
||||
info: {
|
||||
items: { soapBars: 5 },
|
||||
quest: 'atom1',
|
||||
type: 'user_found_items',
|
||||
user: 'Participating Member',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('sends a chat message if no progress is made', async () => {
|
||||
@@ -499,7 +525,15 @@ describe('Group Model', () => {
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledOnce;
|
||||
expect(Group.prototype.sendChat).to.be.calledWith('`Participating Member found 0 Bars of Soap.`');
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: '`Participating Member found 0 Bars of Soap.`',
|
||||
info: {
|
||||
items: { soapBars: 0 },
|
||||
quest: 'atom1',
|
||||
type: 'user_found_items',
|
||||
user: 'Participating Member',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('sends a chat message if no progress is made on quest with multiple items', async () => {
|
||||
@@ -516,9 +550,15 @@ describe('Group Model', () => {
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledOnce;
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch(/`Participating Member found/);
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch(/0 Blue Fins/);
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch(/0 Fire Coral/);
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: '`Participating Member found 0 Fire Coral, 0 Blue Fins.`',
|
||||
info: {
|
||||
items: { blueFins: 0, fireCoral: 0 },
|
||||
quest: 'dilatoryDistress1',
|
||||
type: 'user_found_items',
|
||||
user: 'Participating Member',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('handles collection quests with multiple items', async () => {
|
||||
@@ -535,8 +575,14 @@ describe('Group Model', () => {
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledOnce;
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch(/`Participating Member found/);
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch(/\d* (Tracks|Broken Twigs)/);
|
||||
expect(Group.prototype.sendChat).to.be.calledWithMatch({
|
||||
message: sinon.match(/`Participating Member found/).and(sinon.match(/\d* (Tracks|Broken Twigs)/)),
|
||||
info: {
|
||||
quest: 'evilsanta2',
|
||||
type: 'user_found_items',
|
||||
user: 'Participating Member',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('sends message about victory', async () => {
|
||||
@@ -547,7 +593,10 @@ describe('Group Model', () => {
|
||||
party = await Group.findOne({_id: party._id});
|
||||
|
||||
expect(Group.prototype.sendChat).to.be.calledTwice;
|
||||
expect(Group.prototype.sendChat).to.be.calledWith('`All items found! Party has received their rewards.`');
|
||||
expect(Group.prototype.sendChat).to.be.calledWith({
|
||||
message: '`All items found! Party has received their rewards.`',
|
||||
info: { type: 'all_items_found' },
|
||||
});
|
||||
});
|
||||
|
||||
it('calls finishQuest when all items are found', async () => {
|
||||
@@ -718,6 +767,258 @@ describe('Group Model', () => {
|
||||
expect(res.t).to.not.be.called;
|
||||
});
|
||||
});
|
||||
|
||||
describe('translateSystemMessages', () => {
|
||||
it('translate quest_start', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'quest_start',
|
||||
quest: 'basilist',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate boss_damage', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'boss_damage',
|
||||
user: questLeader.profile.name,
|
||||
quest: 'basilist',
|
||||
userDamage: 15.3,
|
||||
bossDamage: 3.7,
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate boss_dont_attack', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'boss_dont_attack',
|
||||
user: questLeader.profile.name,
|
||||
quest: 'basilist',
|
||||
userDamage: 15.3,
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate boss_rage', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'boss_rage',
|
||||
quest: 'lostMasterclasser3',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate boss_defeated', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'boss_defeated',
|
||||
quest: 'lostMasterclasser3',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate user_found_items', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'user_found_items',
|
||||
user: questLeader.profile.name,
|
||||
quest: 'lostMasterclasser1',
|
||||
items: {
|
||||
ancientTome: 3,
|
||||
forbiddenTome: 2,
|
||||
hiddenTome: 1,
|
||||
},
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate all_items_found', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'all_items_found',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate spell_cast_party', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'spell_cast_party',
|
||||
user: questLeader.profile.name,
|
||||
class: 'wizard',
|
||||
spell: 'earth',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate spell_cast_user', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'spell_cast_user',
|
||||
user: questLeader.profile.name,
|
||||
class: 'special',
|
||||
spell: 'snowball',
|
||||
target: participatingMember.profile.name,
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate quest_cancel', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'quest_cancel',
|
||||
user: questLeader.profile.name,
|
||||
quest: 'basilist',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate quest_abort', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'quest_abort',
|
||||
user: questLeader.profile.name,
|
||||
quest: 'basilist',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate tavern_quest_completed', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'tavern_quest_completed',
|
||||
quest: 'stressbeast',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate tavern_boss_rage_tired', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'tavern_boss_rage_tired',
|
||||
quest: 'stressbeast',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate tavern_boss_rage', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'tavern_boss_rage',
|
||||
quest: 'dysheartener',
|
||||
scene: 'market',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate tavern_boss_desperation', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'tavern_boss_desperation',
|
||||
quest: 'stressbeast',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
|
||||
it('translate claim_task', async () => {
|
||||
questLeader.preferences.language = 'en';
|
||||
party.chat = [{
|
||||
info: {
|
||||
type: 'claim_task',
|
||||
user: questLeader.profile.name,
|
||||
task: 'Feed the pet',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
translationCheck(toJSON.chat[0].text);
|
||||
});
|
||||
});
|
||||
|
||||
describe('toJSONCleanChat', () => {
|
||||
it('shows messages with 1 flag to non-admins', async () => {
|
||||
party.chat = [{
|
||||
flagCount: 1,
|
||||
info: {
|
||||
type: 'quest_start',
|
||||
quest: 'basilist',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
expect(toJSON.chat.length).to.equal(1);
|
||||
});
|
||||
|
||||
it('shows messages with >= 2 flag to admins', async () => {
|
||||
party.chat = [{
|
||||
flagCount: 3,
|
||||
info: {
|
||||
type: 'quest_start',
|
||||
quest: 'basilist',
|
||||
},
|
||||
}];
|
||||
const admin = new User({'contributor.admin': true});
|
||||
let toJSON = await Group.toJSONCleanChat(party, admin);
|
||||
expect(toJSON.chat.length).to.equal(1);
|
||||
});
|
||||
|
||||
it('doesn\'t show flagged messages to non-admins', async () => {
|
||||
party.chat = [{
|
||||
flagCount: 3,
|
||||
info: {
|
||||
type: 'quest_start',
|
||||
quest: 'basilist',
|
||||
},
|
||||
}];
|
||||
let toJSON = await Group.toJSONCleanChat(party, questLeader);
|
||||
expect(toJSON.chat.length).to.equal(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('Instance Methods', () => {
|
||||
@@ -1007,20 +1308,22 @@ describe('Group Model', () => {
|
||||
});
|
||||
|
||||
it('formats message', () => {
|
||||
const chatMessage = party.sendChat('a new message', {
|
||||
_id: 'user-id',
|
||||
profile: { name: 'user name' },
|
||||
contributor: {
|
||||
toObject () {
|
||||
return 'contributor object';
|
||||
const chatMessage = party.sendChat({
|
||||
message: 'a new message', user: {
|
||||
_id: 'user-id',
|
||||
profile: { name: 'user name' },
|
||||
contributor: {
|
||||
toObject () {
|
||||
return 'contributor object';
|
||||
},
|
||||
},
|
||||
},
|
||||
backer: {
|
||||
toObject () {
|
||||
return 'backer object';
|
||||
backer: {
|
||||
toObject () {
|
||||
return 'backer object';
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}}
|
||||
);
|
||||
|
||||
const chat = chatMessage;
|
||||
|
||||
@@ -1037,7 +1340,7 @@ describe('Group Model', () => {
|
||||
});
|
||||
|
||||
it('formats message as system if no user is passed in', () => {
|
||||
const chat = party.sendChat('a system message');
|
||||
const chat = party.sendChat({message: 'a system message'});
|
||||
|
||||
expect(chat.text).to.eql('a system message');
|
||||
expect(validator.isUUID(chat.id)).to.eql(true);
|
||||
@@ -1052,7 +1355,7 @@ describe('Group Model', () => {
|
||||
});
|
||||
|
||||
it('updates users about new messages in party', () => {
|
||||
party.sendChat('message');
|
||||
party.sendChat({message: 'message'});
|
||||
|
||||
expect(User.update).to.be.calledOnce;
|
||||
expect(User.update).to.be.calledWithMatch({
|
||||
@@ -1066,7 +1369,7 @@ describe('Group Model', () => {
|
||||
type: 'guild',
|
||||
});
|
||||
|
||||
group.sendChat('message');
|
||||
group.sendChat({message: 'message'});
|
||||
|
||||
expect(User.update).to.be.calledOnce;
|
||||
expect(User.update).to.be.calledWithMatch({
|
||||
@@ -1076,7 +1379,7 @@ describe('Group Model', () => {
|
||||
});
|
||||
|
||||
it('does not send update to user that sent the message', () => {
|
||||
party.sendChat('message', {_id: 'user-id', profile: { name: 'user' }});
|
||||
party.sendChat({message: 'message', user: {_id: 'user-id', profile: { name: 'user' }}});
|
||||
|
||||
expect(User.update).to.be.calledOnce;
|
||||
expect(User.update).to.be.calledWithMatch({
|
||||
@@ -1088,7 +1391,7 @@ describe('Group Model', () => {
|
||||
it('skips sending new message notification for guilds with > 5000 members', () => {
|
||||
party.memberCount = 5001;
|
||||
|
||||
party.sendChat('message');
|
||||
party.sendChat({message: 'message'});
|
||||
|
||||
expect(User.update).to.not.be.called;
|
||||
});
|
||||
@@ -1096,7 +1399,7 @@ describe('Group Model', () => {
|
||||
it('skips sending messages to the tavern', () => {
|
||||
party._id = TAVERN_ID;
|
||||
|
||||
party.sendChat('message');
|
||||
party.sendChat({message: 'message'});
|
||||
|
||||
expect(User.update).to.not.be.called;
|
||||
});
|
||||
@@ -1431,7 +1734,7 @@ describe('Group Model', () => {
|
||||
let quest;
|
||||
|
||||
beforeEach(() => {
|
||||
quest = questScrolls.whale;
|
||||
quest = questScrolls.armadillo;
|
||||
party.quest.key = quest.key;
|
||||
party.quest.active = false;
|
||||
party.quest.leader = questLeader._id;
|
||||
@@ -1579,6 +1882,36 @@ describe('Group Model', () => {
|
||||
expect(updatedSleepingParticipatingMember.achievements.lostMasterclasser).to.not.eql(true);
|
||||
});
|
||||
|
||||
it('gives out other pet-related quest achievements', async () => {
|
||||
quest = questScrolls.rock;
|
||||
party.quest.key = quest.key;
|
||||
|
||||
questLeader.achievements.quests = {
|
||||
mayhemMistiflying1: 1,
|
||||
yarn: 1,
|
||||
mayhemMistiflying2: 1,
|
||||
egg: 1,
|
||||
mayhemMistiflying3: 1,
|
||||
slime: 2,
|
||||
};
|
||||
await questLeader.save();
|
||||
await party.finishQuest(quest);
|
||||
|
||||
let [
|
||||
updatedLeader,
|
||||
updatedParticipatingMember,
|
||||
updatedSleepingParticipatingMember,
|
||||
] = await Promise.all([
|
||||
User.findById(questLeader._id).exec(),
|
||||
User.findById(participatingMember._id).exec(),
|
||||
User.findById(sleepingParticipatingMember._id).exec(),
|
||||
]);
|
||||
|
||||
expect(updatedLeader.achievements.mindOverMatter).to.eql(true);
|
||||
expect(updatedParticipatingMember.achievements.mindOverMatter).to.not.eql(true);
|
||||
expect(updatedSleepingParticipatingMember.achievements.mindOverMatter).to.not.eql(true);
|
||||
});
|
||||
|
||||
it('gives xp and gold', async () => {
|
||||
await party.finishQuest(quest);
|
||||
|
||||
@@ -1715,13 +2048,13 @@ describe('Group Model', () => {
|
||||
questLeader = await User.findById(questLeader._id);
|
||||
participatingMember = await User.findById(participatingMember._id);
|
||||
|
||||
expect(questLeader.party.quest.completed).to.eql('whale');
|
||||
expect(questLeader.party.quest.completed).to.eql('armadillo');
|
||||
expect(questLeader.party.quest.progress.up).to.eql(10);
|
||||
expect(questLeader.party.quest.progress.down).to.eql(8);
|
||||
expect(questLeader.party.quest.progress.collectedItems).to.eql(5);
|
||||
expect(questLeader.party.quest.RSVPNeeded).to.eql(false);
|
||||
|
||||
expect(participatingMember.party.quest.completed).to.eql('whale');
|
||||
expect(participatingMember.party.quest.completed).to.eql('armadillo');
|
||||
expect(participatingMember.party.quest.progress.up).to.eql(10);
|
||||
expect(participatingMember.party.quest.progress.down).to.eql(8);
|
||||
expect(participatingMember.party.quest.progress.collectedItems).to.eql(5);
|
||||
@@ -1928,7 +2261,7 @@ describe('Group Model', () => {
|
||||
|
||||
await guild.save();
|
||||
|
||||
const groupMessage = guild.sendChat('Test message.');
|
||||
const groupMessage = guild.sendChat({message: 'Test message.'});
|
||||
await groupMessage.save();
|
||||
|
||||
await sleep();
|
||||
|
||||
Reference in New Issue
Block a user