Compare commits

..

105 Commits

Author SHA1 Message Date
Sabe Jones f810fff6fc 4.51.3 2018-07-12 19:10:02 +00:00
Sabe Jones 5bbe59c52d chore(i18n): update locales 2018-07-12 19:09:42 +00:00
Sabe Jones 3f52401384 chore(news): Bailey 2018-07-12 14:05:40 -05:00
Matteo Pagliazzi e7944b3d98 iOS push notifications, use node-apn (#10517)
* fixing typos in comments. yes, I am that kind of nerd

* replacing push-notify with node-apn in deps and in pushNotifications.js

* updating calling code and tests to use node-apn

* updating APN configs to new format

* migrating team ID and key ID to config.json

* update code to use env variables and add correct topic
2018-07-12 12:56:15 +02:00
Sabe Jones 08e925e3da Merge branch 'release' into develop 2018-07-10 17:26:37 +00:00
Sabe Jones 16c9e42ad8 4.51.2 2018-07-10 17:24:18 +00:00
Sabe Jones 0e1d00c95f chore(i18n): update locales 2018-07-10 17:23:40 +00:00
Sabe Jones 166f4683ca feat(content): enable Splashy Skins 2018-07-10 12:18:41 -05:00
Keith Holliday 1fcc0d8d3a Ensured redirect is using base (#10497) 2018-07-09 10:08:19 -05:00
Matteo Pagliazzi 8a4c4e10f1 remove sensitive info from logs 2018-07-08 10:43:28 +02:00
Maurício El Uri 18ed0fe446 Fixed the unnecessary whitespace to the right of landing page (#10435) (#10490) 2018-07-06 15:57:36 -05:00
Vinicius 1f9ebeb629 Set .resting-banner z-index to 1300, set #progress .bar z-index to 1600 (#10492) 2018-07-06 15:55:44 -05:00
Sabe Jones b9d83122d1 fix(tasks): eliminate console error related to filtering
Also localize a group plans string
2018-07-06 15:43:27 -05:00
Sabe Jones d1f7e64156 fix(groups): display correct messages in two places 2018-07-06 13:21:28 -05:00
Sabe Jones 0f8e7416f8 fix(groups): save group options on task create
Also, correct count of assigned members when viewing user is among 
assignments
2018-07-06 10:30:09 -05:00
Sabe Jones 1c8b0f92df Small Group Plan fixes (#10499)
* fix(groups): better margins, don't close whole modal on close assigned members list

* fix(groups): proper sticky toggle switch
2018-07-05 16:37:06 -05:00
Sabe Jones 75e5b20f93 4.51.1 2018-07-05 15:14:05 +00:00
Sabe Jones f9db432794 chore(i18n): update locales 2018-07-05 15:12:59 +00:00
Sabe Jones 6cec7cbba2 Merge branch 'release' into develop 2018-07-03 17:39:27 +00:00
Sabe Jones f76d097313 4.51.0 2018-07-03 17:38:44 +00:00
Sabe Jones 59af471438 chore(i18n): update locales 2018-07-03 17:38:00 +00:00
Sabe Jones d0da303b7d chore(sprites): fix shop icon canvases, compile 2018-07-03 12:33:20 -05:00
Sabe Jones 596383e7a8 feat(content): Armoire and Backgrounds July 2018 2018-07-03 12:26:20 -05:00
Matteo Pagliazzi accba7fc13 fix bug in task approval notification 2018-07-03 11:23:44 +02:00
Sabe Jones dfc54f1600 Merge branch 'release' into develop 2018-07-02 19:58:23 +00:00
Sabe Jones b76ab58e3e 4.50.6 2018-07-02 19:58:00 +00:00
Sabe Jones 6f093a94c4 chore(i18n): update locales 2018-07-02 19:57:39 +00:00
Sabe Jones a9a9e7a4ab chore(sprites): compile 2018-07-02 14:51:59 -05:00
Sabe Jones b2058ec23d chore(news): Bailey challenge announcements 2018-07-02 14:51:40 -05:00
Keith Holliday 2461f53cf5 4.50.5 2018-07-01 18:25:23 -05:00
Keith Holliday 73fc288f3b 4.50.4 2018-07-01 18:25:20 -05:00
Keith Holliday ea78b6feb9 Changed docker file names (#10489) 2018-07-01 18:23:40 -05:00
Keith Holliday 7c141614ed Api login party invites (#10486)
* Fixed incorrect variable

* Fixed redirect params
2018-06-30 22:06:18 -05:00
Alys c072935e80 document the dueDate parameter for API task functions - partial fix for #8087 2018-06-30 15:55:27 +10:00
Alys 54e49ca3b9 adjust README file for recent changes in wiki Blacksmith pages
Also replace non-ascii quotes with ascii ones (nicer for
command-line reading).
2018-06-30 15:05:05 +10:00
Sabe Jones b16a245d61 Merge branch 'release' into develop 2018-06-29 19:06:20 +00:00
Sabe Jones 0a8109e496 4.50.3 2018-06-29 19:05:53 +00:00
Sabe Jones cdfcc6419f chore(i18n): update locales 2018-06-29 19:03:36 +00:00
Matteo Pagliazzi 9c25c2452f fixes #10485 2018-06-29 20:29:14 +02:00
Matteo Pagliazzi 573f2e4732 fix preening when history entries are null 2018-06-29 20:03:45 +02:00
Keith Holliday 81ffcf9c1b Added login path for Spritely (#10484) 2018-06-29 11:35:22 -05:00
Sabe Jones d8925a8811 Merge branch 'release' into develop 2018-06-29 00:22:18 +00:00
Sabe Jones 217c16988b 4.50.2 2018-06-29 00:21:56 +00:00
Sabe Jones de7f953b67 chore(i18n): update locales 2018-06-29 00:20:37 +00:00
SabreCat 8ee2a02e73 chore(news): Bailey 2018-06-29 00:18:13 +00:00
negue d9b573b430 AbstractGemItemOperation - BuyQuestWithGemOperation (#10476) 2018-06-28 12:37:21 +02:00
Keith Holliday cbcf5a03e1 Ensured leader doesn't change with group plans (#10480) 2018-06-28 11:57:24 +02:00
Matteo Pagliazzi 487523f64b client: disable broken test 2018-06-28 11:04:35 +02:00
Matteo Pagliazzi 74cfc2cf52 add ability to specify pool size for mongodb (#10481) 2018-06-28 11:02:26 +02:00
Sabe Jones 2d489e870f Merge branch 'release' into develop 2018-06-27 18:34:06 +00:00
Sabe Jones 6659d4fa52 4.50.1 2018-06-27 18:33:43 +00:00
Sabe Jones 5471af74fa chore(i18n): update locales 2018-06-27 18:33:34 +00:00
Sabe Jones 6eb484605a fix(messages): clarify opt-in/out wording and leave label static (#10470) 2018-06-27 19:13:13 +02:00
Sabe Jones 8969b755a6 fix(analytics): remove spurious click tracking (#10469) 2018-06-27 19:12:51 +02:00
Sabe Jones 0062e5b1f1 fix(time-travelers): don't timeshift background without Hourglass (#10468) 2018-06-27 19:12:36 +02:00
Sabe Jones 50b98d8d92 fix(deletion): show feedback for social accounts (#10467) 2018-06-27 19:12:18 +02:00
Isabelle Lavandero 7ddf4b1f7b Remove "add multiple" tip once a task has been added (fixes #10440) (#10459)
* remove tip once a task has been added

* blur quickadd on enter but not on shift

* blur quickadd after tasks are created
2018-06-27 19:08:45 +02:00
Dexx Mandele c91da86b89 Remember equipment drawer tab (#10458)
* Remember equipment drawer tab

* Split local setting value constants
2018-06-27 19:08:21 +02:00
Jerell Mendoza d549fea4ed 10282: Added code for blocking party and guild invitations from block… (#10454)
* 10282: Added code for blocking party and guild invitations from blocked players, added tests

* 10282: fixed test label

* Update POST-groups_invite.test.js

removed `it.only` which was used for testing
2018-06-27 19:07:57 +02:00
Patricia Beier a362914f93 added ctrl+enter to private messages #10413 (#10436)
* added ctrl+enter to private messages #10413

* Fixes #10413
2018-06-27 19:07:41 +02:00
Hayden Betts 61001d0e9a WIP Fix flicker when user mouses over the very leftmost edge of party member avatar (#10407)
* added 1px margin-right to .member-stats

* added unit test for flicker prevention style

* remove .only() from unit test

* rewrote margin test using computed style
2018-06-27 19:07:21 +02:00
Matteo Pagliazzi fb95d001ab hotfix for bailey not scrolling (might reintroduce a double scrollbar), fixes #10461 2018-06-27 18:59:28 +02:00
Sabe Jones bd5c4a08e2 Merge branch 'release' into develop 2018-06-26 20:45:37 +00:00
Sabe Jones 34fb90455c 4.50.0 2018-06-26 20:44:53 +00:00
Sabe Jones d038d9f9bb chore(i18n): update locales 2018-06-26 20:35:38 +00:00
SabreCat 420d7df4f5 chore(sprites): compile 2018-06-26 20:24:04 +00:00
SabreCat 3ee8072a6c feat(content): Summer Splash Potions and Seafoam 2018-06-26 20:19:16 +00:00
Matteo Pagliazzi 50ebdd1ece tasks hsitory migration: prevent it from running twice 2018-06-25 23:14:35 +02:00
Sabe Jones 4a80dcae2e 4.49.1 2018-06-25 20:27:08 +00:00
Sabe Jones bc03c1d18a fix(sprites): correct armor and weapon sprites 2018-06-25 20:26:26 +00:00
Sabe Jones e5d834b40a 4.49.0 2018-06-25 19:39:39 +00:00
Sabe Jones 7f847d322f chore(i18n): update locales 2018-06-25 19:37:38 +00:00
Phillip Thelen ed27ac15c8 Fix documentation about rejecting group invitation (#10466) 2018-06-23 11:24:33 +02:00
Sabe Jones 88188e56d9 Merge branch 'release' into develop 2018-06-22 19:03:33 +00:00
Sabe Jones 7170cf05d0 4.48.1 2018-06-22 19:02:55 +00:00
Sabe Jones 22a8d5e94c chore(i18n): update locales 2018-06-22 19:02:25 +00:00
SabreCat f37e5cde57 chore(news): Blog Bailey 2018-06-22 18:58:47 +00:00
Matteo Pagliazzi 592cfef6c6 Client: use api v4 (#10457)
* client: use api v4

* fix tests
2018-06-21 21:25:27 +02:00
Matteo Pagliazzi c1bd7f5dc5 Habits: store one history entry per day (#10442)
* initial refactor

* add scoredUp and scoredDown values for habits history entries, one entry per habit per day

* fix lint and add initial migration

* update old test

* remove scoreNotes

* dry run for migration

* migration fixes

* update migration and remove old test

* fix

* add challenges migration (read only)

* fix challenges migration

* handle custom day start

* update tasks in migration

* scoring: support cds

* add new test
2018-06-21 21:25:19 +02:00
Sabe Jones 8437b916c4 4.48.0 2018-06-21 18:50:38 +00:00
Sabe Jones 52e53aa466 chore(i18n): update locales 2018-06-21 18:49:55 +00:00
SabreCat 4471186e09 chore(sprites): maintenance 2018-06-21 18:44:37 +00:00
SabreCat 6a2a844e04 feat(content): Mystery Items June 2018 2018-06-21 18:44:18 +00:00
Sabe Jones 122d147f07 Merge branch 'release' into develop 2018-06-19 23:33:19 +00:00
Sabe Jones 912f00a652 4.47.0 2018-06-19 23:32:57 +00:00
Sabe Jones 627d4330c8 chore(i18n): update locales 2018-06-19 23:31:53 +00:00
SabreCat c7f6794dda chore(sprites): compile 2018-06-19 23:25:41 +00:00
SabreCat 00cb50a781 feat(event): Summer Splash 2018
Also gets rid of those Fairy Potions, FOR REAL this time, and fixes a couple of minor Market layout issues
2018-06-19 23:24:40 +00:00
Matteo Pagliazzi 8be9964483 API v4 (WIP) (#10453)
API v4
2018-06-18 14:40:25 +02:00
Sabe Jones 7ea6c911cb Better group plan member counts (#10449)
* fix(group-plans): improved member count accuracy

* fix(migration): don't leave server running after completion

* fix(migration): don't update Stripe for non-Stripe methods
Also fixes a linting issue.

* fix(lint): no comma dangle here

* fix(async): put async token in relevant spot

* fix(lint): still more linting

* fix(async): better handling for async and promises
Also adds additional logging where discrepancies are found.

* feat(migration): provide CSV output

* fix(promises): better pause/resume

* fix(migration): don't update already canceled subs

* fix(groups): also address quantity/memberCount discrepancies

* fix(migration): also log quantity issues

* fix(migration): equation was reversed

* refactor(migration): condense logic, add error catch

* fix(migration): fix root cause of failed quantity update??

* fix(lint): gratuitous parens

* fix(test): expect group to be updated db-side

* fix(migration): actually update quantities?

* fix(groups): roll back unneeded Stripe lib change, refactor migration
2018-06-15 14:49:18 -05:00
Isabelle Lavandero 97a069642d Add timestamp to moderator Slack messages (fixes #10441) (#10443)
* add timestamp to moderator Slack messages

* fix test errors

* import moment, condense formatting

* add timestamp to author_name variable

* update test to include timestamp, fix footer matching

* change ISODate to Date

* update test to include timestamp
2018-06-15 11:01:10 +02:00
Dexx Mandele 26e9827d39 Open correct group modal from header (#10430)
* Remove outdated server readme

* Open correct group modal from header

* Update party button after joining party

* Review: fix invite members not working without reload

* Remove invite-modal from group page to prevent duplicates

* Pass correct group to invite modal
2018-06-15 11:00:10 +02:00
Brian Fenton 88c625fe80 removing the 24px top margin on .modal-dialog .title (#10377)
* removing the 24px top margin on .modal-dialog .title so boss HP and difficulty line up

* stop overloading title so much and use a properly-scoped style

* removing unnecessary temp vars

* using SCSS color vars as per CR

* using relative font size measurements instead of absolute pixels, and adding popover override CSS to not break quest shop & invite notifications

* removing redundant font declarations
2018-06-15 10:58:28 +02:00
Travis 4044432fad Fixes asynchronous cron bug that allows cron to run twice for a user within seconds. (#10142)
* Fixes asynchronous cron bug that allows cron to run twice for a user within seconds of eachother.

fixes #8991

* Fixing tests.

* Updating assignment to keep user and res.locals.user in sync.
2018-06-14 13:47:44 -05:00
Sabe Jones 6a767ed70b 4.46.2 2018-06-14 17:08:55 +00:00
Sabe Jones 2c2ca4a9c8 chore(i18n): update locales 2018-06-14 17:06:55 +00:00
Sabe Jones 380ad8c9e5 Merge branch 'develop' into release 2018-06-14 17:04:50 +00:00
Sabe Jones f53400f950 Report: Subscriber Task Histories (#10439)
* WIP(report): subscriber task histories

* fix(report): old object ref, return promise, pause/resume

* fix(report): handle 0 Habits 0 Dailies
Also add data for master total of history entries
2018-06-14 05:37:29 -05:00
Sabe Jones 53c719acbd 4.46.1 2018-06-12 22:13:15 +00:00
Sabe Jones 948a5d80c8 fix(news): broken link 2018-06-12 22:13:01 +00:00
Sabe Jones e1f141ee91 Merge branch 'release' into develop 2018-06-12 20:25:32 +00:00
Dominic Lee 44f196080c Match tavern sidebar UI to party and guild page changes (#10400)
* Match tavern sidebar UI to party and guild page changes

* Remove extra space at the top of guild's sidebar
2018-06-11 12:00:19 +02:00
Patricia Beier 65bfd74c93 more place for the donate button - for languages with more letters (#10417) 2018-06-11 11:59:16 +02:00
Michael Chenevey 5e60a05cac related to 10419 (#10438)
Added a 'habitica:update-challenge' call to mirror the 'clone-challenge' call. This properly sets the 'cloning' flag and makes things more consistent.
This fixes the a bug related to #10419 described in the #10419 thread
2018-06-11 11:58:18 +02:00
Yun Ha Seo 59af4a2d3b Modal width responsiveness (partial fix for #10267) (#10354)
* added responsive scss to allow modals to respond to changing window size

* Remove unecessary space

* moved scss around

* remove unnecessary space

* Adjust left and right panels to be more responsive + moved css for buyQuestModal into its respective vue file (startQuestModal css wasn't working in its vue file... I can't figure out why)

* removed important to get rid of extra scrollbar

* moved css all to one file
2018-06-11 11:57:11 +02:00
781 changed files with 35298 additions and 31691 deletions
+2 -1
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
+29 -18
View File
@@ -1,18 +1,29 @@
FROM node:8
# Install global packages
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 https://github.com/HabitRPG/habitica.git /usr/src/habitrpg
RUN cp config.json.example config.json
RUN npm install
# Create Build dir
RUN mkdir -p ./website/build
# Start Habitica
EXPOSE 3000
CMD ["npm", "start"]
FROM node:8
ENV ADMIN_EMAIL admin@habitica.com
ENV AMAZON_PAYMENTS_CLIENT_ID amzn1.application-oa2-client.68ed9e6904ef438fbc1bf86bf494056e
ENV AMAZON_PAYMENTS_SELLER_ID AMQ3SB4SG5E91
ENV AMPLITUDE_KEY e8d4c24b3d6ef3ee73eeba715023dd43
ENV BASE_URL https://habitica.com
ENV FACEBOOK_KEY 128307497299777
ENV GA_ID UA-33510635-1
ENV GOOGLE_CLIENT_ID 1035232791481-32vtplgnjnd1aufv3mcu1lthf31795fq.apps.googleusercontent.com
ENV NODE_ENV production
ENV STRIPE_PUB_KEY pk_85fQ0yMECHNfHTSsZoxZXlPSwSNfA
# Install global packages
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 release https://github.com/HabitRPG/habitica.git /usr/src/habitrpg
RUN npm install
RUN gulp build:prod --force
# Create Build dir
RUN mkdir -p ./website/build
# Start Habitica
EXPOSE 3000
CMD ["node", "./website/transpiled-babel/index.js"]
+18
View File
@@ -0,0 +1,18 @@
FROM node:8
# Install global packages
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 https://github.com/HabitRPG/habitica.git /usr/src/habitrpg
RUN cp config.json.example config.json
RUN npm install
# Create Build dir
RUN mkdir -p ./website/build
# Start Habitica
EXPOSE 3000
CMD ["npm", "start"]
-29
View File
@@ -1,29 +0,0 @@
FROM node:8
ENV ADMIN_EMAIL admin@habitica.com
ENV AMAZON_PAYMENTS_CLIENT_ID amzn1.application-oa2-client.68ed9e6904ef438fbc1bf86bf494056e
ENV AMAZON_PAYMENTS_SELLER_ID AMQ3SB4SG5E91
ENV AMPLITUDE_KEY e8d4c24b3d6ef3ee73eeba715023dd43
ENV BASE_URL https://habitica.com
ENV FACEBOOK_KEY 128307497299777
ENV GA_ID UA-33510635-1
ENV GOOGLE_CLIENT_ID 1035232791481-32vtplgnjnd1aufv3mcu1lthf31795fq.apps.googleusercontent.com
ENV NODE_ENV production
ENV STRIPE_PUB_KEY pk_85fQ0yMECHNfHTSsZoxZXlPSwSNfA
# Install global packages
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.45.1 https://github.com/HabitRPG/habitica.git /usr/src/habitrpg
RUN npm install
RUN gulp build:prod --force
# Create Build dir
RUN mkdir -p ./website/build
# Start Habitica
EXPOSE 3000
CMD ["node", "./website/transpiled-babel/index.js"]
+5 -1
View File
@@ -78,6 +78,9 @@
"PUSH_CONFIGS": {
"GCM_SERVER_API_KEY": "",
"APN_ENABLED": "false",
"APN_KEY_ID": "xxxxxxxxxx",
"APN_KEY": "xxxxxxxxxx",
"APN_TEAM_ID": "aaabbbcccd",
"FCM_SERVER_API_KEY": ""
},
"SITE_HTTP_AUTH": {
@@ -112,5 +115,6 @@
"CLOUDKARAFKA_USERNAME": "",
"CLOUDKARAFKA_PASSWORD": "",
"CLOUDKARAFKA_TOPIC_PREFIX": ""
}
},
"MIGRATION_CONNECT_STRING": "mongodb://localhost:27017/habitrpg?auto_reconnect=true"
}
@@ -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;
+33 -7
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()
));
));
@@ -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;
+1 -1
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();
@@ -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;
@@ -0,0 +1,163 @@
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 = {
migration: {$ne: migrationName},
};
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)));
})
.then(() => {
return dbUsers.update({_id: user._id}, {
$set: {migration: migrationName},
});
})
.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;
+1 -1
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) {
+7 -5
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://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
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) {
@@ -1,4 +1,4 @@
let migrationName = '20180102_takeThis.js'; // Update per month
let migrationName = '20180702_takeThis.js'; // Update per month
let authorName = 'Sabe'; // in case script author needs to know when their ...
let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
@@ -6,15 +6,16 @@ let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
* Award Take This ladder items to participants in this month's challenge
*/
let monk = require('monk');
let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
let dbUsers = monk(connectionString).get('users', { castIds: false });
import monk from 'monk';
import nconf from 'nconf';
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING'); // FOR TEST DATABASE
let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
function processUsers (lastId) {
// specify a query to limit the affected users (empty for all users):
let query = {
migration: {$ne: migrationName},
challenges: {$in: ['5f70ce5b-2d82-4114-8e44-ca65615aae62']}, // Update per month
challenges: {$in: ['f0481f95-1dde-4ae7-a876-d19502a45d61']}, // Update per month
};
if (lastId) {
+114 -41
View File
@@ -1,6 +1,6 @@
{
"name": "habitica",
"version": "4.46.0",
"version": "4.51.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -801,13 +801,25 @@
}
},
"apn": {
"version": "1.7.8",
"resolved": "https://registry.npmjs.org/apn/-/apn-1.7.8.tgz",
"integrity": "sha1-Hp2kKPtXr6lX5UIjvvc0LALCTNo=",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/apn/-/apn-2.2.0.tgz",
"integrity": "sha512-YIypYzPVJA9wzNBLKZ/mq2l1IZX/2FadPvwmSv4ZeR0VH7xdNITQ6Pucgh0Uw6ZZKC+XwheaJ57DFZAhJ0FvPg==",
"requires": {
"debug": "2.6.9",
"node-forge": "0.6.49",
"q": "1.5.1"
"debug": "3.1.0",
"http2": "https://github.com/node-apn/node-http2/archive/apn-2.1.4.tar.gz",
"jsonwebtoken": "8.3.0",
"node-forge": "0.7.5",
"verror": "1.10.0"
},
"dependencies": {
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
}
}
},
"append-buffer": {
@@ -5036,6 +5048,11 @@
"resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz",
"integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74="
},
"buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
},
"buffer-fill": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
@@ -8792,6 +8809,14 @@
"jsbn": "0.1.1"
}
},
"ecdsa-sig-formatter": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz",
"integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=",
"requires": {
"safe-buffer": "5.1.2"
}
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -13292,6 +13317,10 @@
"sshpk": "1.14.1"
}
},
"http2": {
"version": "https://github.com/node-apn/node-http2/archive/apn-2.1.4.tar.gz",
"integrity": "sha512-ad4u4I88X9AcUgxCRW3RLnbh7xHWQ1f5HbrXa7gEy2x4Xgq+rq+auGx5I+nUDE2YYuqteGIlbxrwQXkIaYTfnQ=="
},
"httpntlm": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz",
@@ -14768,6 +14797,29 @@
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz",
"integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk="
},
"jsonwebtoken": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz",
"integrity": "sha512-oge/hvlmeJCH+iIz1DwcO7vKPkNGJHhgkspk8OH3VKlw+mbi42WtD4ig1+VXRln765vxptAv+xT26Fd3cteqag==",
"requires": {
"jws": "3.1.5",
"lodash.includes": "4.3.0",
"lodash.isboolean": "3.0.3",
"lodash.isinteger": "4.0.4",
"lodash.isnumber": "3.0.3",
"lodash.isplainobject": "4.0.6",
"lodash.isstring": "4.0.1",
"lodash.once": "4.1.1",
"ms": "2.1.1"
},
"dependencies": {
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
}
}
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -14806,6 +14858,25 @@
"integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==",
"dev": true
},
"jwa": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.6.tgz",
"integrity": "sha512-tBO/cf++BUsJkYql/kBbJroKOgHWEigTKBAjjBEmrMGYd1QMBC74Hr4Wo2zCZw6ZrVhlJPvoMrkcOnlWR/DJfw==",
"requires": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.10",
"safe-buffer": "5.1.2"
}
},
"jws": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.1.5.tgz",
"integrity": "sha512-GsCSexFADNQUr8T5HPJvayTjvPIfoyJPtLQBwn5a4WZQchcrPMPMAWcC1AzJVRDKyD6ZPROPAxgv6rfHViO4uQ==",
"requires": {
"jwa": "1.1.6",
"safe-buffer": "5.1.2"
}
},
"kareem": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.1.0.tgz",
@@ -16418,6 +16489,11 @@
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
},
"lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
},
"lodash.initial": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.initial/-/lodash.initial-4.1.1.tgz",
@@ -16433,16 +16509,36 @@
"resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
"integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U="
},
"lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
},
"lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
},
"lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
},
"lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
},
"lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
},
"lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
},
"lodash.istypedarray": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz",
@@ -16484,6 +16580,11 @@
"resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz",
"integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ=="
},
"lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
},
"lodash.pairs": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/lodash.pairs/-/lodash.pairs-3.0.1.tgz",
@@ -18033,11 +18134,6 @@
"resolved": "https://registry.npmjs.org/mpath/-/mpath-0.4.1.tgz",
"integrity": "sha512-NNY/MpBkALb9jJmjpBlIi6GRoLveLUM0pJzgbp9vY9F7IQEb/HREC/nxrixechcQwd1NevOhJnWWV8QQQRE+OA=="
},
"mpns": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/mpns/-/mpns-2.1.3.tgz",
"integrity": "sha512-gPLNoVqwYoKUmNYZ2shMSdaE2XvHSRxWNzyG4DUi6Av7MSujyeOw/nj61nnQeuV/vke5E0Dni468xn0qxTHIZQ=="
},
"mquery": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/mquery/-/mquery-3.0.0.tgz",
@@ -18457,9 +18553,9 @@
}
},
"node-forge": {
"version": "0.6.49",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.6.49.tgz",
"integrity": "sha1-8e6V1ddGI5OP4Z1piqWibVTS9g8="
"version": "0.7.5",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz",
"integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ=="
},
"node-gcm": {
"version": "0.14.10",
@@ -18655,9 +18751,9 @@
}
},
"node-rdkafka": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/node-rdkafka/-/node-rdkafka-2.3.3.tgz",
"integrity": "sha512-2J54zC9+Zj0iRQttmQs1Ubv8aHhmh04XjP3vk39uco7l6tp8BYYHG4XRsoqKOGGKjBLctGpFHr9g97WBE1pTbg==",
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/node-rdkafka/-/node-rdkafka-2.3.4.tgz",
"integrity": "sha512-ilaAOrEpDF3TGTlItsxU5pQXG+qjN1gKbhSvs9CoLXZaItt2EN6oU+kEdO6UkRQLKO6/Kv4m296cBrr0JCmiTw==",
"optional": true,
"requires": {
"bindings": "1.3.0",
@@ -20335,11 +20431,6 @@
"pinkie": "2.0.4"
}
},
"pipe-event": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/pipe-event/-/pipe-event-0.1.0.tgz",
"integrity": "sha1-pfXgPlqXsrdJPUsqBgzYPazLmmE="
},
"pixelsmith": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/pixelsmith/-/pixelsmith-2.2.1.tgz",
@@ -22718,19 +22809,6 @@
}
}
},
"push-notify": {
"version": "git://github.com/habitrpg/push-notify.git#6bc2b5fdb1bdc9649b9ec1964d79ca50187fc8a9",
"requires": {
"apn": "1.7.8",
"bluebird": "3.5.1",
"lodash": "4.17.10",
"mpns": "2.1.3",
"node-gcm": "0.14.10",
"pipe-event": "0.1.0",
"q": "1.5.1",
"wns": "0.5.3"
}
},
"pusher": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/pusher/-/pusher-1.5.1.tgz",
@@ -27870,11 +27948,6 @@
"dev": true,
"optional": true
},
"wns": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/wns/-/wns-0.5.3.tgz",
"integrity": "sha1-APToXPz44zg9y9gYmJBvH2rUhF8="
},
"wordwrap": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
+5 -3
View File
@@ -1,7 +1,7 @@
{
"name": "habitica",
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
"version": "4.46.0",
"version": "4.51.3",
"main": "./website/server/index.js",
"dependencies": {
"@slack/client": "^3.8.1",
@@ -11,6 +11,7 @@
"apidoc": "^0.17.5",
"autoprefixer": "^8.5.0",
"aws-sdk": "^2.239.1",
"apn": "^2.2.0",
"axios": "^0.18.0",
"axios-progress-bar": "^1.2.0",
"babel-core": "^6.26.3",
@@ -78,7 +79,6 @@
"postcss-easy-import": "^3.0.0",
"ps-tree": "^1.0.0",
"pug": "^2.0.3",
"push-notify": "git://github.com/habitrpg/push-notify.git#6bc2b5fdb1bdc9649b9ec1964d79ca50187fc8a9",
"pusher": "^1.3.0",
"rimraf": "^2.4.3",
"sass-loader": "^7.0.0",
@@ -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",
@@ -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';
@@ -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.';
@@ -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', () => {
@@ -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', () => {
@@ -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;
@@ -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;
@@ -1,7 +1,7 @@
import {
encrypt,
decrypt,
} from '../../../../../website/server/libs/encryption';
} from '../../../../website/server/libs/encryption';
describe('encryption', () => {
it('can encrypt and decrypt', () => {
@@ -5,7 +5,7 @@ import {
BadRequest,
InternalServerError,
NotFound,
} from '../../../../../website/server/libs/errors';
} from '../../../../website/server/libs/errors';
describe('Custom Errors', () => {
describe('CustomError', () => {
@@ -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';
@@ -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;
@@ -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', () => {
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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';
@@ -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();
@@ -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;
@@ -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';
@@ -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;
@@ -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';
@@ -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;
@@ -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';
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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';
@@ -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');
@@ -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;
@@ -1,13 +1,13 @@
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 apn from 'apn/mock';
import nconf from 'nconf';
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;
@@ -24,7 +24,7 @@ describe('pushNotifications', () => {
sandbox.stub(gcmLib.Sender.prototype, 'send').callsFake(fcmSendSpy);
sandbox.stub(pushNotify, 'apn').returns({
sandbox.stub(apn.Provider.prototype, 'send').returns({
on: () => null,
send: apnSendSpy,
});
@@ -104,10 +104,7 @@ describe('pushNotifications', () => {
},
};
sendPushNotification(user, details);
expect(apnSendSpy).to.have.been.calledOnce;
expect(apnSendSpy).to.have.been.calledWithMatch({
token: '123',
const expectedNotification = new apn.Notification({
alert: message,
sound: 'default',
category: 'fun',
@@ -117,6 +114,10 @@ describe('pushNotifications', () => {
b: true,
},
});
sendPushNotification(user, details);
expect(apnSendSpy).to.have.been.calledOnce;
expect(apnSendSpy).to.have.been.calledWithMatch(expectedNotification, '123');
expect(fcmSendSpy).to.not.have.been.called;
});
});
@@ -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';
@@ -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 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;
@@ -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;
@@ -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;
@@ -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();
@@ -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;
@@ -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;
@@ -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,8 +166,11 @@ 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);
resolve();
User.findOne({_id: user._id}, function (secondErr, updatedUser) {
if (secondErr) return reject(secondErr);
expect(updatedUser.stats.hp).to.be.lessThan(hpBefore);
resolve();
});
});
});
});
@@ -217,8 +220,11 @@ 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);
resolve();
User.findOne({_id: user._id}, function (secondErr, updatedUser) {
if (secondErr) return reject(secondErr);
expect(updatedUser.stats.hp).to.be.lessThan(hpBefore);
resolve();
});
});
});
});
@@ -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;
@@ -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', () => {
@@ -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;
@@ -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;
@@ -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();
@@ -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();
@@ -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;
@@ -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', () => {
@@ -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;
@@ -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', () => {
@@ -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;
@@ -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', () => {
@@ -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', () => {
@@ -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', () => {
@@ -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', () => {
@@ -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', () => {
@@ -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', () => {
@@ -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', () => {
@@ -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', () => {
@@ -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', () => {
@@ -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', () => {
@@ -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', () => {
@@ -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', () => {
@@ -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', () => {
@@ -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', () => {
@@ -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 () => {
@@ -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;
@@ -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', () => {
@@ -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;
@@ -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', () => {
@@ -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', () => {
@@ -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,
@@ -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', () => {
@@ -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';
@@ -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', () => {
@@ -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/', () => {
@@ -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;
@@ -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';
@@ -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();
@@ -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', () => {
@@ -1,6 +1,6 @@
import {
generateUser,
} from '../../../../helpers/api-v3-integration.helper';
} from '../../../../helpers/api-integration/v3';
import {
updateDocument,
} from '../../../../helpers/mongo';

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