Merge branch 'develop' of https://github.com/HabitRPG/habitica into negue/flagpm

# Conflicts:
#	website/client/store/actions/chat.js
This commit is contained in:
negue
2018-06-25 18:47:47 +02:00
601 changed files with 31507 additions and 28325 deletions

View File

@@ -20,8 +20,9 @@ env:
- DISABLE_REQUEST_LOGGING=true
matrix:
- TEST="lint"
- TEST="test:api-v3:unit" REQUIRES_SERVER=true COVERAGE=true
- TEST="test:api:unit" REQUIRES_SERVER=true COVERAGE=true
- TEST="test:api-v3:integration" REQUIRES_SERVER=true COVERAGE=true
- TEST="test:api-v4:integration" REQUIRES_SERVER=true COVERAGE=true
- TEST="test:sanity"
- TEST="test:content" COVERAGE=true
- TEST="test:common" COVERAGE=true

View File

@@ -17,7 +17,7 @@ RUN npm install -g gulp-cli mocha
# Clone Habitica repo and install dependencies
RUN mkdir -p /usr/src/habitrpg
WORKDIR /usr/src/habitrpg
RUN git clone --branch v4.44.2 https://github.com/HabitRPG/habitica.git /usr/src/habitrpg
RUN git clone --branch v4.48.0 https://github.com/HabitRPG/habitica.git /usr/src/habitrpg
RUN npm install
RUN gulp build:prod --force

View File

@@ -112,5 +112,6 @@
"CLOUDKARAFKA_USERNAME": "",
"CLOUDKARAFKA_PASSWORD": "",
"CLOUDKARAFKA_TOPIC_PREFIX": ""
}
},
"MIGRATION_CONNECT_STRING": "mongodb://localhost:27017/habitrpg?auto_reconnect=true"
}

View File

@@ -0,0 +1,100 @@
import max from 'lodash/max';
import mean from 'lodash/mean';
import monk from 'monk';
import round from 'lodash/round';
import sum from 'lodash/sum';
/*
* Output data on subscribers' task histories, formatted for CSV.
* User ID,Count of Dailies,Count of Habits,Total History Size,Max History Size,Mean History Size,Median History Size
*/
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
let dbUsers = monk(connectionString).get('users', { castIds: false });
let dbTasks = monk(connectionString).get('tasks', { castIds: false });
function usersReport () {
let allHistoryLengths = [];
console.info('User ID,Count of Dailies,Count of Habits,Total History Size,Max History Size,Mean History Size,Median History Size');
dbUsers.find(
{
$and:
[
{'purchased.plan.planId': {$ne:null}},
{'purchased.plan.planId': {$ne:''}},
],
$or:
[
{'purchased.plan.dateTerminated': null},
{'purchased.plan.dateTerminated': ''},
{'purchased.plan.dateTerminated': {$gt:new Date()}},
],
},
{
fields: {_id: 1},
}
).each((user, {close, pause, resume}) => {
let historyLengths = [];
let habitCount = 0;
let dailyCount = 0;
pause();
return dbTasks.find(
{
userId: user._id,
$or:
[
{type: 'habit'},
{type: 'daily'},
],
},
{
fields: {
type: 1,
history: 1,
},
}
).each((task) => {
if (task.type === 'habit') {
habitCount++;
}
if (task.type === 'daily') {
dailyCount++;
}
if (task.history.length > 0) {
allHistoryLengths.push(task.history.length);
historyLengths.push(task.history.length);
}
}).then(() => {
const totalHistory = sum(historyLengths);
const maxHistory = historyLengths.length > 0 ? max(historyLengths) : 0;
const meanHistory = historyLengths.length > 0 ? round(mean(historyLengths)) : 0;
const medianHistory = historyLengths.length > 0 ? median(historyLengths) : 0;
console.info(`${user._id},${dailyCount},${habitCount},${totalHistory},${maxHistory},${meanHistory},${medianHistory}`);
resume();
});
}).then(() => {
console.info(`Total Subscriber History Entries: ${sum(allHistoryLengths)}`);
console.info(`Largest History Size: ${max(allHistoryLengths)}`);
console.info(`Mean History Size: ${round(mean(allHistoryLengths))}`);
console.info(`Median History Size: ${median(allHistoryLengths)}`);
return process.exit(0);
});
}
function median(values) { // https://gist.github.com/caseyjustus/1166258
values.sort( function(a,b) {return a - b;} );
var half = Math.floor(values.length/2);
if (values.length % 2) {
return values[half];
}
else {
return (values[half-1] + values[half]) / 2.0;
}
}
module.exports = usersReport;

View File

@@ -165,9 +165,9 @@ gulp.task('test:content:safe', gulp.series('test:prepare:build', (cb) => {
pipe(runner);
}));
gulp.task('test:api-v3:unit', (done) => {
gulp.task('test:api:unit', (done) => {
let runner = exec(
testBin('node_modules/.bin/istanbul cover --dir coverage/api-v3-unit node_modules/mocha/bin/_mocha -- test/api/v3/unit --recursive --require ./test/helpers/start-server'),
testBin('node_modules/.bin/istanbul cover --dir coverage/api-unit node_modules/mocha/bin/_mocha -- test/api/unit --recursive --require ./test/helpers/start-server'),
(err) => {
if (err) {
process.exit(1);
@@ -179,8 +179,8 @@ gulp.task('test:api-v3:unit', (done) => {
pipe(runner);
});
gulp.task('test:api-v3:unit:watch', () => {
return gulp.watch(['website/server/libs/*', 'test/api/v3/unit/**/*', 'website/server/controllers/**/*'], gulp.series('test:api-v3:unit', done => done()));
gulp.task('test:api:unit:watch', () => {
return gulp.watch(['website/server/libs/*', 'test/api/v3/unit/**/*', 'website/server/controllers/**/*'], gulp.series('test:api:unit', done => done()));
});
gulp.task('test:api-v3:integration', (done) => {
@@ -215,17 +215,43 @@ gulp.task('test:api-v3:integration:separate-server', (done) => {
pipe(runner);
});
gulp.task('test:api-v4:integration', (done) => {
let runner = exec(
testBin('node_modules/.bin/istanbul cover --dir coverage/api-v4-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v4 --recursive --require ./test/helpers/start-server'),
{maxBuffer: 500 * 1024},
(err) => {
if (err) {
process.exit(1);
}
done();
}
);
pipe(runner);
});
gulp.task('test:api-v4:integration:separate-server', (done) => {
let runner = exec(
testBin('mocha test/api/v4 --recursive --require ./test/helpers/start-server', 'LOAD_SERVER=0'),
{maxBuffer: 500 * 1024},
(err) => done(err)
);
pipe(runner);
});
gulp.task('test', gulp.series(
'test:sanity',
'test:content',
'test:common',
'test:api-v3:unit',
'test:api:unit',
'test:api-v3:integration',
'test:api-v4:integration',
done => done()
));
gulp.task('test:api-v3', gulp.series(
'test:api-v3:unit',
'test:api:unit',
'test:api-v3:integration',
done => done()
));

View File

@@ -0,0 +1,107 @@
import monk from 'monk';
import nconf from 'nconf';
import stripePayments from '../../website/server/libs/payments/stripe';
/*
* Ensure that group plan billing is accurate by doing the following:
* 1. Correct the memberCount in all paid groups whose counts are wrong
* 2. Where the above uses Stripe, update their subscription counts in Stripe
*
* Provides output on what groups were fixed, which can be piped to CSV.
*/
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
let dbGroups = monk(CONNECTION_STRING).get('groups', { castIds: false });
let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
async function fixGroupPlanMembers () {
console.info('Group ID, Customer ID, Plan ID, Quantity, Recorded Member Count, Actual Member Count');
let groupPlanCount = 0;
let fixedGroupCount = 0;
dbGroups.find(
{
$and:
[
{'purchased.plan.planId': {$ne: null}},
{'purchased.plan.planId': {$ne: ''}},
{'purchased.plan.customerId': {$ne: 'cus_9f0DV4g7WHRzpM'}}, // Demo groups
{'purchased.plan.customerId': {$ne: 'cus_9maalqDOFTrvqx'}},
],
$or:
[
{'purchased.plan.dateTerminated': null},
{'purchased.plan.dateTerminated': ''},
],
},
{
fields: {
memberCount: 1,
'purchased.plan': 1,
},
}
).each(async (group, {close, pause, resume}) => { // eslint-disable-line no-unused-vars
pause();
groupPlanCount++;
const canonicalMemberCount = await dbUsers.count(
{
$or:
[
{'party._id': group._id},
{guilds: group._id},
],
}
);
const incorrectMemberCount = group.memberCount !== canonicalMemberCount;
const isMonthlyPlan = group.purchased.plan.planId === 'group_monthly';
const quantityMismatch = group.purchased.plan.quantity !== group.memberCount + 2;
const incorrectQuantity = isMonthlyPlan && quantityMismatch;
if (!incorrectMemberCount && !incorrectQuantity) {
resume();
return;
}
console.info(`${group._id}, ${group.purchased.plan.customerId}, ${group.purchased.plan.planId}, ${group.purchased.plan.quantity}, ${group.memberCount}, ${canonicalMemberCount}`);
const groupUpdate = await dbGroups.update(
{ _id: group._id },
{
$set: {
memberCount: canonicalMemberCount,
},
}
);
if (!groupUpdate) return;
fixedGroupCount++;
if (group.purchased.plan.paymentMethod === 'Stripe') {
await stripePayments.chargeForAdditionalGroupMember(group);
await dbGroups.update(
{_id: group._id},
{$set: {'purchased.plan.quantity': canonicalMemberCount + 2}}
);
}
if (incorrectQuantity) {
await dbGroups.update(
{_id: group._id},
{$set: {'purchased.plan.quantity': canonicalMemberCount + 2}}
);
}
resume();
}).then(() => {
console.info(`Fixed ${fixedGroupCount} out of ${groupPlanCount} active Group Plans`);
return process.exit(0);
}).catch((err) => {
console.log(err);
return process.exit(1);
});
}
module.exports = fixGroupPlanMembers;

View File

@@ -17,5 +17,5 @@ function setUpServer () {
setUpServer();
// Replace this with your migration
const processUsers = require('./users/mystery-items.js');
const processUsers = require('./tasks/habits-one-history-entry-per-day-challenges.js');
processUsers();

View File

@@ -0,0 +1,138 @@
// const migrationName = 'habits-one-history-entry-per-day';
// const authorName = 'paglias'; // in case script author needs to know when their ...
// const authorUuid = 'ed4c688c-6652-4a92-9d03-a5a79844174a'; // ... own data is done
/*
* Iterates over all habits and condense multiple history entries for the same day into a single entry
*/
const monk = require('monk');
const _ = require('lodash');
const moment = require('moment');
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
const dbTasks = monk(connectionString).get('tasks', { castIds: false });
function processChallengeHabits (lastId) {
let query = {
'challenge.id': {$exists: true},
userId: {$exists: false},
type: 'habit',
};
if (lastId) {
query._id = {
$gt: lastId,
};
}
dbTasks.find(query, {
sort: {_id: 1},
limit: 500,
})
.then(updateChallengeHabits)
.catch((err) => {
console.log(err);
return exiting(1, `ERROR! ${ err}`);
});
}
let progressCount = 1000;
let count = 0;
function updateChallengeHabits (habits) {
if (!habits || habits.length === 0) {
console.warn('All appropriate challenge habits found and modified.');
displayData();
return;
}
let habitsPromises = habits.map(updateChallengeHabit);
let lastHabit = habits[habits.length - 1];
return Promise.all(habitsPromises)
.then(() => {
return processChallengeHabits(lastHabit._id);
});
}
function updateChallengeHabit (habit) {
count++;
if (habit && habit.history && habit.history.length > 0) {
// First remove missing entries
habit.history = habit.history.filter(entry => Boolean(entry));
habit.history = _.chain(habit.history)
// processes all entries to identify an up or down score
.forEach((entry, index) => {
if (index === 0) { // first entry doesn't have a previous one
// first value < 0 identifies a negative score as the first action
entry.scoreDirection = entry.value >= 0 ? 'up' : 'down';
} else {
// could be missing if the previous entry was null and thus excluded
const previousEntry = habit.history[index - 1];
const previousValue = previousEntry.value;
entry.scoreDirection = entry.value > previousValue ? 'up' : 'down';
}
})
.groupBy(entry => { // group entries by aggregateBy
return moment(entry.date).format('YYYYMMDD');
})
.toPairs() // [key, entry]
.sortBy(([key]) => key) // sort by date
.map(keyEntryPair => {
let entries = keyEntryPair[1]; // 1 is entry, 0 is key
let scoredUp = 0;
let scoredDown = 0;
entries.forEach(entry => {
if (entry.scoreDirection === 'up') {
scoredUp += 1;
} else {
scoredDown += 1;
}
// delete the unnecessary scoreDirection and scoreNotes prop
delete entry.scoreDirection;
delete entry.scoreNotes;
});
return {
date: Number(entries[entries.length - 1].date), // keep last value
value: entries[entries.length - 1].value, // keep last value,
scoredUp,
scoredDown,
};
})
.value();
return dbTasks.update({_id: habit._id}, {
$set: {history: habit.history},
});
}
if (count % progressCount === 0) console.warn(`${count } habits processed`);
}
function displayData () {
console.warn(`\n${ count } tasks processed\n`);
return exiting(0);
}
function exiting (code, msg) {
code = code || 0; // 0 = success
if (code && !msg) {
msg = 'ERROR!';
}
if (msg) {
if (code) {
console.error(msg);
} else {
console.log(msg);
}
}
process.exit(code);
}
module.exports = processChallengeHabits;

View File

@@ -0,0 +1,156 @@
// const migrationName = 'habits-one-history-entry-per-day';
const authorName = 'paglias'; // in case script author needs to know when their ...
const authorUuid = 'ed4c688c-6652-4a92-9d03-a5a79844174a'; // ... own data is done
/*
* Iterates over all habits and condense multiple history entries for the same day into a single entry
*/
const monk = require('monk');
const _ = require('lodash');
const moment = require('moment');
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
const dbTasks = monk(connectionString).get('tasks', { castIds: false });
const dbUsers = monk(connectionString).get('users', { castIds: false });
function processUsers (lastId) {
let query = {};
if (lastId) {
query._id = {
$gt: lastId,
};
}
dbUsers.find(query, {
sort: {_id: 1},
limit: 50, // just 50 users per time since we have to process all their habits as well
fields: ['_id', 'preferences.timezoneOffset', 'preferences.dayStart'],
})
.then(updateUsers)
.catch((err) => {
console.log(err);
return exiting(1, `ERROR! ${ err}`);
});
}
let progressCount = 1000;
let count = 0;
function updateUsers (users) {
if (!users || users.length === 0) {
console.warn('All appropriate users and their tasks found and modified.');
displayData();
return;
}
let usersPromises = users.map(updateUser);
let lastUser = users[users.length - 1];
return Promise.all(usersPromises)
.then(() => {
return processUsers(lastUser._id);
});
}
function updateHabit (habit, timezoneOffset, dayStart) {
if (habit && habit.history && habit.history.length > 0) {
// First remove missing entries
habit.history = habit.history.filter(entry => Boolean(entry));
habit.history = _.chain(habit.history)
// processes all entries to identify an up or down score
.forEach((entry, index) => {
if (index === 0) { // first entry doesn't have a previous one
// first value < 0 identifies a negative score as the first action
entry.scoreDirection = entry.value >= 0 ? 'up' : 'down';
} else {
// could be missing if the previous entry was null and thus excluded
const previousEntry = habit.history[index - 1];
const previousValue = previousEntry.value;
entry.scoreDirection = entry.value > previousValue ? 'up' : 'down';
}
})
.groupBy(entry => { // group entries by aggregateBy
const entryDate = moment(entry.date).zone(timezoneOffset || 0);
if (entryDate.hour() < dayStart) entryDate.subtract(1, 'day');
return entryDate.format('YYYYMMDD');
})
.toPairs() // [key, entry]
.sortBy(([key]) => key) // sort by date
.map(keyEntryPair => {
let entries = keyEntryPair[1]; // 1 is entry, 0 is key
let scoredUp = 0;
let scoredDown = 0;
entries.forEach(entry => {
if (entry.scoreDirection === 'up') {
scoredUp += 1;
} else {
scoredDown += 1;
}
// delete the unnecessary scoreDirection and scoreNotes prop
delete entry.scoreDirection;
delete entry.scoreNotes;
});
return {
date: Number(entries[entries.length - 1].date), // keep last value
value: entries[entries.length - 1].value, // keep last value,
scoredUp,
scoredDown,
};
})
.value();
return dbTasks.update({_id: habit._id}, {
$set: {history: habit.history},
});
}
}
function updateUser (user) {
count++;
const timezoneOffset = user.preferences.timezoneOffset;
const dayStart = user.preferences.dayStart;
if (count % progressCount === 0) console.warn(`${count } ${ user._id}`);
if (user._id === authorUuid) console.warn(`${authorName } being processed`);
return dbTasks.find({
type: 'habit',
userId: user._id,
})
.then(habits => {
return Promise.all(habits.map(habit => updateHabit(habit, timezoneOffset, dayStart)));
})
.catch((err) => {
console.log(err);
return exiting(1, `ERROR! ${ err}`);
});
}
function displayData () {
console.warn(`\n${ count } tasks processed\n`);
return exiting(0);
}
function exiting (code, msg) {
code = code || 0; // 0 = success
if (code && !msg) {
msg = 'ERROR!';
}
if (msg) {
if (code) {
console.error(msg);
} else {
console.log(msg);
}
}
process.exit(code);
}
module.exports = processUsers;

View File

@@ -7,7 +7,7 @@ let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
*/
let monk = require('monk');
let connectionString = 'mongodb://sabrecat:z8e8jyRA8CTofMQ@ds013393-a0.mlab.com:13393/habitica?auto_reconnect=true';
let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true';
let dbTasks = monk(connectionString).get('tasks', { castIds: false });
function processTasks (lastId) {

View File

@@ -1,15 +1,17 @@
const migrationName = 'mystery-items-201805.js'; // Update per month
import monk from 'monk';
import nconf from 'nconf';
const migrationName = 'mystery-items-201806.js'; // Update per month
const authorName = 'Sabe'; // in case script author needs to know when their ...
const authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
/*
* Award this month's mystery items to subscribers
*/
const MYSTERY_ITEMS = ['back_mystery_201805', 'head_mystery_201805'];
const connectionString = 'mongodb://sabrecat:mT1wp9Nf5xUDmV5@ds013393-a0.mlab.com:13393/habitica?auto_reconnect=true';
const MYSTERY_ITEMS = ['armor_mystery_201806', 'head_mystery_201806'];
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
let monk = require('monk');
let dbUsers = monk(connectionString).get('users', { castIds: false });
let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
let UserNotification = require('../../website/server/models/userNotification').model;
function processUsers (lastId) {

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "habitica",
"version": "4.44.3",
"version": "4.48.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,7 +1,7 @@
{
"name": "habitica",
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
"version": "4.44.3",
"version": "4.48.1",
"main": "./website/server/index.js",
"dependencies": {
"@slack/client": "^3.8.1",
@@ -121,9 +121,11 @@
"test": "npm run lint && gulp test && gulp apidoc",
"test:build": "gulp test:prepare:build",
"test:api-v3": "gulp test:api-v3",
"test:api-v3:unit": "gulp test:api-v3:unit",
"test:api:unit": "gulp test:api:unit",
"test:api-v3:integration": "gulp test:api-v3:integration",
"test:api-v3:integration:separate-server": "NODE_ENV=test gulp test:api-v3:integration:separate-server",
"test:api-v4:integration": "gulp test:api-v4:integration",
"test:api-v4:integration:separate-server": "NODE_ENV=test gulp test:api-v4:integration:separate-server",
"test:sanity": "istanbul cover --dir coverage/sanity --report lcovonly node_modules/mocha/bin/_mocha -- test/sanity --recursive",
"test:common": "istanbul cover --dir coverage/common --report lcovonly node_modules/mocha/bin/_mocha -- test/common --recursive",
"test:content": "istanbul cover --dir coverage/content --report lcovonly node_modules/mocha/bin/_mocha -- test/content --recursive",

View File

@@ -1,5 +1,5 @@
/* eslint-disable camelcase */
import analyticsService from '../../../../../website/server/libs/analyticsService';
import analyticsService from '../../../../website/server/libs/analyticsService';
import Amplitude from 'amplitude';
import { Visitor } from 'universal-analytics';

View File

@@ -1,4 +1,4 @@
import apiError from '../../../../../website/server/libs/apiError';
import apiError from '../../../../website/server/libs/apiError';
describe('API Messages', () => {
const message = 'Only public guilds support pagination.';

View File

@@ -1,4 +1,4 @@
import baseModel from '../../../../../website/server/libs/baseModel';
import baseModel from '../../../../website/server/libs/baseModel';
import mongoose from 'mongoose';
describe('Base model plugin', () => {

View File

@@ -1,7 +1,7 @@
import mongoose from 'mongoose';
import {
removeFromArray,
} from '../../../../../website/server/libs/collectionManipulators';
} from '../../../../website/server/libs/collectionManipulators';
describe('Collection Manipulators', () => {
describe('removeFromArray', () => {

View File

@@ -2,15 +2,15 @@
import moment from 'moment';
import nconf from 'nconf';
import requireAgain from 'require-again';
import { recoverCron, cron } from '../../../../../website/server/libs/cron';
import { model as User } from '../../../../../website/server/models/user';
import * as Tasks from '../../../../../website/server/models/task';
import common from '../../../../../website/common';
import analytics from '../../../../../website/server/libs/analyticsService';
import { recoverCron, cron } from '../../../../website/server/libs/cron';
import { model as User } from '../../../../website/server/models/user';
import * as Tasks from '../../../../website/server/models/task';
import common from '../../../../website/common';
import analytics from '../../../../website/server/libs/analyticsService';
// const scoreTask = common.ops.scoreTask;
let pathToCronLib = '../../../../../website/server/libs/cron';
let pathToCronLib = '../../../../website/server/libs/cron';
describe('cron', () => {
let clock = null;

View File

@@ -3,9 +3,9 @@ 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';
import logger from '../../../../website/server/libs/logger';
import { TAVERN_ID } from '../../../../website/server/models/group';
import { defer } from '../../../helpers/api-unit.helper';
function getUser () {
return {
@@ -33,7 +33,7 @@ function getUser () {
}
describe('emails', () => {
let pathToEmailLib = '../../../../../website/server/libs/email';
let pathToEmailLib = '../../../../website/server/libs/email';
describe('sendEmail', () => {
let sendMailSpy;

View File

@@ -1,7 +1,7 @@
import {
encrypt,
decrypt,
} from '../../../../../website/server/libs/encryption';
} from '../../../../website/server/libs/encryption';
describe('encryption', () => {
it('can encrypt and decrypt', () => {

View File

@@ -5,7 +5,7 @@ import {
BadRequest,
InternalServerError,
NotFound,
} from '../../../../../website/server/libs/errors';
} from '../../../../website/server/libs/errors';
describe('Custom Errors', () => {
describe('CustomError', () => {

View File

@@ -2,7 +2,7 @@ import {
translations,
localePath,
langCodes,
} from '../../../../../website/server/libs/i18n';
} from '../../../../website/server/libs/i18n';
import fs from 'fs';
import path from 'path';

View File

@@ -1,8 +1,8 @@
import winston from 'winston';
import logger from '../../../../../website/server/libs/logger';
import logger from '../../../../website/server/libs/logger';
import {
NotFound,
} from '../../../../../website/server/libs//errors';
} from '../../../../website/server/libs//errors';
describe('logger', () => {
let logSpy;

View File

@@ -2,11 +2,11 @@
import {
encrypt,
} from '../../../../../website/server/libs/encryption';
} from '../../../../website/server/libs/encryption';
import moment from 'moment';
import {
generateUser,
} from '../../../../helpers/api-integration/v3';
} from '../../../helpers/api-integration/v3';
import {
sha1Encrypt as sha1EncryptPassword,
sha1MakeSalt,
@@ -15,7 +15,7 @@ import {
compare,
convertToBcrypt,
validatePasswordResetCodeAndFindUser,
} from '../../../../../website/server/libs/password';
} from '../../../../website/server/libs/password';
describe('Password Utilities', () => {
describe('compare', () => {

View File

@@ -2,11 +2,11 @@ import moment from 'moment';
import {
generateGroup,
} from '../../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../../website/server/models/user';
import amzLib from '../../../../../../../website/server/libs/payments/amazon';
import payments from '../../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../../website/common';
} from '../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../website/server/models/user';
import amzLib from '../../../../../../website/server/libs/payments/amazon';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
import { createNonLeaderGroupMember } from '../paymentHelpers';
const i18n = common.i18n;

View File

@@ -1,7 +1,7 @@
import { model as User } from '../../../../../../../website/server/models/user';
import amzLib from '../../../../../../../website/server/libs/payments/amazon';
import payments from '../../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../../website/common';
import { model as User } from '../../../../../../website/server/models/user';
import amzLib from '../../../../../../website/server/libs/payments/amazon';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
const i18n = common.i18n;

View File

@@ -2,12 +2,12 @@ import cc from 'coupon-code';
import {
generateGroup,
} from '../../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../../website/server/models/user';
import { model as Coupon } from '../../../../../../../website/server/models/coupon';
import amzLib from '../../../../../../../website/server/libs/payments/amazon';
import payments from '../../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../../website/common';
} from '../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../website/server/models/user';
import { model as Coupon } from '../../../../../../website/server/models/coupon';
import amzLib from '../../../../../../website/server/libs/payments/amazon';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
const i18n = common.i18n;

View File

@@ -2,11 +2,11 @@ import uuid from 'uuid';
import {
generateGroup,
} from '../../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../../website/server/models/user';
import { model as Group } from '../../../../../../../website/server/models/group';
import amzLib from '../../../../../../../website/server/libs/payments/amazon';
import payments from '../../../../../../../website/server/libs/payments/payments';
} from '../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../website/server/models/user';
import { model as Group } from '../../../../../../website/server/models/group';
import amzLib from '../../../../../../website/server/libs/payments/amazon';
import payments from '../../../../../../website/server/libs/payments/payments';
describe('#upgradeGroupPlan', () => {
let spy, data, user, group, uuidString;

View File

@@ -1,10 +1,10 @@
/* eslint-disable camelcase */
import iapModule from '../../../../../../website/server/libs/inAppPurchases';
import payments from '../../../../../../website/server/libs/payments/payments';
import applePayments from '../../../../../../website/server/libs/payments/apple';
import iap from '../../../../../../website/server/libs/inAppPurchases';
import {model as User} from '../../../../../../website/server/models/user';
import common from '../../../../../../website/common';
import iapModule from '../../../../../website/server/libs/inAppPurchases';
import payments from '../../../../../website/server/libs/payments/payments';
import applePayments from '../../../../../website/server/libs/payments/apple';
import iap from '../../../../../website/server/libs/inAppPurchases';
import {model as User} from '../../../../../website/server/models/user';
import common from '../../../../../website/common';
import moment from 'moment';
const i18n = common.i18n;

View File

@@ -1,10 +1,10 @@
/* eslint-disable camelcase */
import iapModule from '../../../../../../website/server/libs/inAppPurchases';
import payments from '../../../../../../website/server/libs/payments/payments';
import googlePayments from '../../../../../../website/server/libs/payments/google';
import iap from '../../../../../../website/server/libs/inAppPurchases';
import {model as User} from '../../../../../../website/server/models/user';
import common from '../../../../../../website/common';
import iapModule from '../../../../../website/server/libs/inAppPurchases';
import payments from '../../../../../website/server/libs/payments/payments';
import googlePayments from '../../../../../website/server/libs/payments/google';
import iap from '../../../../../website/server/libs/inAppPurchases';
import {model as User} from '../../../../../website/server/models/user';
import common from '../../../../../website/common';
import moment from 'moment';
const i18n = common.i18n;

View File

@@ -1,13 +1,13 @@
import moment from 'moment';
import * as sender from '../../../../../../../website/server/libs/email';
import * as api from '../../../../../../../website/server/libs/payments/payments';
import { model as User } from '../../../../../../../website/server/models/user';
import { model as Group } from '../../../../../../../website/server/models/group';
import * as sender from '../../../../../../website/server/libs/email';
import * as api from '../../../../../../website/server/libs/payments/payments';
import { model as User } from '../../../../../../website/server/models/user';
import { model as Group } from '../../../../../../website/server/models/group';
import {
generateGroup,
} from '../../../../../../helpers/api-unit.helper.js';
import i18n from '../../../../../../../website/common/script/i18n';
} from '../../../../../helpers/api-unit.helper.js';
import i18n from '../../../../../../website/common/script/i18n';
describe('Canceling a subscription for group', () => {
let plan, group, user, data;

View File

@@ -2,16 +2,16 @@ import moment from 'moment';
import stripeModule from 'stripe';
import nconf from 'nconf';
import * as sender from '../../../../../../../website/server/libs/email';
import * as api from '../../../../../../../website/server/libs/payments/payments';
import amzLib from '../../../../../../../website/server/libs/payments/amazon';
import paypalPayments from '../../../../../../../website/server/libs/payments/paypal';
import stripePayments from '../../../../../../../website/server/libs/payments/stripe';
import { model as User } from '../../../../../../../website/server/models/user';
import { model as Group } from '../../../../../../../website/server/models/group';
import * as sender from '../../../../../../website/server/libs/email';
import * as api from '../../../../../../website/server/libs/payments/payments';
import amzLib from '../../../../../../website/server/libs/payments/amazon';
import paypalPayments from '../../../../../../website/server/libs/payments/paypal';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import { model as User } from '../../../../../../website/server/models/user';
import { model as Group } from '../../../../../../website/server/models/group';
import {
generateGroup,
} from '../../../../../../helpers/api-unit.helper.js';
} from '../../../../../helpers/api-unit.helper.js';
describe('Purchasing a group plan for group', () => {
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_GOOGLE = 'Google_subscription';

View File

@@ -1,4 +1,4 @@
import { model as User } from '../../../../../../website/server/models/user';
import { model as User } from '../../../../../website/server/models/user';
export async function createNonLeaderGroupMember (group) {
let nonLeader = new User();

View File

@@ -1,14 +1,14 @@
import moment from 'moment';
import * as sender from '../../../../../../website/server/libs/email';
import * as api from '../../../../../../website/server/libs/payments/payments';
import analytics from '../../../../../../website/server/libs/analyticsService';
import notifications from '../../../../../../website/server/libs/pushNotifications';
import { model as User } from '../../../../../../website/server/models/user';
import { translate as t } from '../../../../../helpers/api-v3-integration.helper';
import * as sender from '../../../../../website/server/libs/email';
import * as api from '../../../../../website/server/libs/payments/payments';
import analytics from '../../../../../website/server/libs/analyticsService';
import notifications from '../../../../../website/server/libs/pushNotifications';
import { model as User } from '../../../../../website/server/models/user';
import { translate as t } from '../../../../helpers/api-integration/v3';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper.js';
} from '../../../../helpers/api-unit.helper.js';
describe('payments/index', () => {
let user, group, data, plan;

View File

@@ -1,7 +1,7 @@
/* eslint-disable camelcase */
import paypalPayments from '../../../../../../../website/server/libs/payments/paypal';
import payments from '../../../../../../../website/server/libs/payments/payments';
import { model as User } from '../../../../../../../website/server/models/user';
import paypalPayments from '../../../../../../website/server/libs/payments/paypal';
import payments from '../../../../../../website/server/libs/payments/payments';
import { model as User } from '../../../../../../website/server/models/user';
describe('checkout success', () => {
const subKey = 'basic_3mo';

View File

@@ -1,9 +1,9 @@
/* eslint-disable camelcase */
import nconf from 'nconf';
import paypalPayments from '../../../../../../../website/server/libs/payments/paypal';
import { model as User } from '../../../../../../../website/server/models/user';
import common from '../../../../../../../website/common';
import paypalPayments from '../../../../../../website/server/libs/payments/paypal';
import { model as User } from '../../../../../../website/server/models/user';
import common from '../../../../../../website/common';
const BASE_URL = nconf.get('BASE_URL');
const i18n = common.i18n;

View File

@@ -1,10 +1,10 @@
/* eslint-disable camelcase */
import paypalPayments from '../../../../../../../website/server/libs/payments/paypal';
import payments from '../../../../../../../website/server/libs/payments/payments';
import paypalPayments from '../../../../../../website/server/libs/payments/paypal';
import payments from '../../../../../../website/server/libs/payments/payments';
import {
generateGroup,
} from '../../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../../website/server/models/user';
} from '../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../website/server/models/user';
describe('ipn', () => {
const subKey = 'basic_3mo';

View File

@@ -1,11 +1,11 @@
/* eslint-disable camelcase */
import paypalPayments from '../../../../../../../website/server/libs/payments/paypal';
import payments from '../../../../../../../website/server/libs/payments/payments';
import paypalPayments from '../../../../../../website/server/libs/payments/paypal';
import payments from '../../../../../../website/server/libs/payments/payments';
import {
generateGroup,
} from '../../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../../website/server/models/user';
import common from '../../../../../../../website/common';
} from '../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../website/server/models/user';
import common from '../../../../../../website/common';
import { createNonLeaderGroupMember } from '../paymentHelpers';
const i18n = common.i18n;

View File

@@ -1,11 +1,11 @@
/* eslint-disable camelcase */
import paypalPayments from '../../../../../../../website/server/libs/payments/paypal';
import payments from '../../../../../../../website/server/libs/payments/payments';
import paypalPayments from '../../../../../../website/server/libs/payments/paypal';
import payments from '../../../../../../website/server/libs/payments/payments';
import {
generateGroup,
} from '../../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../../website/server/models/user';
import common from '../../../../../../../website/common';
} from '../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../website/server/models/user';
import common from '../../../../../../website/common';
describe('subscribeSuccess', () => {
const subKey = 'basic_3mo';

View File

@@ -2,9 +2,9 @@
import moment from 'moment';
import cc from 'coupon-code';
import paypalPayments from '../../../../../../../website/server/libs/payments/paypal';
import { model as Coupon } from '../../../../../../../website/server/models/coupon';
import common from '../../../../../../../website/common';
import paypalPayments from '../../../../../../website/server/libs/payments/paypal';
import { model as Coupon } from '../../../../../../website/server/models/coupon';
import common from '../../../../../../website/common';
const i18n = common.i18n;

View File

@@ -2,11 +2,11 @@ import stripeModule from 'stripe';
import {
generateGroup,
} from '../../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../../website/server/models/user';
import stripePayments from '../../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../../website/common';
} from '../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../website/server/models/user';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
const i18n = common.i18n;

View File

@@ -3,12 +3,12 @@ import cc from 'coupon-code';
import {
generateGroup,
} from '../../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../../website/server/models/user';
import { model as Coupon } from '../../../../../../../website/server/models/coupon';
import stripePayments from '../../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../../website/common';
} from '../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../website/server/models/user';
import { model as Coupon } from '../../../../../../website/server/models/coupon';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
const i18n = common.i18n;

View File

@@ -1,9 +1,9 @@
import stripeModule from 'stripe';
import { model as User } from '../../../../../../../website/server/models/user';
import stripePayments from '../../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../../website/common';
import { model as User } from '../../../../../../website/server/models/user';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
const i18n = common.i18n;

View File

@@ -2,10 +2,10 @@ import stripeModule from 'stripe';
import {
generateGroup,
} from '../../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../../website/server/models/user';
import stripePayments from '../../../../../../../website/server/libs/payments/stripe';
import common from '../../../../../../../website/common';
} from '../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../website/server/models/user';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import common from '../../../../../../website/common';
const i18n = common.i18n;

View File

@@ -2,12 +2,12 @@ import stripeModule from 'stripe';
import {
generateGroup,
} from '../../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../../website/server/models/user';
import stripePayments from '../../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../../website/common';
import logger from '../../../../../../../website/server/libs/logger';
} from '../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../website/server/models/user';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
import logger from '../../../../../../website/server/libs/logger';
import { v4 as uuid } from 'uuid';
import moment from 'moment';

View File

@@ -2,11 +2,11 @@ import stripeModule from 'stripe';
import {
generateGroup,
} from '../../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../../website/server/models/user';
import { model as Group } from '../../../../../../../website/server/models/group';
import stripePayments from '../../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../../website/server/libs/payments/payments';
} from '../../../../../helpers/api-unit.helper.js';
import { model as User } from '../../../../../../website/server/models/user';
import { model as Group } from '../../../../../../website/server/models/group';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../website/server/libs/payments/payments';
describe('Stripe - Upgrade Group Plan', () => {
const stripe = stripeModule('test');

View File

@@ -1,7 +1,7 @@
import { preenHistory } from '../../../../../website/server/libs/preening';
import { preenHistory } from '../../../../website/server/libs/preening';
import moment from 'moment';
import sinon from 'sinon'; // eslint-disable-line no-shadow
import { generateHistory } from '../../../../helpers/api-unit.helper.js';
import { generateHistory } from '../../../helpers/api-unit.helper.js';
describe('preenHistory', () => {
let clock;

View File

@@ -1,4 +1,4 @@
import { model as User } from '../../../../../website/server/models/user';
import { model as User } from '../../../../website/server/models/user';
import requireAgain from 'require-again';
import pushNotify from 'push-notify';
import nconf from 'nconf';
@@ -7,7 +7,7 @@ import gcmLib from 'node-gcm'; // works with FCM notifications too
describe('pushNotifications', () => {
let user;
let sendPushNotification;
let pathToPushNotifications = '../../../../../website/server/libs/pushNotifications';
let pathToPushNotifications = '../../../../website/server/libs/pushNotifications';
let fcmSendSpy;
let apnSendSpy;

View File

@@ -1,4 +1,4 @@
import setupNconf from '../../../../../website/server/libs/setupNconf';
import setupNconf from '../../../../website/server/libs/setupNconf';
import path from 'path';
import nconf from 'nconf';

View File

@@ -1,10 +1,11 @@
/* eslint-disable camelcase */
import { IncomingWebhook } from '@slack/client';
import requireAgain from 'require-again';
import slack from '../../../../../website/server/libs/slack';
import logger from '../../../../../website/server/libs/logger';
import { TAVERN_ID } from '../../../../../website/server/models/group';
import slack from '../../../../website/server/libs/slack';
import logger from '../../../../website/server/libs/logger';
import { TAVERN_ID } from '../../../../website/server/models/group';
import nconf from 'nconf';
import moment from 'moment';
describe('slack', () => {
describe('sendFlagNotification', () => {
@@ -45,13 +46,15 @@ describe('slack', () => {
it('sends a slack webhook', () => {
slack.sendFlagNotification(data);
const timestamp = `${moment(data.message.timestamp).utc().format('YYYY-MM-DD HH:mm')} UTC`;
expect(IncomingWebhook.prototype.send).to.be.calledOnce;
expect(IncomingWebhook.prototype.send).to.be.calledWith({
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',
author_name: `Author - author@example.com - author-id\n${timestamp}`,
title: 'Flag in Some group - (private guild)',
title_link: undefined,
text: 'some text',
@@ -97,9 +100,11 @@ describe('slack', () => {
slack.sendFlagNotification(data);
const timestamp = `${moment(data.message.timestamp).utc().format('YYYY-MM-DD HH:mm')} UTC`;
expect(IncomingWebhook.prototype.send).to.be.calledWithMatch({
attachments: [sandbox.match({
author_name: 'System Message',
author_name: `System Message\n${timestamp}`,
})],
});
});
@@ -107,7 +112,7 @@ describe('slack', () => {
it('noops if no flagging url is provided', () => {
sandbox.stub(nconf, 'get').withArgs('SLACK:FLAGGING_URL').returns('');
sandbox.stub(logger, 'error');
let reRequiredSlack = requireAgain('../../../../../website/server/libs/slack');
let reRequiredSlack = requireAgain('../../../../website/server/libs/slack');
expect(logger.error).to.be.calledOnce;

View File

@@ -3,13 +3,13 @@ import {
getTasks,
syncableAttrs,
moveTask,
} from '../../../../../website/server/libs/taskManager';
import i18n from '../../../../../website/common/script/i18n';
} from '../../../../website/server/libs/taskManager';
import i18n from '../../../../website/common/script/i18n';
import {
generateUser,
generateGroup,
generateChallenge,
} from '../../../../helpers/api-unit.helper.js';
} from '../../../helpers/api-unit.helper.js';
describe('taskManager', () => {
let user, group, challenge;

View File

@@ -6,14 +6,14 @@ import {
taskActivityWebhook,
questActivityWebhook,
userActivityWebhook,
} from '../../../../../website/server/libs/webhook';
} from '../../../../website/server/libs/webhook';
import {
model as User,
} from '../../../../../website/server/models/user';
} from '../../../../website/server/models/user';
import {
generateUser,
} from '../../../../helpers/api-unit.helper.js';
import { defer } from '../../../../helpers/api-unit.helper';
} from '../../../helpers/api-unit.helper.js';
import { defer } from '../../../helpers/api-unit.helper';
describe('webhooks', () => {
let webhooks, user;

View File

@@ -3,14 +3,14 @@ import {
generateRes,
generateReq,
generateNext,
} from '../../../../helpers/api-unit.helper';
import analyticsService from '../../../../../website/server/libs/analyticsService';
} from '../../../helpers/api-unit.helper';
import analyticsService from '../../../../website/server/libs/analyticsService';
import nconf from 'nconf';
import requireAgain from 'require-again';
describe('analytics middleware', () => {
let res, req, next;
let pathToAnalyticsMiddleware = '../../../../../website/server/middlewares/analytics';
let pathToAnalyticsMiddleware = '../../../../website/server/middlewares/analytics';
beforeEach(() => {
res = generateRes();

View File

@@ -1,8 +1,8 @@
import {
generateRes,
generateReq,
} from '../../../../helpers/api-unit.helper';
import { authWithHeaders as authWithHeadersFactory } from '../../../../../website/server/middlewares/auth';
} from '../../../helpers/api-unit.helper';
import { authWithHeaders as authWithHeadersFactory } from '../../../../website/server/middlewares/auth';
describe('auth middleware', () => {
let res, req, user;

View File

@@ -3,8 +3,8 @@ import {
generateRes,
generateReq,
generateNext,
} from '../../../../helpers/api-unit.helper';
import cors from '../../../../../website/server/middlewares/cors';
} from '../../../helpers/api-unit.helper';
import cors from '../../../../website/server/middlewares/cors';
describe('cors middleware', () => {
let res, req, next;

View File

@@ -3,14 +3,14 @@ import {
generateReq,
generateTodo,
generateDaily,
} from '../../../../helpers/api-unit.helper';
import cronMiddleware from '../../../../../website/server/middlewares/cron';
} from '../../../helpers/api-unit.helper';
import cronMiddleware from '../../../../website/server/middlewares/cron';
import moment from 'moment';
import { model as User } from '../../../../../website/server/models/user';
import { model as Group } from '../../../../../website/server/models/group';
import * as Tasks from '../../../../../website/server/models/task';
import analyticsService from '../../../../../website/server/libs/analyticsService';
import * as cronLib from '../../../../../website/server/libs/cron';
import { model as User } from '../../../../website/server/models/user';
import { model as Group } from '../../../../website/server/models/group';
import * as Tasks from '../../../../website/server/models/task';
import analyticsService from '../../../../website/server/libs/analyticsService';
import * as cronLib from '../../../../website/server/libs/cron';
import { v4 as generateUUID } from 'uuid';
const CRON_TIMEOUT_WAIT = new Date(60 * 60 * 1000).getTime();
@@ -166,11 +166,14 @@ describe('cron middleware', () => {
await new Promise((resolve, reject) => {
cronMiddleware(req, res, (err) => {
if (err) return reject(err);
expect(user.stats.hp).to.be.lessThan(hpBefore);
User.findOne({_id: user._id}, function (secondErr, updatedUser) {
if (secondErr) return reject(secondErr);
expect(updatedUser.stats.hp).to.be.lessThan(hpBefore);
resolve();
});
});
});
});
it('updates tasks', async () => {
user.lastCron = moment(new Date()).subtract({days: 2});
@@ -217,11 +220,14 @@ describe('cron middleware', () => {
await new Promise((resolve, reject) => {
cronMiddleware(req, res, (err) => {
if (err) return reject(err);
expect(user.stats.hp).to.be.lessThan(hpBefore);
User.findOne({_id: user._id}, function (secondErr, updatedUser) {
if (secondErr) return reject(secondErr);
expect(updatedUser.stats.hp).to.be.lessThan(hpBefore);
resolve();
});
});
});
});
it('recovers from failed cron and does not error when user is already cronning', async () => {
user.lastCron = moment(new Date()).subtract({days: 2});

View File

@@ -3,11 +3,11 @@ import {
generateRes,
generateReq,
generateNext,
} from '../../../../helpers/api-unit.helper';
import i18n from '../../../../../website/common/script/i18n';
import { ensureAdmin, ensureSudo } from '../../../../../website/server/middlewares/ensureAccessRight';
import { NotAuthorized } from '../../../../../website/server/libs/errors';
import apiError from '../../../../../website/server/libs/apiError';
} from '../../../helpers/api-unit.helper';
import i18n from '../../../../website/common/script/i18n';
import { ensureAdmin, ensureSudo } from '../../../../website/server/middlewares/ensureAccessRight';
import { NotAuthorized } from '../../../../website/server/libs/errors';
import apiError from '../../../../website/server/libs/apiError';
describe('ensure access middlewares', () => {
let res, req, next;

View File

@@ -3,9 +3,9 @@ import {
generateRes,
generateReq,
generateNext,
} from '../../../../helpers/api-unit.helper';
import ensureDevelpmentMode from '../../../../../website/server/middlewares/ensureDevelpmentMode';
import { NotFound } from '../../../../../website/server/libs/errors';
} from '../../../helpers/api-unit.helper';
import ensureDevelpmentMode from '../../../../website/server/middlewares/ensureDevelpmentMode';
import { NotFound } from '../../../../website/server/libs/errors';
import nconf from 'nconf';
describe('developmentMode middleware', () => {

View File

@@ -2,17 +2,17 @@ import {
generateRes,
generateReq,
generateNext,
} from '../../../../helpers/api-unit.helper';
} from '../../../helpers/api-unit.helper';
import errorHandler from '../../../../../website/server/middlewares/errorHandler';
import responseMiddleware from '../../../../../website/server/middlewares/response';
import errorHandler from '../../../../website/server/middlewares/errorHandler';
import responseMiddleware from '../../../../website/server/middlewares/response';
import {
getUserLanguage,
attachTranslateFunction,
} from '../../../../../website/server/middlewares/language';
} from '../../../../website/server/middlewares/language';
import { BadRequest } from '../../../../../website/server/libs/errors';
import logger from '../../../../../website/server/libs/logger';
import { BadRequest } from '../../../../website/server/libs/errors';
import logger from '../../../../website/server/libs/logger';
describe('errorHandler', () => {
let res, req, next;

View File

@@ -2,13 +2,13 @@ import {
generateRes,
generateReq,
generateNext,
} from '../../../../helpers/api-unit.helper';
} from '../../../helpers/api-unit.helper';
import {
getUserLanguage,
attachTranslateFunction,
} from '../../../../../website/server/middlewares/language';
import common from '../../../../../website/common';
import { model as User } from '../../../../../website/server/models/user';
} from '../../../../website/server/middlewares/language';
import common from '../../../../website/common';
import { model as User } from '../../../../website/server/models/user';
const i18n = common.i18n;

View File

@@ -2,13 +2,13 @@ import {
generateRes,
generateReq,
generateNext,
} from '../../../../helpers/api-unit.helper';
} from '../../../helpers/api-unit.helper';
import nconf from 'nconf';
import requireAgain from 'require-again';
describe('maintenance mode middleware', () => {
let res, req, next;
let pathToMaintenanceModeMiddleware = '../../../../../website/server/middlewares/maintenanceMode';
let pathToMaintenanceModeMiddleware = '../../../../website/server/middlewares/maintenanceMode';
beforeEach(() => {
res = generateRes();

View File

@@ -2,13 +2,13 @@ import {
generateRes,
generateReq,
generateNext,
} from '../../../../helpers/api-unit.helper';
} from '../../../helpers/api-unit.helper';
import nconf from 'nconf';
import requireAgain from 'require-again';
describe('redirects middleware', () => {
let res, req, next;
let pathToRedirectsMiddleware = '../../../../../website/server/middlewares/redirects';
let pathToRedirectsMiddleware = '../../../../website/server/middlewares/redirects';
beforeEach(() => {
res = generateRes();

View File

@@ -2,9 +2,9 @@ import {
generateRes,
generateReq,
generateNext,
} from '../../../../helpers/api-unit.helper';
import responseMiddleware from '../../../../../website/server/middlewares/response';
import packageInfo from '../../../../../package.json';
} from '../../../helpers/api-unit.helper';
import responseMiddleware from '../../../../website/server/middlewares/response';
import packageInfo from '../../../../package.json';
describe('response middleware', () => {
let res, req, next;

View File

@@ -1,8 +1,8 @@
import { model as Challenge } from '../../../../../website/server/models/challenge';
import { model as Group } from '../../../../../website/server/models/group';
import { model as User } from '../../../../../website/server/models/user';
import * as Tasks from '../../../../../website/server/models/task';
import common from '../../../../../website/common/';
import { model as Challenge } from '../../../../website/server/models/challenge';
import { model as Group } from '../../../../website/server/models/group';
import { model as User } from '../../../../website/server/models/user';
import * as Tasks from '../../../../website/server/models/task';
import common from '../../../../website/common/';
import { each, find } from 'lodash';
describe('Challenge Model', () => {

View File

@@ -1,23 +1,23 @@
import moment from 'moment';
import { v4 as generateUUID } from 'uuid';
import validator from 'validator';
import { sleep } from '../../../../helpers/api-unit.helper';
import { sleep } from '../../../helpers/api-unit.helper';
import {
SPAM_MESSAGE_LIMIT,
SPAM_MIN_EXEMPT_CONTRIB_LEVEL,
SPAM_WINDOW_LENGTH,
INVITES_LIMIT,
model as Group,
} from '../../../../../website/server/models/group';
import { model as User } from '../../../../../website/server/models/user';
import { quests as questScrolls } from '../../../../../website/common/script/content';
} from '../../../../website/server/models/group';
import { model as User } from '../../../../website/server/models/user';
import { quests as questScrolls } from '../../../../website/common/script/content';
import {
groupChatReceivedWebhook,
questActivityWebhook,
} from '../../../../../website/server/libs/webhook';
import * as email from '../../../../../website/server/libs/email';
import { TAVERN_ID } from '../../../../../website/common/script/';
import shared from '../../../../../website/common';
} from '../../../../website/server/libs/webhook';
import * as email from '../../../../website/server/libs/email';
import { TAVERN_ID } from '../../../../website/common/script/';
import shared from '../../../../website/common';
describe('Group Model', () => {
let party, questLeader, participatingMember, nonParticipatingMember, undecidedMember;

View File

@@ -1,7 +1,7 @@
import { model as Challenge } from '../../../../../website/server/models/challenge';
import { model as Group } from '../../../../../website/server/models/group';
import { model as User } from '../../../../../website/server/models/user';
import * as Tasks from '../../../../../website/server/models/task';
import { model as Challenge } from '../../../../website/server/models/challenge';
import { model as Group } from '../../../../website/server/models/group';
import { model as User } from '../../../../website/server/models/user';
import * as Tasks from '../../../../website/server/models/task';
import { each, find, findIndex } from 'lodash';
describe('Group Task Methods', () => {

View File

@@ -1,10 +1,10 @@
import { model as Challenge } from '../../../../../website/server/models/challenge';
import { model as Group } from '../../../../../website/server/models/group';
import { model as User } from '../../../../../website/server/models/user';
import * as Tasks from '../../../../../website/server/models/task';
import { InternalServerError } from '../../../../../website/server/libs/errors';
import { model as Challenge } from '../../../../website/server/models/challenge';
import { model as Group } from '../../../../website/server/models/group';
import { model as User } from '../../../../website/server/models/user';
import * as Tasks from '../../../../website/server/models/task';
import { InternalServerError } from '../../../../website/server/libs/errors';
import { each } from 'lodash';
import { generateHistory } from '../../../../helpers/api-unit.helper.js';
import { generateHistory } from '../../../helpers/api-unit.helper.js';
describe('Task Model', () => {
let guild, leader, challenge, task;

View File

@@ -1,7 +1,7 @@
import moment from 'moment';
import { model as User } from '../../../../../website/server/models/user';
import { model as Group } from '../../../../../website/server/models/group';
import common from '../../../../../website/common';
import { model as User } from '../../../../website/server/models/user';
import { model as Group } from '../../../../website/server/models/group';
import common from '../../../../website/common';
describe('User Model', () => {
it('keeps user._tmp when calling .toJSON', () => {

View File

@@ -1,4 +1,4 @@
import { model as UserNotification } from '../../../../../website/server/models/userNotification';
import { model as UserNotification } from '../../../../website/server/models/userNotification';
describe('UserNotification Model', () => {
context('convertNotificationsToSafeJson', () => {

View File

@@ -1,7 +1,7 @@
import { model as Webhook } from '../../../../../website/server/models/webhook';
import { BadRequest } from '../../../../../website/server/libs/errors';
import { model as Webhook } from '../../../../website/server/models/webhook';
import { BadRequest } from '../../../../website/server/libs/errors';
import { v4 as generateUUID } from 'uuid';
import apiError from '../../../../../website/server/libs/apiError';
import apiError from '../../../../website/server/libs/apiError';
describe('Webhook Model', () => {
context('Instance Methods', () => {

View File

@@ -5,7 +5,7 @@ import {
sleep,
checkExistence,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import { v4 as generateUUID } from 'uuid';
describe('DELETE /challenges/:challengeId', () => {

View File

@@ -3,7 +3,7 @@ import {
createAndPopulateGroup,
generateChallenge,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import { v4 as generateUUID } from 'uuid';
describe('GET /challenges/:challengeId', () => {

View File

@@ -4,7 +4,7 @@ import {
generateChallenge,
translate as t,
sleep,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import { v4 as generateUUID } from 'uuid';
describe('GET /challenges/:challengeId/export/csv', () => {

View File

@@ -3,7 +3,7 @@ import {
generateGroup,
generateChallenge,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import { v4 as generateUUID } from 'uuid';
describe('GET /challenges/:challengeId/members', () => {

View File

@@ -3,7 +3,7 @@ import {
generateChallenge,
generateGroup,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import { v4 as generateUUID } from 'uuid';
describe('GET /challenges/:challengeId/members/:memberId', () => {

View File

@@ -3,7 +3,7 @@ import {
generateChallenge,
createAndPopulateGroup,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import { TAVERN_ID } from '../../../../../website/common/script/constants';
describe('GET challenges/groups/:groupId', () => {

View File

@@ -2,7 +2,7 @@ import {
generateUser,
generateChallenge,
createAndPopulateGroup,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
describe('GET challenges/user', () => {
context('no official challenges', () => {

View File

@@ -2,7 +2,7 @@ import {
generateUser,
createAndPopulateGroup,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import { v4 as generateUUID } from 'uuid';
describe('POST /challenges', () => {

View File

@@ -3,7 +3,7 @@ import {
generateChallenge,
createAndPopulateGroup,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import { v4 as generateUUID } from 'uuid';
describe('POST /challenges/:challengeId/join', () => {

View File

@@ -3,7 +3,7 @@ import {
generateChallenge,
createAndPopulateGroup,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import { v4 as generateUUID } from 'uuid';
describe('POST /challenges/:challengeId/leave', () => {

View File

@@ -5,7 +5,7 @@ import {
sleep,
checkExistence,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import { v4 as generateUUID } from 'uuid';
describe('POST /challenges/:challengeId/winner/:winnerId', () => {

View File

@@ -1,7 +1,7 @@
import {
generateUser,
generateGroup,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
describe('POST /challenges/:challengeId/clone', () => {
it('clones a challenge', async () => {

View File

@@ -3,7 +3,7 @@ import {
generateChallenge,
createAndPopulateGroup,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
describe('PUT /challenges/:challengeId', () => {
let privateGuild, user, nonMember, challenge, member;

View File

@@ -2,7 +2,7 @@ import {
createAndPopulateGroup,
generateUser,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import { v4 as generateUUID } from 'uuid';
describe('DELETE /groups/:groupId/chat/:chatId', () => {

View File

@@ -2,7 +2,7 @@ import {
generateUser,
generateGroup,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
describe('GET /groups/:groupId/chat', () => {
let user;

View File

@@ -1,7 +1,7 @@
import {
generateUser,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import { find } from 'lodash';
describe('POST /chat/:chatId/flag', () => {

View File

@@ -1,7 +1,7 @@
import {
createAndPopulateGroup,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import { find } from 'lodash';
describe('POST /chat/:chatId/like', () => {

View File

@@ -4,7 +4,7 @@ import {
translate as t,
sleep,
server,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import {
SPAM_MESSAGE_LIMIT,
SPAM_MIN_EXEMPT_CONTRIB_LEVEL,

View File

@@ -1,7 +1,7 @@
import {
createAndPopulateGroup,
sleep,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
describe('POST /groups/:id/chat/seen', () => {
context('Guild', () => {

View File

@@ -2,7 +2,7 @@ import {
createAndPopulateGroup,
generateUser,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import config from '../../../../../config.json';
import { v4 as generateUUID } from 'uuid';

View File

@@ -1,7 +1,7 @@
import {
requester,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import i18n from '../../../../../website/common/script/i18n';
describe('GET /content', () => {

View File

@@ -1,7 +1,7 @@
import {
generateUser,
resetHabiticaDB,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import apiError from '../../../../../website/server/libs/apiError';
describe('GET /coupons/', () => {

View File

@@ -2,7 +2,7 @@ import {
generateUser,
translate as t,
resetHabiticaDB,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
describe('POST /coupons/enter/:code', () => {
let user;

View File

@@ -2,7 +2,7 @@ import {
generateUser,
translate as t,
resetHabiticaDB,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import couponCode from 'coupon-code';
import apiError from '../../../../../website/server/libs/apiError';

View File

@@ -2,7 +2,7 @@ import {
generateUser,
requester,
resetHabiticaDB,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
describe('POST /coupons/validate/:code', () => {
let api = requester();

View File

@@ -1,7 +1,7 @@
import {
generateUser,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import { v4 as generateUUID } from 'uuid';
xdescribe('GET /export/avatar-:memberId.html', () => {

View File

@@ -1,6 +1,6 @@
import {
generateUser,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import {
updateDocument,
} from '../../../../helpers/mongo';

View File

@@ -1,6 +1,6 @@
import {
generateUser,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
describe('GET /export/inbox.html', () => {
let user;

View File

@@ -1,6 +1,6 @@
import {
generateUser,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
describe('GET /export/userdata.json', () => {
it('should return a valid JSON file with user data', async () => {

View File

@@ -1,6 +1,6 @@
import {
generateUser,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import xml2js from 'xml2js';
import util from 'util';

Some files were not shown because too many files have changed in this diff Show More