mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 14:47:53 +01:00
after merge
This commit is contained in:
12
.babelrc
12
.babelrc
@@ -1,6 +1,12 @@
|
|||||||
{
|
{
|
||||||
"plugins": [
|
"presets": [
|
||||||
"transform-es2015-modules-commonjs",
|
[
|
||||||
"syntax-object-rest-spread",
|
"@babel/preset-env",
|
||||||
|
{
|
||||||
|
"targets": {
|
||||||
|
"node": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,8 @@ coverage/
|
|||||||
database_reports/
|
database_reports/
|
||||||
website/build/
|
website/build/
|
||||||
website/transpiled-babel/
|
website/transpiled-babel/
|
||||||
|
# Has its own linter
|
||||||
|
website/client/
|
||||||
website/common/transpiled-babel/
|
website/common/transpiled-babel/
|
||||||
dist/
|
dist/
|
||||||
dist-client/
|
dist-client/
|
||||||
|
|||||||
10
.eslintrc
10
.eslintrc
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"root": true,
|
|
||||||
"env": {
|
|
||||||
"node": true,
|
|
||||||
},
|
|
||||||
"extends": [
|
|
||||||
"habitrpg",
|
|
||||||
"habitrpg/esnext"
|
|
||||||
],
|
|
||||||
}
|
|
||||||
6
.eslintrc.js
Normal file
6
.eslintrc.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
extends: [
|
||||||
|
'habitrpg/lib/node'
|
||||||
|
],
|
||||||
|
}
|
||||||
198
.github/workflows/test.yml
vendored
Normal file
198
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
name: Test
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [12.x]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- run: cp config.json.example config.json
|
||||||
|
- name: npm install
|
||||||
|
run: |
|
||||||
|
npm ci
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
- run: npm run lint-no-fix
|
||||||
|
apidoc:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [12.x]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- run: cp config.json.example config.json
|
||||||
|
- name: npm install
|
||||||
|
run: |
|
||||||
|
npm ci
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
- run: npm run apidoc
|
||||||
|
sanity:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [12.x]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- run: cp config.json.example config.json
|
||||||
|
- name: npm install
|
||||||
|
run: |
|
||||||
|
npm ci
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
- run: npm run test:sanity
|
||||||
|
|
||||||
|
common:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [12.x]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- run: cp config.json.example config.json
|
||||||
|
- name: npm install
|
||||||
|
run: |
|
||||||
|
npm ci
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
- run: npm run test:common
|
||||||
|
content:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [12.x]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- run: cp config.json.example config.json
|
||||||
|
- name: npm install
|
||||||
|
run: |
|
||||||
|
npm ci
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
- run: npm run test:content
|
||||||
|
|
||||||
|
api-unit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [12.x]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- run: sudo docker run --name mongo -d -p 27017:27017 mongo
|
||||||
|
- run: cp config.json.example config.json
|
||||||
|
- name: npm install
|
||||||
|
run: |
|
||||||
|
npm ci
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
- run: npm run test:api:unit
|
||||||
|
env:
|
||||||
|
REQUIRES_SERVER=true: true
|
||||||
|
api-v3-integration:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [12.x]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- run: sudo docker run --name mongo -d -p 27017:27017 mongo
|
||||||
|
- run: cp config.json.example config.json
|
||||||
|
- name: npm install
|
||||||
|
run: |
|
||||||
|
npm ci
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
- run: npm run test:api-v3:integration
|
||||||
|
env:
|
||||||
|
REQUIRES_SERVER=true: true
|
||||||
|
api-v4-integration:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [12.x]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- run: sudo docker run --name mongo -d -p 27017:27017 mongo
|
||||||
|
- run: cp config.json.example config.json
|
||||||
|
- name: npm install
|
||||||
|
run: |
|
||||||
|
npm ci
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
- run: npm run test:api-v4:integration
|
||||||
|
env:
|
||||||
|
REQUIRES_SERVER=true: true
|
||||||
|
|
||||||
|
client-unit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [12.x]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- run: cp config.json.example config.json
|
||||||
|
- name: npm install
|
||||||
|
run: |
|
||||||
|
npm ci
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
- run: npm run test:unit
|
||||||
|
working-directory: ./website/client
|
||||||
11
.gitignore
vendored
11
.gitignore
vendored
@@ -1,10 +1,5 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
website/client-old/gen
|
|
||||||
website/client-old/common
|
|
||||||
website/client-old/apidoc
|
|
||||||
website/build
|
website/build
|
||||||
website/client-old/js/habitrpg-shared.js*
|
|
||||||
website/client-old/css/habitrpg-shared.css
|
|
||||||
website/transpiled-babel/
|
website/transpiled-babel/
|
||||||
website/common/transpiled-babel/
|
website/common/transpiled-babel/
|
||||||
node_modules
|
node_modules
|
||||||
@@ -15,8 +10,6 @@ apidoc_build
|
|||||||
config.json
|
config.json
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
lib
|
lib
|
||||||
website/client-old/bower_components
|
|
||||||
website/client-old/new-stuff.html
|
|
||||||
newrelic_agent.log
|
newrelic_agent.log
|
||||||
.bower-tmp
|
.bower-tmp
|
||||||
.bower-registry
|
.bower-registry
|
||||||
@@ -27,15 +20,13 @@ TODO
|
|||||||
*.log
|
*.log
|
||||||
src/*/*.map
|
src/*/*.map
|
||||||
src/*/*/*.map
|
src/*/*/*.map
|
||||||
test/*.js
|
|
||||||
test/*.map
|
|
||||||
website/client-old/docs
|
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
coverage
|
coverage
|
||||||
coverage.html
|
coverage.html
|
||||||
common/dist/scripts/*
|
common/dist/scripts/*
|
||||||
dist
|
dist
|
||||||
dist-client
|
dist-client
|
||||||
|
website/client/dist
|
||||||
test/client/unit/coverage
|
test/client/unit/coverage
|
||||||
test/client/e2e/reports
|
test/client/e2e/reports
|
||||||
test/client-old/spec/mocks/translations.js
|
test/client-old/spec/mocks/translations.js
|
||||||
|
|||||||
@@ -1,20 +1,9 @@
|
|||||||
node_modules/**
|
node_modules/**
|
||||||
.bower-cache/**
|
|
||||||
.bower-tmp/**
|
|
||||||
.bower-registry/**
|
|
||||||
website/client-old/**
|
|
||||||
website/client/**
|
website/client/**
|
||||||
website/client/store/**
|
|
||||||
website/views/**
|
|
||||||
website/build/**
|
|
||||||
dist/**
|
|
||||||
test/**
|
test/**
|
||||||
.git/**
|
.git/**
|
||||||
Gruntfile.js
|
|
||||||
CHANGELOG.md
|
|
||||||
.idea*
|
.idea*
|
||||||
*.log
|
*.log
|
||||||
newrelic_agent.log
|
|
||||||
*.swp
|
*.swp
|
||||||
*.swx
|
*.swx
|
||||||
website/raw_sprites/**
|
website/raw_sprites/**
|
||||||
|
|||||||
29
.travis.yml
29
.travis.yml
@@ -1,29 +0,0 @@
|
|||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- '12'
|
|
||||||
services:
|
|
||||||
- mongodb
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- 'node_modules'
|
|
||||||
addons:
|
|
||||||
chrome: stable
|
|
||||||
before_script:
|
|
||||||
- npm run test:build
|
|
||||||
- cp config.json.example config.json
|
|
||||||
- sleep 5
|
|
||||||
script:
|
|
||||||
- npm run $TEST
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- DISABLE_REQUEST_LOGGING=true
|
|
||||||
matrix:
|
|
||||||
- TEST="lint"
|
|
||||||
- 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
|
|
||||||
- TEST="client:unit" COVERAGE=true
|
|
||||||
- TEST="apidoc"
|
|
||||||
@@ -22,9 +22,6 @@ RUN git clone --branch release --depth 1 https://github.com/HabitRPG/habitica.gi
|
|||||||
RUN npm install
|
RUN npm install
|
||||||
RUN gulp build:prod --force
|
RUN gulp build:prod --force
|
||||||
|
|
||||||
# Create Build dir
|
|
||||||
RUN mkdir -p ./website/build
|
|
||||||
|
|
||||||
# Start Habitica
|
# Start Habitica
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
CMD ["node", "./website/transpiled-babel/index.js"]
|
CMD ["node", "./website/transpiled-babel/index.js"]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Habitica [](https://travis-ci.org/HabitRPG/habitica) [](https://codeclimate.com/github/HabitRPG/habitrpg) [](https://www.bountysource.com/trackers/68393-habitrpg?utm_source=68393&utm_medium=shield&utm_campaign=TRACKER_BADGE) [](https://www.codetriage.com/habitrpg/habitica)
|
Habitica  [](https://codeclimate.com/github/HabitRPG/habitrpg) [](https://www.bountysource.com/trackers/68393-habitrpg?utm_source=68393&utm_medium=shield&utm_campaign=TRACKER_BADGE) [](https://www.codetriage.com/habitrpg/habitica)
|
||||||
===============
|
===============
|
||||||
|
|
||||||
[](https://greenkeeper.io/)
|
[](https://greenkeeper.io/)
|
||||||
|
|||||||
11
VAGRANT.md
11
VAGRANT.md
@@ -1,11 +0,0 @@
|
|||||||
# Vagrant #
|
|
||||||
|
|
||||||
Vagrant is a system to create reproducible and portable development
|
|
||||||
environments. Because of the variety of systems used for Habitica
|
|
||||||
development and the various issues developers may encounter setting up
|
|
||||||
Habitica on them, vagrant provides a single development enviroment with
|
|
||||||
minimal dependencies on the developer's local platform. It can be used
|
|
||||||
on a variety of systems including Windows, Mac OS X, and Linux.
|
|
||||||
|
|
||||||
Instructions for using the Habitica Vagrant environment are in
|
|
||||||
[Setting up Habitica Locally](http://habitica.fandom.com/wiki/Setting_up_Habitica_Locally).
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
# -*- mode: ruby -*-
|
|
||||||
# vi: set ft=ruby :
|
|
||||||
|
|
||||||
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
|
|
||||||
VAGRANTFILE_API_VERSION = "2"
|
|
||||||
|
|
||||||
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
|
||||||
config.vm.provider "virtualbox" do |v|
|
|
||||||
v.memory = 4096
|
|
||||||
v.cpus = 1
|
|
||||||
v.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/vagrant", "1"]
|
|
||||||
end
|
|
||||||
config.vm.box = "thepeopleseason/habitrpg"
|
|
||||||
config.ssh.forward_agent = true
|
|
||||||
|
|
||||||
config.vm.hostname = "habitrpg"
|
|
||||||
config.vm.network "forwarded_port", guest: 3000, host: 3000, auto_correct: true
|
|
||||||
config.vm.usable_port_range = (3000..3050)
|
|
||||||
config.vm.network "forwarded_port", guest: 8080, host: 8080, auto_correct: true
|
|
||||||
config.vm.usable_port_range = (8080..8130)
|
|
||||||
config.vm.provision :shell, :path => "vagrant_scripts/vagrant.sh"
|
|
||||||
end
|
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
"LOGGLY_TOKEN": "example-token",
|
"LOGGLY_TOKEN": "example-token",
|
||||||
"MAINTENANCE_MODE": "false",
|
"MAINTENANCE_MODE": "false",
|
||||||
"NODE_DB_URI": "mongodb://localhost/habitrpg",
|
"NODE_DB_URI": "mongodb://localhost/habitrpg",
|
||||||
|
"MONGODB_POOL_SIZE": "10",
|
||||||
"NODE_ENV": "development",
|
"NODE_ENV": "development",
|
||||||
"PATH": "bin:node_modules/.bin:/usr/local/bin:/usr/bin:/bin",
|
"PATH": "bin:node_modules/.bin:/usr/local/bin:/usr/bin:/bin",
|
||||||
"PAYPAL_BILLING_PLANS_basic_12mo": "basic_12mo",
|
"PAYPAL_BILLING_PLANS_basic_12mo": "basic_12mo",
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ services:
|
|||||||
- .:/code
|
- .:/code
|
||||||
- /code/node_modules
|
- /code/node_modules
|
||||||
mongo:
|
mongo:
|
||||||
image: mongo:3.4
|
image: mongo:3.6
|
||||||
networks:
|
networks:
|
||||||
- habitica
|
- habitica
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ services:
|
|||||||
- mongo
|
- mongo
|
||||||
|
|
||||||
mongo:
|
mongo:
|
||||||
image: mongo:3.4
|
image: mongo:3.6
|
||||||
ports:
|
ports:
|
||||||
- "27017:27017"
|
- "27017:27017"
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import apidoc from 'apidoc';
|
|||||||
|
|
||||||
const APIDOC_DEST_PATH = './apidoc_build';
|
const APIDOC_DEST_PATH = './apidoc_build';
|
||||||
const APIDOC_SRC_PATH = './website/server';
|
const APIDOC_SRC_PATH = './website/server';
|
||||||
gulp.task('apidoc:clean', (done) => {
|
gulp.task('apidoc:clean', done => {
|
||||||
clean(APIDOC_DEST_PATH, done);
|
clean(APIDOC_DEST_PATH, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('apidoc', gulp.series('apidoc:clean', (done) => {
|
gulp.task('apidoc', gulp.series('apidoc:clean', done => {
|
||||||
let result = apidoc.createDoc({
|
const result = apidoc.createDoc({
|
||||||
src: APIDOC_SRC_PATH,
|
src: APIDOC_SRC_PATH,
|
||||||
dest: APIDOC_DEST_PATH,
|
dest: APIDOC_DEST_PATH,
|
||||||
});
|
});
|
||||||
@@ -21,6 +21,4 @@ gulp.task('apidoc', gulp.series('apidoc:clean', (done) => {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
gulp.task('apidoc:watch', gulp.series('apidoc', (done) => {
|
gulp.task('apidoc:watch', gulp.series('apidoc', done => gulp.watch(`${APIDOC_SRC_PATH}/**/*.js`, gulp.series('apidoc', done))));
|
||||||
return gulp.watch(`${APIDOC_SRC_PATH}/**/*.js`, gulp.series('apidoc', done));
|
|
||||||
}));
|
|
||||||
|
|||||||
@@ -1,43 +1,28 @@
|
|||||||
import gulp from 'gulp';
|
import gulp from 'gulp';
|
||||||
import babel from 'gulp-babel';
|
import babel from 'gulp-babel';
|
||||||
import webpackProductionBuild from '../webpack/build';
|
|
||||||
|
|
||||||
gulp.task('build:src', () => {
|
gulp.task('build:src', () => gulp.src('website/server/**/*.js')
|
||||||
return gulp.src('website/server/**/*.js')
|
.pipe(babel())
|
||||||
.pipe(babel())
|
.pipe(gulp.dest('website/transpiled-babel/')));
|
||||||
.pipe(gulp.dest('website/transpiled-babel/'));
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('build:common', () => {
|
gulp.task('build:common', () => gulp.src('website/common/script/**/*.js')
|
||||||
return gulp.src('website/common/script/**/*.js')
|
.pipe(babel())
|
||||||
.pipe(babel())
|
.pipe(gulp.dest('website/common/transpiled-babel/')));
|
||||||
.pipe(gulp.dest('website/common/transpiled-babel/'));
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('build:server', gulp.series('build:src', 'build:common', done => done()));
|
gulp.task('build:server', gulp.series('build:src', 'build:common', done => done()));
|
||||||
|
|
||||||
// Client Production Build
|
|
||||||
gulp.task('build:client', (done) => {
|
|
||||||
webpackProductionBuild((err, output) => {
|
|
||||||
if (err) return done(err);
|
|
||||||
console.log(output); // eslint-disable-line no-console
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('build:prod', gulp.series(
|
gulp.task('build:prod', gulp.series(
|
||||||
'build:server',
|
'build:server',
|
||||||
'build:client',
|
|
||||||
'apidoc',
|
'apidoc',
|
||||||
done => done()
|
done => done(),
|
||||||
));
|
));
|
||||||
|
|
||||||
let buildArgs = [];
|
const buildArgs = [];
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'production') { // eslint-disable-line no-process-env
|
if (process.env.NODE_ENV === 'production') { // eslint-disable-line no-process-env
|
||||||
buildArgs.push('build:prod');
|
buildArgs.push('build:prod');
|
||||||
}
|
}
|
||||||
|
|
||||||
gulp.task('build', gulp.series(buildArgs, (done) => {
|
gulp.task('build', gulp.series(buildArgs, done => {
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
@@ -1,26 +1,30 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import logger from '../website/server/libs/logger';
|
import nconf from 'nconf';
|
||||||
import nconf from 'nconf';
|
import repl from 'repl';
|
||||||
import repl from 'repl';
|
import gulp from 'gulp';
|
||||||
import gulp from 'gulp';
|
import logger from '../website/server/libs/logger';
|
||||||
|
|
||||||
// Add additional properties to the repl's context
|
// Add additional properties to the repl's context
|
||||||
let improveRepl = (context) => {
|
const improveRepl = context => {
|
||||||
// Let "exit" and "quit" terminate the console
|
// Let "exit" and "quit" terminate the console
|
||||||
['exit', 'quit'].forEach((term) => {
|
['exit', 'quit'].forEach(term => {
|
||||||
Object.defineProperty(context, term, { get () {
|
Object.defineProperty(context, term, {
|
||||||
process.exit();
|
get () { // eslint-disable-line getter-return
|
||||||
}});
|
process.exit();
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// "clear" clears the screen
|
// "clear" clears the screen
|
||||||
Object.defineProperty(context, 'clear', { get () {
|
Object.defineProperty(context, 'clear', {
|
||||||
process.stdout.write('\u001B[2J\u001B[0;0f');
|
get () { // eslint-disable-line getter-return
|
||||||
}});
|
process.stdout.write('\u001B[2J\u001B[0;0f');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
context.Challenge = require('../website/server/models/challenge').model; // eslint-disable-line global-require
|
context.Challenge = require('../website/server/models/challenge').model; // eslint-disable-line global-require
|
||||||
context.Group = require('../website/server/models/group').model; // eslint-disable-line global-require
|
context.Group = require('../website/server/models/group').model; // eslint-disable-line global-require
|
||||||
context.User = require('../website/server/models/user').model; // eslint-disable-line global-require
|
context.User = require('../website/server/models/user').model; // eslint-disable-line global-require
|
||||||
|
|
||||||
const isProd = nconf.get('NODE_ENV') === 'production';
|
const isProd = nconf.get('NODE_ENV') === 'production';
|
||||||
const mongooseOptions = !isProd ? {} : {
|
const mongooseOptions = !isProd ? {} : {
|
||||||
@@ -30,14 +34,14 @@ let improveRepl = (context) => {
|
|||||||
mongoose.connect(
|
mongoose.connect(
|
||||||
nconf.get('NODE_DB_URI'),
|
nconf.get('NODE_DB_URI'),
|
||||||
mongooseOptions,
|
mongooseOptions,
|
||||||
(err) => {
|
err => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
logger.info('Connected with Mongoose');
|
logger.info('Connected with Mongoose');
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
gulp.task('console', (done) => {
|
gulp.task('console', done => {
|
||||||
improveRepl(repl.start({
|
improveRepl(repl.start({
|
||||||
prompt: 'Habitica > ',
|
prompt: 'Habitica > ',
|
||||||
}).context);
|
}).context);
|
||||||
|
|||||||
@@ -4,29 +4,29 @@ import spritesmith from 'gulp.spritesmith';
|
|||||||
import clean from 'rimraf';
|
import clean from 'rimraf';
|
||||||
import sizeOf from 'image-size';
|
import sizeOf from 'image-size';
|
||||||
import mergeStream from 'merge-stream';
|
import mergeStream from 'merge-stream';
|
||||||
import {basename} from 'path';
|
import { basename } from 'path';
|
||||||
import {sync} from 'glob';
|
import { sync } from 'glob';
|
||||||
import {each} from 'lodash';
|
import { each } from 'lodash';
|
||||||
import vinylBuffer from 'vinyl-buffer';
|
import vinylBuffer from 'vinyl-buffer';
|
||||||
|
|
||||||
// https://github.com/Ensighten/grunt-spritesmith/issues/67#issuecomment-34786248
|
// https://github.com/Ensighten/grunt-spritesmith/issues/67#issuecomment-34786248
|
||||||
const MAX_SPRITESHEET_SIZE = 1024 * 1024 * 3;
|
const MAX_SPRITESHEET_SIZE = 1024 * 1024 * 3;
|
||||||
|
|
||||||
const IMG_DIST_PATH = 'website/client/assets/images/sprites/';
|
const IMG_DIST_PATH = 'website/client/src/assets/images/sprites/';
|
||||||
const CSS_DIST_PATH = 'website/client/assets/css/sprites/';
|
const CSS_DIST_PATH = 'website/client/src/assets/css/sprites/';
|
||||||
|
|
||||||
function checkForSpecialTreatment (name) {
|
function checkForSpecialTreatment (name) {
|
||||||
let regex = /^hair|skin|beard|mustach|shirt|flower|^headAccessory_special_\w+Ears|^eyewear_special_\w+TopFrame|^eyewear_special_\w+HalfMoon/;
|
const regex = /^hair|skin|beard|mustach|shirt|flower|^headAccessory_special_\w+Ears|^eyewear_special_\w+TopFrame|^eyewear_special_\w+HalfMoon/;
|
||||||
return name.match(regex) || name === 'head_0';
|
return name.match(regex) || name === 'head_0';
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateImgDimensions (img, addPadding) {
|
function calculateImgDimensions (img, addPadding) {
|
||||||
let dims = sizeOf(img);
|
let dims = sizeOf(img);
|
||||||
|
|
||||||
let requiresSpecialTreatment = checkForSpecialTreatment(img);
|
const requiresSpecialTreatment = checkForSpecialTreatment(img);
|
||||||
if (requiresSpecialTreatment) {
|
if (requiresSpecialTreatment) {
|
||||||
let newWidth = dims.width < 90 ? 90 : dims.width;
|
const newWidth = dims.width < 90 ? 90 : dims.width;
|
||||||
let newHeight = dims.height < 90 ? 90 : dims.height;
|
const newHeight = dims.height < 90 ? 90 : dims.height;
|
||||||
dims = {
|
dims = {
|
||||||
width: newWidth,
|
width: newWidth,
|
||||||
height: newHeight,
|
height: newHeight,
|
||||||
@@ -41,17 +41,17 @@ function calculateImgDimensions (img, addPadding) {
|
|||||||
|
|
||||||
if (!dims.width || !dims.height) console.error('MISSING DIMENSIONS:', dims); // eslint-disable-line no-console
|
if (!dims.width || !dims.height) console.error('MISSING DIMENSIONS:', dims); // eslint-disable-line no-console
|
||||||
|
|
||||||
let totalPixelSize = dims.width * dims.height + padding;
|
const totalPixelSize = dims.width * dims.height + padding;
|
||||||
|
|
||||||
return totalPixelSize;
|
return totalPixelSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateSpritesheetsSrcIndicies (src) {
|
function calculateSpritesheetsSrcIndicies (src) {
|
||||||
let totalPixels = 0;
|
let totalPixels = 0;
|
||||||
let slices = [0];
|
const slices = [0];
|
||||||
|
|
||||||
each(src, (img, index) => {
|
each(src, (img, index) => {
|
||||||
let imageSize = calculateImgDimensions(img, true);
|
const imageSize = calculateImgDimensions(img, true);
|
||||||
totalPixels += imageSize;
|
totalPixels += imageSize;
|
||||||
|
|
||||||
if (totalPixels > MAX_SPRITESHEET_SIZE) {
|
if (totalPixels > MAX_SPRITESHEET_SIZE) {
|
||||||
@@ -64,37 +64,35 @@ function calculateSpritesheetsSrcIndicies (src) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cssVarMap (sprite) {
|
function cssVarMap (sprite) {
|
||||||
// For hair, skins, beards, etc. we want to output a '.customize-options.WHATEVER' class, which works as a
|
// For hair, skins, beards, etc. we want to output a '.customize-options.WHATEVER' class,
|
||||||
// 60x60 image pointing at the proper part of the 90x90 sprite.
|
// which works as a 60x60 image pointing at the proper part of the 90x90 sprite.
|
||||||
// We set up the custom info here, and the template makes use of it.
|
// We set up the custom info here, and the template makes use of it.
|
||||||
let requiresSpecialTreatment = checkForSpecialTreatment(sprite.name);
|
const requiresSpecialTreatment = checkForSpecialTreatment(sprite.name);
|
||||||
if (requiresSpecialTreatment) {
|
if (requiresSpecialTreatment) {
|
||||||
sprite.custom = {
|
sprite.custom = {
|
||||||
px: {
|
px: {
|
||||||
offsetX: `-${ sprite.x + 25 }px`,
|
offsetX: `-${sprite.x + 25}px`,
|
||||||
offsetY: `-${ sprite.y + 15 }px`,
|
offsetY: `-${sprite.y + 15}px`,
|
||||||
width: '60px',
|
width: '60px',
|
||||||
height: '60px',
|
height: '60px',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (sprite.name.indexOf('shirt') !== -1)
|
if (sprite.name.indexOf('shirt') !== -1) sprite.custom.px.offsetY = `-${sprite.y + 35}px`; // even more for shirts
|
||||||
sprite.custom.px.offsetY = `-${ sprite.y + 35 }px`; // even more for shirts
|
|
||||||
if (sprite.name.indexOf('hair_base') !== -1) {
|
if (sprite.name.indexOf('hair_base') !== -1) {
|
||||||
let styleArray = sprite.name.split('_').slice(2, 3);
|
const styleArray = sprite.name.split('_').slice(2, 3);
|
||||||
if (Number(styleArray[0]) > 14)
|
if (Number(styleArray[0]) > 14) sprite.custom.px.offsetY = `-${sprite.y}px`; // don't crop updos
|
||||||
sprite.custom.px.offsetY = `-${ sprite.y }px`; // don't crop updos
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSpritesStream (name, src) {
|
function createSpritesStream (name, src) {
|
||||||
let spritesheetSliceIndicies = calculateSpritesheetsSrcIndicies(src);
|
const spritesheetSliceIndicies = calculateSpritesheetsSrcIndicies(src);
|
||||||
let stream = mergeStream();
|
const stream = mergeStream();
|
||||||
|
|
||||||
each(spritesheetSliceIndicies, (start, index) => {
|
each(spritesheetSliceIndicies, (start, index) => {
|
||||||
let slicedSrc = src.slice(start, spritesheetSliceIndicies[index + 1]);
|
const slicedSrc = src.slice(start, spritesheetSliceIndicies[index + 1]);
|
||||||
|
|
||||||
let spriteData = gulp.src(slicedSrc)
|
const spriteData = gulp.src(slicedSrc)
|
||||||
.pipe(spritesmith({
|
.pipe(spritesmith({
|
||||||
imgName: `spritesmith-${name}-${index}.png`,
|
imgName: `spritesmith-${name}-${index}.png`,
|
||||||
cssName: `spritesmith-${name}-${index}.css`,
|
cssName: `spritesmith-${name}-${index}.css`,
|
||||||
@@ -104,12 +102,12 @@ function createSpritesStream (name, src) {
|
|||||||
cssVarMap,
|
cssVarMap,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let imgStream = spriteData.img
|
const imgStream = spriteData.img
|
||||||
.pipe(vinylBuffer())
|
.pipe(vinylBuffer())
|
||||||
.pipe(imagemin())
|
.pipe(imagemin())
|
||||||
.pipe(gulp.dest(IMG_DIST_PATH));
|
.pipe(gulp.dest(IMG_DIST_PATH));
|
||||||
|
|
||||||
let cssStream = spriteData.css
|
const cssStream = spriteData.css
|
||||||
.pipe(gulp.dest(CSS_DIST_PATH));
|
.pipe(gulp.dest(CSS_DIST_PATH));
|
||||||
|
|
||||||
stream.add(imgStream);
|
stream.add(imgStream);
|
||||||
@@ -120,32 +118,32 @@ function createSpritesStream (name, src) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gulp.task('sprites:main', () => {
|
gulp.task('sprites:main', () => {
|
||||||
let mainSrc = sync('website/raw_sprites/spritesmith/**/*.png');
|
const mainSrc = sync('website/raw_sprites/spritesmith/**/*.png');
|
||||||
return createSpritesStream('main', mainSrc);
|
return createSpritesStream('main', mainSrc);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('sprites:largeSprites', () => {
|
gulp.task('sprites:largeSprites', () => {
|
||||||
let largeSrc = sync('website/raw_sprites/spritesmith_large/**/*.png');
|
const largeSrc = sync('website/raw_sprites/spritesmith_large/**/*.png');
|
||||||
return createSpritesStream('largeSprites', largeSrc);
|
return createSpritesStream('largeSprites', largeSrc);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('sprites:clean', (done) => {
|
gulp.task('sprites:clean', done => {
|
||||||
clean(`${IMG_DIST_PATH}spritesmith*,${CSS_DIST_PATH}spritesmith*}`, done);
|
clean(`${IMG_DIST_PATH}spritesmith*,${CSS_DIST_PATH}spritesmith*}`, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('sprites:checkCompiledDimensions', gulp.series('sprites:main', 'sprites:largeSprites', (done) => {
|
gulp.task('sprites:checkCompiledDimensions', gulp.series('sprites:main', 'sprites:largeSprites', done => {
|
||||||
console.log('Verifiying that images do not exceed max dimensions'); // eslint-disable-line no-console
|
console.log('Verifiying that images do not exceed max dimensions'); // eslint-disable-line no-console
|
||||||
|
|
||||||
let numberOfSheetsThatAreTooBig = 0;
|
let numberOfSheetsThatAreTooBig = 0;
|
||||||
|
|
||||||
let distSpritesheets = sync(`${IMG_DIST_PATH}*.png`);
|
const distSpritesheets = sync(`${IMG_DIST_PATH}*.png`);
|
||||||
|
|
||||||
each(distSpritesheets, (img) => {
|
each(distSpritesheets, img => {
|
||||||
let spriteSize = calculateImgDimensions(img);
|
const spriteSize = calculateImgDimensions(img);
|
||||||
|
|
||||||
if (spriteSize > MAX_SPRITESHEET_SIZE) {
|
if (spriteSize > MAX_SPRITESHEET_SIZE) {
|
||||||
numberOfSheetsThatAreTooBig++;
|
numberOfSheetsThatAreTooBig += 1;
|
||||||
let name = basename(img, '.png');
|
const name = basename(img, '.png');
|
||||||
console.error(`WARNING: ${name} might be too big - ${spriteSize} > ${MAX_SPRITESHEET_SIZE}`); // eslint-disable-line no-console
|
console.error(`WARNING: ${name} might be too big - ${spriteSize} > ${MAX_SPRITESHEET_SIZE}`); // eslint-disable-line no-console
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -155,7 +153,8 @@ gulp.task('sprites:checkCompiledDimensions', gulp.series('sprites:main', 'sprite
|
|||||||
console.error( // eslint-disable-line no-console
|
console.error( // eslint-disable-line no-console
|
||||||
`${numberOfSheetsThatAreTooBig} sheets might too big for mobile Safari to be able to handle
|
`${numberOfSheetsThatAreTooBig} sheets might too big for mobile Safari to be able to handle
|
||||||
them, but there is a margin of error in these calculations so it is probably okay. Mention
|
them, but there is a margin of error in these calculations so it is probably okay. Mention
|
||||||
this to an admin so they can test a staging site on mobile Safari after your PR is merged.`);
|
this to an admin so they can test a staging site on mobile Safari after your PR is merged.`,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
console.log('All images are within the correct dimensions'); // eslint-disable-line no-console
|
console.log('All images are within the correct dimensions'); // eslint-disable-line no-console
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
import gulp from 'gulp';
|
import gulp from 'gulp';
|
||||||
import nodemon from 'gulp-nodemon';
|
import nodemon from 'gulp-nodemon';
|
||||||
|
|
||||||
let pkg = require('../package.json');
|
import pkg from '../package.json';
|
||||||
|
|
||||||
gulp.task('nodemon', (done) => {
|
gulp.task('nodemon', done => {
|
||||||
nodemon({
|
nodemon({
|
||||||
script: pkg.main,
|
script: pkg.main,
|
||||||
ignore: [
|
|
||||||
'website/client-old/*',
|
|
||||||
'website/views/*',
|
|
||||||
'common/dist/script/content/*',
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,60 +1,59 @@
|
|||||||
|
import mongoose from 'mongoose';
|
||||||
|
import { exec } from 'child_process';
|
||||||
|
import gulp from 'gulp';
|
||||||
|
import os from 'os';
|
||||||
|
import nconf from 'nconf';
|
||||||
import {
|
import {
|
||||||
pipe,
|
pipe,
|
||||||
} from './taskHelper';
|
} from './taskHelper';
|
||||||
import mongoose from 'mongoose';
|
|
||||||
import { exec } from 'child_process';
|
|
||||||
import gulp from 'gulp';
|
|
||||||
import os from 'os';
|
|
||||||
import nconf from 'nconf';
|
|
||||||
|
|
||||||
// TODO rewrite
|
// TODO rewrite
|
||||||
|
|
||||||
const TEST_SERVER_PORT = 3003;
|
const TEST_SERVER_PORT = 3003;
|
||||||
let server;
|
let server;
|
||||||
|
|
||||||
const TEST_DB_URI = nconf.get('TEST_DB_URI');
|
const TEST_DB_URI = nconf.get('TEST_DB_URI');
|
||||||
|
|
||||||
const SANITY_TEST_COMMAND = 'npm run test:sanity';
|
const SANITY_TEST_COMMAND = 'npm run test:sanity';
|
||||||
const COMMON_TEST_COMMAND = 'npm run test:common';
|
const COMMON_TEST_COMMAND = 'npm run test:common';
|
||||||
const CONTENT_TEST_COMMAND = 'npm run test:content';
|
const CONTENT_TEST_COMMAND = 'npm run test:content';
|
||||||
const CONTENT_OPTIONS = {maxBuffer: 1024 * 500};
|
const CONTENT_OPTIONS = { maxBuffer: 1024 * 500 };
|
||||||
|
|
||||||
/* Helper methods for reporting test summary */
|
/* Helper methods for reporting test summary */
|
||||||
let testResults = [];
|
const testResults = [];
|
||||||
let testCount = (stdout, regexp) => {
|
const testCount = (stdout, regexp) => {
|
||||||
let match = stdout.match(regexp);
|
const match = stdout.match(regexp);
|
||||||
return parseInt(match && match[1] || 0, 10);
|
return parseInt(match && (match[1] || 0), 10);
|
||||||
};
|
};
|
||||||
|
|
||||||
let testBin = (string, additionalEnvVariables = '') => {
|
const testBin = (string, additionalEnvVariables = '') => {
|
||||||
if (os.platform() === 'win32') {
|
if (os.platform() === 'win32') {
|
||||||
if (additionalEnvVariables !== '') {
|
if (additionalEnvVariables !== '') {
|
||||||
additionalEnvVariables = additionalEnvVariables.split(' ').join('&&set ');
|
additionalEnvVariables = additionalEnvVariables.split(' ').join('&&set '); // eslint-disable-line no-param-reassign
|
||||||
additionalEnvVariables = `set ${additionalEnvVariables}&&`;
|
additionalEnvVariables = `set ${additionalEnvVariables}&&`; // eslint-disable-line no-param-reassign
|
||||||
}
|
}
|
||||||
return `set NODE_ENV=test&&${additionalEnvVariables}${string}`;
|
return `set NODE_ENV=test&&${additionalEnvVariables}${string}`;
|
||||||
} else {
|
|
||||||
return `NODE_ENV=test ${additionalEnvVariables} ${string}`;
|
|
||||||
}
|
}
|
||||||
|
return `NODE_ENV=test ${additionalEnvVariables} ${string}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
gulp.task('test:nodemon', gulp.series(function setupNodemon (done) {
|
gulp.task('test:nodemon', gulp.series(done => {
|
||||||
process.env.PORT = TEST_SERVER_PORT; // eslint-disable-line no-process-env
|
process.env.PORT = TEST_SERVER_PORT; // eslint-disable-line no-process-env
|
||||||
process.env.NODE_DB_URI = TEST_DB_URI; // eslint-disable-line no-process-env
|
process.env.NODE_DB_URI = TEST_DB_URI; // eslint-disable-line no-process-env
|
||||||
done();
|
done();
|
||||||
}, 'nodemon'));
|
}, 'nodemon'));
|
||||||
|
|
||||||
gulp.task('test:prepare:mongo', (cb) => {
|
gulp.task('test:prepare:mongo', cb => {
|
||||||
mongoose.connect(TEST_DB_URI, (err) => {
|
mongoose.connect(TEST_DB_URI, err => {
|
||||||
if (err) return cb(`Unable to connect to mongo database. Are you sure it's running? \n\n${err}`);
|
if (err) return cb(`Unable to connect to mongo database. Are you sure it's running? \n\n${err}`);
|
||||||
mongoose.connection.dropDatabase((err2) => {
|
return mongoose.connection.dropDatabase(err2 => {
|
||||||
if (err2) return cb(err2);
|
if (err2) return cb(err2);
|
||||||
mongoose.connection.close(cb);
|
return mongoose.connection.close(cb);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('test:prepare:server', gulp.series('test:prepare:mongo', (done) => {
|
gulp.task('test:prepare:server', gulp.series('test:prepare:mongo', done => {
|
||||||
if (!server) {
|
if (!server) {
|
||||||
server = exec(testBin('node ./website/server/index.js', `NODE_DB_URI=${TEST_DB_URI} PORT=${TEST_SERVER_PORT}`), (error, stdout, stderr) => {
|
server = exec(testBin('node ./website/server/index.js', `NODE_DB_URI=${TEST_DB_URI} PORT=${TEST_SERVER_PORT}`), (error, stdout, stderr) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -73,45 +72,43 @@ gulp.task('test:prepare:build', gulp.series('build', done => done()));
|
|||||||
gulp.task('test:prepare', gulp.series(
|
gulp.task('test:prepare', gulp.series(
|
||||||
'test:prepare:build',
|
'test:prepare:build',
|
||||||
'test:prepare:mongo',
|
'test:prepare:mongo',
|
||||||
done => done()
|
done => done(),
|
||||||
));
|
));
|
||||||
|
|
||||||
gulp.task('test:sanity', (cb) => {
|
gulp.task('test:sanity', cb => {
|
||||||
let runner = exec(
|
const runner = exec(
|
||||||
testBin(SANITY_TEST_COMMAND),
|
testBin(SANITY_TEST_COMMAND),
|
||||||
(err) => {
|
err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
cb();
|
cb();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
pipe(runner);
|
pipe(runner);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('test:common', gulp.series('test:prepare:build', (cb) => {
|
gulp.task('test:common', gulp.series('test:prepare:build', cb => {
|
||||||
let runner = exec(
|
const runner = exec(
|
||||||
testBin(COMMON_TEST_COMMAND),
|
testBin(COMMON_TEST_COMMAND),
|
||||||
(err) => {
|
err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
cb();
|
cb();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
pipe(runner);
|
pipe(runner);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
gulp.task('test:common:clean', (cb) => {
|
gulp.task('test:common:clean', cb => {
|
||||||
pipe(exec(testBin(COMMON_TEST_COMMAND), () => cb()));
|
pipe(exec(testBin(COMMON_TEST_COMMAND), () => cb()));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('test:common:watch', gulp.series('test:common:clean', () => {
|
gulp.task('test:common:watch', gulp.series('test:common:clean', () => gulp.watch(['common/script/**/*', 'test/common/**/*'], gulp.series('test:common:clean', done => done()))));
|
||||||
return gulp.watch(['common/script/**/*', 'test/common/**/*'], gulp.series('test:common:clean', done => done()));
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('test:common:safe', gulp.series('test:prepare:build', (cb) => {
|
gulp.task('test:common:safe', gulp.series('test:prepare:build', cb => {
|
||||||
let runner = exec(
|
const runner = exec(
|
||||||
testBin(COMMON_TEST_COMMAND),
|
testBin(COMMON_TEST_COMMAND),
|
||||||
(err, stdout) => { // eslint-disable-line handle-callback-err
|
(err, stdout) => { // eslint-disable-line handle-callback-err
|
||||||
testResults.push({
|
testResults.push({
|
||||||
@@ -121,38 +118,36 @@ gulp.task('test:common:safe', gulp.series('test:prepare:build', (cb) => {
|
|||||||
pend: testCount(stdout, /(\d+) pending/),
|
pend: testCount(stdout, /(\d+) pending/),
|
||||||
});
|
});
|
||||||
cb();
|
cb();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
pipe(runner);
|
pipe(runner);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
gulp.task('test:content', gulp.series('test:prepare:build', (cb) => {
|
gulp.task('test:content', gulp.series('test:prepare:build', cb => {
|
||||||
let runner = exec(
|
const runner = exec(
|
||||||
testBin(CONTENT_TEST_COMMAND),
|
testBin(CONTENT_TEST_COMMAND),
|
||||||
CONTENT_OPTIONS,
|
CONTENT_OPTIONS,
|
||||||
(err) => {
|
err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
cb();
|
cb();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
pipe(runner);
|
pipe(runner);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
gulp.task('test:content:clean', (cb) => {
|
gulp.task('test:content:clean', cb => {
|
||||||
pipe(exec(testBin(CONTENT_TEST_COMMAND), CONTENT_OPTIONS, () => cb()));
|
pipe(exec(testBin(CONTENT_TEST_COMMAND), CONTENT_OPTIONS, () => cb()));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('test:content:watch', gulp.series('test:content:clean', () => {
|
gulp.task('test:content:watch', gulp.series('test:content:clean', () => gulp.watch(['common/script/content/**', 'test/**'], gulp.series('test:content:clean', done => done()))));
|
||||||
return gulp.watch(['common/script/content/**', 'test/**'], gulp.series('test:content:clean', done => done()));
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('test:content:safe', gulp.series('test:prepare:build', (cb) => {
|
gulp.task('test:content:safe', gulp.series('test:prepare:build', cb => {
|
||||||
let runner = exec(
|
const runner = exec(
|
||||||
testBin(CONTENT_TEST_COMMAND),
|
testBin(CONTENT_TEST_COMMAND),
|
||||||
CONTENT_OPTIONS,
|
CONTENT_OPTIONS,
|
||||||
(err, stdout) => { // eslint-disable-line handle-callback-err
|
(err, stdout) => { // eslint-disable-line handle-callback-err
|
||||||
testResults.push({
|
testResults.push({
|
||||||
suite: 'Content Specs\t',
|
suite: 'Content Specs\t',
|
||||||
pass: testCount(stdout, /(\d+) passing/),
|
pass: testCount(stdout, /(\d+) passing/),
|
||||||
@@ -160,81 +155,77 @@ gulp.task('test:content:safe', gulp.series('test:prepare:build', (cb) => {
|
|||||||
pend: testCount(stdout, /(\d+) pending/),
|
pend: testCount(stdout, /(\d+) pending/),
|
||||||
});
|
});
|
||||||
cb();
|
cb();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
pipe(runner);
|
pipe(runner);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
gulp.task('test:api:unit', (done) => {
|
gulp.task('test:api:unit', done => {
|
||||||
let runner = exec(
|
const runner = exec(
|
||||||
testBin('istanbul cover --dir coverage/api-unit node_modules/mocha/bin/_mocha -- test/api/unit --recursive --require ./test/helpers/start-server'),
|
testBin('istanbul cover --dir coverage/api-unit node_modules/mocha/bin/_mocha -- test/api/unit --recursive --require ./test/helpers/start-server'),
|
||||||
(err) => {
|
err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
done();
|
done();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
pipe(runner);
|
pipe(runner);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('test:api:unit:watch', () => {
|
gulp.task('test:api:unit:watch', () => gulp.watch(['website/server/libs/*', 'test/api/unit/**/*', 'website/server/controllers/**/*'], gulp.series('test:api:unit', done => done())));
|
||||||
return gulp.watch(['website/server/libs/*', 'test/api/unit/**/*', 'website/server/controllers/**/*'], gulp.series('test:api:unit', done => done()));
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('test:api-v3:integration', (done) => {
|
gulp.task('test:api-v3:integration', done => {
|
||||||
let runner = exec(
|
const runner = exec(
|
||||||
testBin('istanbul cover --dir coverage/api-v3-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v3/integration --recursive --require ./test/helpers/start-server'),
|
testBin('istanbul cover --dir coverage/api-v3-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v3/integration --recursive --require ./test/helpers/start-server'),
|
||||||
{maxBuffer: 500 * 1024},
|
{ maxBuffer: 500 * 1024 },
|
||||||
(err) => {
|
err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
done();
|
done();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
pipe(runner);
|
pipe(runner);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('test:api-v3:integration:watch', () => {
|
gulp.task('test:api-v3:integration:watch', () => gulp.watch([
|
||||||
return gulp.watch([
|
'website/server/controllers/api-v3/**/*', 'common/script/ops/*', 'website/server/libs/*.js',
|
||||||
'website/server/controllers/api-v3/**/*', 'common/script/ops/*', 'website/server/libs/*.js',
|
'test/api/v3/integration/**/*',
|
||||||
'test/api/v3/integration/**/*',
|
], gulp.series('test:api-v3:integration', done => done())));
|
||||||
], gulp.series('test:api-v3:integration', done => done()));
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('test:api-v3:integration:separate-server', (done) => {
|
gulp.task('test:api-v3:integration:separate-server', done => {
|
||||||
let runner = exec(
|
const runner = exec(
|
||||||
testBin('mocha test/api/v3/integration --recursive --require ./test/helpers/start-server', 'LOAD_SERVER=0'),
|
testBin('mocha test/api/v3/integration --recursive --require ./test/helpers/start-server', 'LOAD_SERVER=0'),
|
||||||
{maxBuffer: 500 * 1024},
|
{ maxBuffer: 500 * 1024 },
|
||||||
(err) => done(err)
|
err => done(err),
|
||||||
);
|
);
|
||||||
|
|
||||||
pipe(runner);
|
pipe(runner);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('test:api-v4:integration', (done) => {
|
gulp.task('test:api-v4:integration', done => {
|
||||||
let runner = exec(
|
const runner = exec(
|
||||||
testBin('istanbul cover --dir coverage/api-v4-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v4 --recursive --require ./test/helpers/start-server'),
|
testBin('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},
|
{ maxBuffer: 500 * 1024 },
|
||||||
(err) => {
|
err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
done();
|
done();
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
pipe(runner);
|
pipe(runner);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('test:api-v4:integration:separate-server', (done) => {
|
gulp.task('test:api-v4:integration:separate-server', done => {
|
||||||
let runner = exec(
|
const runner = exec(
|
||||||
testBin('mocha test/api/v4 --recursive --require ./test/helpers/start-server', 'LOAD_SERVER=0'),
|
testBin('mocha test/api/v4 --recursive --require ./test/helpers/start-server', 'LOAD_SERVER=0'),
|
||||||
{maxBuffer: 500 * 1024},
|
{ maxBuffer: 500 * 1024 },
|
||||||
(err) => done(err)
|
err => done(err),
|
||||||
);
|
);
|
||||||
|
|
||||||
pipe(runner);
|
pipe(runner);
|
||||||
@@ -247,11 +238,11 @@ gulp.task('test', gulp.series(
|
|||||||
'test:api:unit',
|
'test:api:unit',
|
||||||
'test:api-v3:integration',
|
'test:api-v3:integration',
|
||||||
'test:api-v4:integration',
|
'test:api-v4:integration',
|
||||||
done => done()
|
done => done(),
|
||||||
));
|
));
|
||||||
|
|
||||||
gulp.task('test:api-v3', gulp.series(
|
gulp.task('test:api-v3', gulp.series(
|
||||||
'test:api:unit',
|
'test:api:unit',
|
||||||
'test:api-v3:integration',
|
'test:api-v3:integration',
|
||||||
done => done()
|
done => done(),
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import gulp from 'gulp';
|
import gulp from 'gulp';
|
||||||
import { postToSlack, conf } from './taskHelper';
|
import { postToSlack, conf } from './taskHelper';
|
||||||
|
|
||||||
const SLACK_CONFIG = {
|
const SLACK_CONFIG = {
|
||||||
@@ -14,7 +14,7 @@ const ENGLISH_LOCALE = `${LOCALES}en/`;
|
|||||||
|
|
||||||
|
|
||||||
function getArrayOfLanguages () {
|
function getArrayOfLanguages () {
|
||||||
let languages = fs.readdirSync(LOCALES);
|
const languages = fs.readdirSync(LOCALES);
|
||||||
languages.shift(); // Remove README.md from array of languages
|
languages.shift(); // Remove README.md from array of languages
|
||||||
|
|
||||||
return languages;
|
return languages;
|
||||||
@@ -23,18 +23,16 @@ function getArrayOfLanguages () {
|
|||||||
const ALL_LANGUAGES = getArrayOfLanguages();
|
const ALL_LANGUAGES = getArrayOfLanguages();
|
||||||
|
|
||||||
function stripOutNonJsonFiles (collection) {
|
function stripOutNonJsonFiles (collection) {
|
||||||
let onlyJson = _.filter(collection, (file) => {
|
const onlyJson = _.filter(collection, file => file.match(/[a-zA-Z]*\.json/));
|
||||||
return file.match(/[a-zA-Z]*\.json/);
|
|
||||||
});
|
|
||||||
|
|
||||||
return onlyJson;
|
return onlyJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
function eachTranslationFile (languages, cb) {
|
function eachTranslationFile (languages, cb) {
|
||||||
let jsonFiles = stripOutNonJsonFiles(fs.readdirSync(ENGLISH_LOCALE));
|
const jsonFiles = stripOutNonJsonFiles(fs.readdirSync(ENGLISH_LOCALE));
|
||||||
|
|
||||||
_.each(languages, (lang) => {
|
_.each(languages, lang => {
|
||||||
_.each(jsonFiles, (filename) => {
|
_.each(jsonFiles, filename => {
|
||||||
let parsedTranslationFile;
|
let parsedTranslationFile;
|
||||||
try {
|
try {
|
||||||
const translationFile = fs.readFileSync(`${LOCALES}${lang}/${filename}`);
|
const translationFile = fs.readFileSync(`${LOCALES}${lang}/${filename}`);
|
||||||
@@ -43,10 +41,10 @@ function eachTranslationFile (languages, cb) {
|
|||||||
return cb(err);
|
return cb(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
let englishFile = fs.readFileSync(ENGLISH_LOCALE + filename);
|
const englishFile = fs.readFileSync(ENGLISH_LOCALE + filename);
|
||||||
let parsedEnglishFile = JSON.parse(englishFile);
|
const parsedEnglishFile = JSON.parse(englishFile);
|
||||||
|
|
||||||
cb(null, lang, filename, parsedEnglishFile, parsedTranslationFile);
|
return cb(null, lang, filename, parsedEnglishFile, parsedTranslationFile);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -71,9 +69,9 @@ function formatMessageForPosting (msg, items) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getStringsWith (json, interpolationRegex) {
|
function getStringsWith (json, interpolationRegex) {
|
||||||
let strings = {};
|
const strings = {};
|
||||||
|
|
||||||
_.each(json, (fileName) => {
|
_.each(json, fileName => {
|
||||||
const rawFile = fs.readFileSync(ENGLISH_LOCALE + fileName);
|
const rawFile = fs.readFileSync(ENGLISH_LOCALE + fileName);
|
||||||
const parsedJson = JSON.parse(rawFile);
|
const parsedJson = JSON.parse(rawFile);
|
||||||
|
|
||||||
@@ -93,66 +91,69 @@ const malformedStringExceptions = {
|
|||||||
feedPet: true,
|
feedPet: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
gulp.task('transifex:missingFiles', (done) => {
|
gulp.task('transifex:missingFiles', done => {
|
||||||
let missingStrings = [];
|
const missingStrings = [];
|
||||||
|
|
||||||
eachTranslationFile(ALL_LANGUAGES, (error) => {
|
eachTranslationFile(ALL_LANGUAGES, error => {
|
||||||
if (error) {
|
if (error) {
|
||||||
missingStrings.push(error.path);
|
missingStrings.push(error.path);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!_.isEmpty(missingStrings)) {
|
if (!_.isEmpty(missingStrings)) {
|
||||||
let message = 'the following files were missing from the translations folder';
|
const message = 'the following files were missing from the translations folder';
|
||||||
let formattedMessage = formatMessageForPosting(message, missingStrings);
|
const formattedMessage = formatMessageForPosting(message, missingStrings);
|
||||||
postToSlack(formattedMessage, SLACK_CONFIG);
|
postToSlack(formattedMessage, SLACK_CONFIG);
|
||||||
}
|
}
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('transifex:missingStrings', (done) => {
|
gulp.task('transifex:missingStrings', done => {
|
||||||
let missingStrings = [];
|
const missingStrings = [];
|
||||||
|
|
||||||
eachTranslationString(ALL_LANGUAGES, (language, filename, key, englishString, translationString) => {
|
eachTranslationString(ALL_LANGUAGES, (lang, filename, key, englishString, translationString) => {
|
||||||
if (!translationString) {
|
if (!translationString) {
|
||||||
let errorString = `${language} - ${filename} - ${key} - ${englishString}`;
|
const errorString = `${lang} - ${filename} - ${key} - ${englishString}`;
|
||||||
missingStrings.push(errorString);
|
missingStrings.push(errorString);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!_.isEmpty(missingStrings)) {
|
if (!_.isEmpty(missingStrings)) {
|
||||||
let message = 'The following strings are not translated';
|
const message = 'The following strings are not translated';
|
||||||
let formattedMessage = formatMessageForPosting(message, missingStrings);
|
const formattedMessage = formatMessageForPosting(message, missingStrings);
|
||||||
postToSlack(formattedMessage, SLACK_CONFIG);
|
postToSlack(formattedMessage, SLACK_CONFIG);
|
||||||
}
|
}
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('transifex:malformedStrings', (done) => {
|
gulp.task('transifex:malformedStrings', done => {
|
||||||
let jsonFiles = stripOutNonJsonFiles(fs.readdirSync(ENGLISH_LOCALE));
|
const jsonFiles = stripOutNonJsonFiles(fs.readdirSync(ENGLISH_LOCALE));
|
||||||
let interpolationRegex = /<%= [a-zA-Z]* %>/g;
|
const interpolationRegex = /<%= [a-zA-Z]* %>/g;
|
||||||
let stringsToLookFor = getStringsWith(jsonFiles, interpolationRegex);
|
const stringsToLookFor = getStringsWith(jsonFiles, interpolationRegex);
|
||||||
|
|
||||||
let stringsWithMalformedInterpolations = [];
|
const stringsWithMalformedInterpolations = [];
|
||||||
let stringsWithIncorrectNumberOfInterpolations = [];
|
const stringsWithIncorrectNumberOfInterpolations = [];
|
||||||
|
|
||||||
_.each(ALL_LANGUAGES, (lang) => {
|
_.each(ALL_LANGUAGES, lang => {
|
||||||
_.each(stringsToLookFor, (strings, filename) => {
|
_.each(stringsToLookFor, (strings, filename) => {
|
||||||
let translationFile = fs.readFileSync(`${LOCALES}${lang}/${filename}`);
|
const translationFile = fs.readFileSync(`${LOCALES}${lang}/${filename}`);
|
||||||
let parsedTranslationFile = JSON.parse(translationFile);
|
const parsedTranslationFile = JSON.parse(translationFile);
|
||||||
|
|
||||||
_.each(strings, (value, key) => { // eslint-disable-line max-nested-callbacks
|
_.each(strings, (value, key) => { // eslint-disable-line max-nested-callbacks
|
||||||
let translationString = parsedTranslationFile[key];
|
const translationString = parsedTranslationFile[key];
|
||||||
if (!translationString) return;
|
if (!translationString) return;
|
||||||
|
|
||||||
let englishOccurences = stringsToLookFor[filename][key];
|
const englishOccurences = stringsToLookFor[filename][key];
|
||||||
let translationOccurences = translationString.match(interpolationRegex);
|
const translationOccurences = translationString.match(interpolationRegex);
|
||||||
|
|
||||||
if (!translationOccurences) {
|
if (!translationOccurences) {
|
||||||
let malformedString = `${lang} - ${filename} - ${key} - ${translationString}`;
|
const malformedString = `${lang} - ${filename} - ${key} - ${translationString}`;
|
||||||
stringsWithMalformedInterpolations.push(malformedString);
|
stringsWithMalformedInterpolations.push(malformedString);
|
||||||
} else if (englishOccurences.length !== translationOccurences.length && !malformedStringExceptions[key]) {
|
} else if (
|
||||||
let missingInterpolationString = `${lang} - ${filename} - ${key} - ${translationString}`;
|
englishOccurences.length !== translationOccurences.length
|
||||||
|
&& !malformedStringExceptions[key]
|
||||||
|
) {
|
||||||
|
const missingInterpolationString = `${lang} - ${filename} - ${key} - ${translationString}`;
|
||||||
stringsWithIncorrectNumberOfInterpolations.push(missingInterpolationString);
|
stringsWithIncorrectNumberOfInterpolations.push(missingInterpolationString);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -160,14 +161,17 @@ gulp.task('transifex:malformedStrings', (done) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!_.isEmpty(stringsWithMalformedInterpolations)) {
|
if (!_.isEmpty(stringsWithMalformedInterpolations)) {
|
||||||
let message = 'The following strings have malformed or missing interpolations';
|
const message = 'The following strings have malformed or missing interpolations';
|
||||||
let formattedMessage = formatMessageForPosting(message, stringsWithMalformedInterpolations);
|
const formattedMessage = formatMessageForPosting(message, stringsWithMalformedInterpolations);
|
||||||
postToSlack(formattedMessage, SLACK_CONFIG);
|
postToSlack(formattedMessage, SLACK_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_.isEmpty(stringsWithIncorrectNumberOfInterpolations)) {
|
if (!_.isEmpty(stringsWithIncorrectNumberOfInterpolations)) {
|
||||||
let message = 'The following strings have a different number of string interpolations';
|
const message = 'The following strings have a different number of string interpolations';
|
||||||
let formattedMessage = formatMessageForPosting(message, stringsWithIncorrectNumberOfInterpolations);
|
const formattedMessage = formatMessageForPosting(
|
||||||
|
message,
|
||||||
|
stringsWithIncorrectNumberOfInterpolations,
|
||||||
|
);
|
||||||
postToSlack(formattedMessage, SLACK_CONFIG);
|
postToSlack(formattedMessage, SLACK_CONFIG);
|
||||||
}
|
}
|
||||||
done();
|
done();
|
||||||
@@ -176,5 +180,5 @@ gulp.task('transifex:malformedStrings', (done) => {
|
|||||||
gulp.task(
|
gulp.task(
|
||||||
'transifex',
|
'transifex',
|
||||||
gulp.series('transifex:missingFiles', 'transifex:missingStrings', 'transifex:malformedStrings'),
|
gulp.series('transifex:missingFiles', 'transifex:missingStrings', 'transifex:malformedStrings'),
|
||||||
(done) => done()
|
done => done(),
|
||||||
);
|
);
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { exec } from 'child_process';
|
import { exec } from 'child_process';
|
||||||
import psTree from 'ps-tree';
|
import psTree from 'ps-tree';
|
||||||
import nconf from 'nconf';
|
import nconf from 'nconf';
|
||||||
import net from 'net';
|
import net from 'net';
|
||||||
import { post } from 'superagent';
|
import { post } from 'superagent';
|
||||||
import { sync as glob } from 'glob';
|
import { sync as glob } from 'glob';
|
||||||
import Mocha from 'mocha';
|
import Mocha from 'mocha'; // eslint-disable-line import/no-extraneous-dependencies
|
||||||
import { resolve } from 'path';
|
import { resolve } from 'path';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get access to configruable values
|
* Get access to configruable values
|
||||||
@@ -19,15 +19,15 @@ export const conf = nconf;
|
|||||||
* its tasks.
|
* its tasks.
|
||||||
*/
|
*/
|
||||||
export function kill (proc) {
|
export function kill (proc) {
|
||||||
let killProcess = (pid) => {
|
const killProcess = pid => {
|
||||||
psTree(pid, (_, pids) => {
|
psTree(pid, (_, pids) => {
|
||||||
if (pids.length) {
|
if (pids.length) {
|
||||||
pids.forEach(kill); return;
|
pids.forEach(kill); return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
exec(/^win/.test(process.platform) ?
|
exec(/^win/.test(process.platform)
|
||||||
`taskkill /PID ${pid} /T /F` :
|
? `taskkill /PID ${pid} /T /F`
|
||||||
`kill -9 ${pid}`);
|
: `kill -9 ${pid}`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e); // eslint-disable-line no-console
|
console.log(e); // eslint-disable-line no-console
|
||||||
}
|
}
|
||||||
@@ -46,16 +46,15 @@ export function kill (proc) {
|
|||||||
export function awaitPort (port, max = 60) {
|
export function awaitPort (port, max = 60) {
|
||||||
return new Promise((rej, res) => {
|
return new Promise((rej, res) => {
|
||||||
let socket;
|
let socket;
|
||||||
let timeout;
|
|
||||||
let interval;
|
let interval;
|
||||||
|
|
||||||
timeout = setTimeout(() => {
|
const timeout = setTimeout(() => {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
rej(`Timed out after ${max} seconds`);
|
rej(`Timed out after ${max} seconds`);
|
||||||
}, max * 1000);
|
}, max * 1000);
|
||||||
|
|
||||||
interval = setInterval(() => {
|
interval = setInterval(() => {
|
||||||
socket = net.connect({port}, () => {
|
socket = net.connect({ port }, () => {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
socket.destroy();
|
socket.destroy();
|
||||||
@@ -71,10 +70,10 @@ export function awaitPort (port, max = 60) {
|
|||||||
* Pipe the child's stdin and stderr to the parent process.
|
* Pipe the child's stdin and stderr to the parent process.
|
||||||
*/
|
*/
|
||||||
export function pipe (child) {
|
export function pipe (child) {
|
||||||
child.stdout.on('data', (data) => {
|
child.stdout.on('data', data => {
|
||||||
process.stdout.write(data);
|
process.stdout.write(data);
|
||||||
});
|
});
|
||||||
child.stderr.on('data', (data) => {
|
child.stderr.on('data', data => {
|
||||||
process.stderr.write(data);
|
process.stderr.write(data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -83,7 +82,7 @@ export function pipe (child) {
|
|||||||
* Post request to notify configured slack channel
|
* Post request to notify configured slack channel
|
||||||
*/
|
*/
|
||||||
export function postToSlack (msg, config = {}) {
|
export function postToSlack (msg, config = {}) {
|
||||||
let slackUrl = nconf.get('SLACK_URL');
|
const slackUrl = nconf.get('SLACK_URL');
|
||||||
|
|
||||||
if (!slackUrl) {
|
if (!slackUrl) {
|
||||||
console.error('No slack post url specified. Your message was:'); // eslint-disable-line no-console
|
console.error('No slack post url specified. Your message was:'); // eslint-disable-line no-console
|
||||||
@@ -99,7 +98,7 @@ export function postToSlack (msg, config = {}) {
|
|||||||
text: msg,
|
text: msg,
|
||||||
icon_emoji: `:${config.emoji || 'gulp'}:`, // eslint-disable-line camelcase
|
icon_emoji: `:${config.emoji || 'gulp'}:`, // eslint-disable-line camelcase
|
||||||
})
|
})
|
||||||
.end((err) => {
|
.end(err => {
|
||||||
if (err) console.error('Unable to post to slack', err); // eslint-disable-line no-console
|
if (err) console.error('Unable to post to slack', err); // eslint-disable-line no-console
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -107,15 +106,15 @@ export function postToSlack (msg, config = {}) {
|
|||||||
export function runMochaTests (files, server, cb) {
|
export function runMochaTests (files, server, cb) {
|
||||||
require('../test/helpers/globals.helper'); // eslint-disable-line global-require
|
require('../test/helpers/globals.helper'); // eslint-disable-line global-require
|
||||||
|
|
||||||
let mocha = new Mocha({reporter: 'spec'});
|
const mocha = new Mocha({ reporter: 'spec' });
|
||||||
let tests = glob(files);
|
const tests = glob(files);
|
||||||
|
|
||||||
tests.forEach((test) => {
|
tests.forEach(test => {
|
||||||
delete require.cache[resolve(test)];
|
delete require.cache[resolve(test)];
|
||||||
mocha.addFile(test);
|
mocha.addFile(test);
|
||||||
});
|
});
|
||||||
|
|
||||||
mocha.run((numberOfFailures) => {
|
mocha.run(numberOfFailures => {
|
||||||
if (!process.env.RUN_INTEGRATION_TEST_FOREVER) { // eslint-disable-line no-process-env
|
if (!process.env.RUN_INTEGRATION_TEST_FOREVER) { // eslint-disable-line no-process-env
|
||||||
if (server) kill(server);
|
if (server) kill(server);
|
||||||
process.exit(numberOfFailures);
|
process.exit(numberOfFailures);
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
* directory, and it will automatically be included.
|
* directory, and it will automatically be included.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require('babel-register');
|
/* eslint-disable import/no-commonjs */
|
||||||
|
require('@babel/register');
|
||||||
|
|
||||||
const gulp = require('gulp');
|
const gulp = require('gulp');
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"root": false,
|
|
||||||
"rules": {
|
|
||||||
"no-console": 0,
|
|
||||||
"no-use-before-define": ["error", { "functions": false }]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
8
migrations/.eslintrc.js
Normal file
8
migrations/.eslintrc.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/* eslint-disable import/no-commonjs */
|
||||||
|
module.exports = {
|
||||||
|
root: false,
|
||||||
|
rules: {
|
||||||
|
'no-console': 0,
|
||||||
|
'no-use-before-define': ['error', { functions: false }]
|
||||||
|
}
|
||||||
|
}
|
||||||
82
migrations/archive/2019/20191022_pet_color_achievements.js
Normal file
82
migrations/archive/2019/20191022_pet_color_achievements.js
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
const MIGRATION_NAME = '20191022_pet_color_achievements';
|
||||||
|
import { model as User } from '../../../website/server/models/user';
|
||||||
|
|
||||||
|
const progressCount = 1000;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
async function updateUser (user) {
|
||||||
|
count++;
|
||||||
|
|
||||||
|
let set = {
|
||||||
|
migration: MIGRATION_NAME,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (user && user.items && user.items.pets) {
|
||||||
|
const pets = user.items.pets;
|
||||||
|
if (pets['Wolf-Zombie'] > 0
|
||||||
|
&& pets['TigerCub-Zombie'] > 0
|
||||||
|
&& pets['PandaCub-Zombie'] > 0
|
||||||
|
&& pets['LionCub-Zombie'] > 0
|
||||||
|
&& pets['Fox-Zombie'] > 0
|
||||||
|
&& pets['FlyingPig-Zombie'] > 0
|
||||||
|
&& pets['Dragon-Zombie'] > 0
|
||||||
|
&& pets['Cactus-Zombie'] > 0
|
||||||
|
&& pets['BearCub-Zombie'] > 0) {
|
||||||
|
set['achievements.monsterMagus'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user && user.items && user.items.mounts) {
|
||||||
|
const mounts = user.items.mounts;
|
||||||
|
if (mounts['Wolf-Zombie']
|
||||||
|
&& mounts['TigerCub-Zombie']
|
||||||
|
&& mounts['PandaCub-Zombie']
|
||||||
|
&& mounts['LionCub-Zombie']
|
||||||
|
&& mounts['Fox-Zombie']
|
||||||
|
&& mounts['FlyingPig-Zombie']
|
||||||
|
&& mounts['Dragon-Zombie']
|
||||||
|
&& mounts['Cactus-Zombie']
|
||||||
|
&& mounts['BearCub-Zombie'] ) {
|
||||||
|
set['achievements.undeadUndertaker'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
|
||||||
|
return await User.update({ _id: user._id }, { $set: set }).exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = async function processUsers () {
|
||||||
|
let query = {
|
||||||
|
migration: { $ne: MIGRATION_NAME },
|
||||||
|
'auth.timestamps.loggedin': { $gt: new Date('2019-10-01') },
|
||||||
|
};
|
||||||
|
|
||||||
|
const fields = {
|
||||||
|
_id: 1,
|
||||||
|
items: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true) { // eslint-disable-line no-constant-condition
|
||||||
|
const users = await User // eslint-disable-line no-await-in-loop
|
||||||
|
.find(query)
|
||||||
|
.limit(250)
|
||||||
|
.sort({_id: 1})
|
||||||
|
.select(fields)
|
||||||
|
.lean()
|
||||||
|
.exec();
|
||||||
|
|
||||||
|
if (users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
console.warn(`\n${count} users processed\n`);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
query._id = {
|
||||||
|
$gt: users[users.length - 1]._id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -2,14 +2,14 @@ import { model as Challenges } from '../../website/server/models/challenge';
|
|||||||
import { model as User } from '../../website/server/models/user';
|
import { model as User } from '../../website/server/models/user';
|
||||||
|
|
||||||
async function syncChallengeToMembers (challenges) {
|
async function syncChallengeToMembers (challenges) {
|
||||||
let challengSyncPromises = challenges.map(async (challenge) => {
|
const challengSyncPromises = challenges.map(async challenge => {
|
||||||
let users = await User.find({
|
const users = await User.find({
|
||||||
// _id: '',
|
// _id: '',
|
||||||
challenges: challenge._id,
|
challenges: challenge._id,
|
||||||
}).exec();
|
}).exec();
|
||||||
|
|
||||||
let promises = [];
|
const promises = [];
|
||||||
users.forEach((user) => {
|
users.forEach(user => {
|
||||||
promises.push(challenge.syncToUser(user));
|
promises.push(challenge.syncToUser(user));
|
||||||
promises.push(challenge.save());
|
promises.push(challenge.save());
|
||||||
promises.push(user.save());
|
promises.push(user.save());
|
||||||
@@ -18,11 +18,11 @@ async function syncChallengeToMembers (challenges) {
|
|||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
});
|
});
|
||||||
|
|
||||||
return await Promise.all(challengSyncPromises);
|
return Promise.all(challengSyncPromises);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function syncChallenges (lastChallengeDate) {
|
async function syncChallenges (lastChallengeDate) {
|
||||||
let query = {
|
const query = {
|
||||||
// _id: '',
|
// _id: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -30,16 +30,16 @@ async function syncChallenges (lastChallengeDate) {
|
|||||||
query.createdOn = { $lte: lastChallengeDate };
|
query.createdOn = { $lte: lastChallengeDate };
|
||||||
}
|
}
|
||||||
|
|
||||||
let challengesFound = await Challenges.find(query)
|
const challengesFound = await Challenges.find(query)
|
||||||
.limit(10)
|
.limit(10)
|
||||||
.sort('-createdAt')
|
.sort('-createdAt')
|
||||||
.exec();
|
.exec();
|
||||||
|
|
||||||
let syncedChallenges = await syncChallengeToMembers(challengesFound)
|
const syncedChallenges = await syncChallengeToMembers(challengesFound)
|
||||||
.catch(reason => console.error(reason));
|
.catch(reason => console.error(reason));
|
||||||
let lastChallenge = challengesFound[challengesFound.length - 1];
|
const lastChallenge = challengesFound[challengesFound.length - 1];
|
||||||
if (lastChallenge) syncChallenges(lastChallenge.createdAt);
|
if (lastChallenge) syncChallenges(lastChallenge.createdAt);
|
||||||
return syncedChallenges;
|
return syncedChallenges;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = syncChallenges;
|
export default syncChallenges;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
db.users.update({_id: {$in: ['']}}, {$inc: {balance: 0.5}}, {multi: true});
|
db.users.update({ _id: { $in: [''] } }, { $inc: { balance: 0.5 } }, { multi: true });
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
// mongo habitrpg ./node_modules/moment/moment.js ./migrations/cancelSubscription.js
|
// mongo habitrpg ./node_modules/moment/moment.js ./migrations/cancelSubscription.js
|
||||||
|
|
||||||
// For some reason people often to contact me to cancel their sub, rather than do it online. Even when I point them to
|
// For some reason people often to contact me to cancel their sub,
|
||||||
|
// rather than do it online. Even when I point them to
|
||||||
// the FAQ (http://goo.gl/1uoPGQ) they insist...
|
// the FAQ (http://goo.gl/1uoPGQ) they insist...
|
||||||
|
|
||||||
db.users.update(
|
db.users.update(
|
||||||
{_id: ''},
|
{ _id: '' },
|
||||||
{$set: {
|
{
|
||||||
'purchased.plan.dateTerminated': moment().add('month', 1).toDate(),
|
$set: {
|
||||||
}}
|
'purchased.plan.dateTerminated': moment().add('month', 1).toDate(),
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
// Give contrib.level 7+ free subscription for life
|
// Give contrib.level 7+ free subscription for life
|
||||||
db.users.update(
|
db.users.update(
|
||||||
|
|
||||||
{
|
{
|
||||||
'contributor.level': {$gte: 7},
|
'contributor.level': { $gte: 7 },
|
||||||
'purchased.plan.customerId': null,
|
'purchased.plan.customerId': null,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -18,6 +17,6 @@ db.users.update(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{multi: true}
|
{ multi: true },
|
||||||
|
|
||||||
);
|
);
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// mongo habitrpg ./node_modules/moment/moment.js ./migrations/current_period_end.js
|
// mongo habitrpg ./node_modules/moment/moment.js ./migrations/current_period_end.js
|
||||||
db.users.update(
|
db.users.update(
|
||||||
{_id: ''},
|
{ _id: '' },
|
||||||
{$set: {'purchased.plan.dateTerminated': moment().add({days: 7}).toDate()}}
|
{ $set: { 'purchased.plan.dateTerminated': moment().add({ days: 7 }).toDate() } },
|
||||||
);
|
);
|
||||||
@@ -39,38 +39,52 @@
|
|||||||
// needed. Do not miss any of them!
|
// needed. Do not miss any of them!
|
||||||
|
|
||||||
|
|
||||||
let uuid = '30fb2640-7121-4968-ace5-f385e60ea6c5';
|
const uuid = '30fb2640-7121-4968-ace5-f385e60ea6c5';
|
||||||
|
|
||||||
db.users.aggregate([
|
db.users.aggregate([
|
||||||
{$match: {
|
{
|
||||||
_id: uuid,
|
$match: {
|
||||||
}},
|
_id: uuid,
|
||||||
{$project: {
|
},
|
||||||
_id: 0, todos: 1,
|
},
|
||||||
}},
|
{
|
||||||
{$unwind: '$todos'},
|
$project: {
|
||||||
{$group: {
|
_id: 0, todos: 1,
|
||||||
_id: { taskid: '$todos.id' },
|
},
|
||||||
count: { $sum: 1 },
|
},
|
||||||
}},
|
{ $unwind: '$todos' },
|
||||||
{$match: {
|
{
|
||||||
count: { $gt: 1 },
|
$group: {
|
||||||
}},
|
_id: { taskid: '$todos.id' },
|
||||||
{$project: {
|
count: { $sum: 1 },
|
||||||
'_id.taskid': 1,
|
},
|
||||||
}},
|
},
|
||||||
{$group: {
|
{
|
||||||
_id: { taskid: '$todos.id' },
|
$match: {
|
||||||
troublesomeIds: { $addToSet: '$_id.taskid' },
|
count: { $gt: 1 },
|
||||||
}},
|
},
|
||||||
{$project: {
|
},
|
||||||
_id: 0,
|
{
|
||||||
troublesomeIds: 1,
|
$project: {
|
||||||
}},
|
'_id.taskid': 1,
|
||||||
]).forEach((data) => {
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$group: {
|
||||||
|
_id: { taskid: '$todos.id' },
|
||||||
|
troublesomeIds: { $addToSet: '$_id.taskid' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$project: {
|
||||||
|
_id: 0,
|
||||||
|
troublesomeIds: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]).forEach(data => {
|
||||||
// print( "\n" ); printjson(data);
|
// print( "\n" ); printjson(data);
|
||||||
data.troublesomeIds.forEach((taskid) => {
|
data.troublesomeIds.forEach(taskid => {
|
||||||
print(`non-unique task: ${ taskid}`);
|
print(`non-unique task: ${taskid}`); // eslint-disable-line no-restricted-globals
|
||||||
db.users.update({
|
db.users.update({
|
||||||
_id: uuid,
|
_id: uuid,
|
||||||
todos: { $elemMatch: { id: taskid } },
|
todos: { $elemMatch: { id: taskid } },
|
||||||
@@ -81,8 +95,7 @@ db.users.aggregate([
|
|||||||
});
|
});
|
||||||
|
|
||||||
db.users.update(
|
db.users.update(
|
||||||
{_id: uuid},
|
{ _id: uuid },
|
||||||
{$pull: { todos: { id: 'de666' } } },
|
{ $pull: { todos: { id: 'de666' } } },
|
||||||
{multi: false }
|
{ multi: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
let oldId = '';
|
const oldId = '';
|
||||||
let newId = '';
|
const newId = '';
|
||||||
let newUser = db.users.findOne({_id: newId});
|
const newUser = db.users.findOne({ _id: newId });
|
||||||
|
|
||||||
db.users.update({_id: oldId}, {$set: {auth: newUser.auth}});
|
db.users.update({ _id: oldId }, { $set: { auth: newUser.auth } });
|
||||||
|
|
||||||
// remove the auth on the new user (which is a template account). The account will be preened automatically later,
|
// remove the auth on the new user (which is a template account).
|
||||||
|
// The account will be preened automatically later,
|
||||||
// this allows us to keep the account around a few days in case there was a mistake
|
// this allows us to keep the account around a few days in case there was a mistake
|
||||||
db.users.update({_id: newId}, {$unset: {auth: 1}});
|
db.users.update({ _id: newId }, { $unset: { auth: 1 } });
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
* Past in the text of a unique habit here to find the user, then you can restore their UUID
|
* Past in the text of a unique habit here to find the user, then you can restore their UUID
|
||||||
*/
|
*/
|
||||||
|
|
||||||
db.users.find().forEach((user) => {
|
db.users.find().forEach(user => {
|
||||||
user.tasks = user.habits.concat(user.dailys).concat(user.todos).concat(user.rewards);
|
user.tasks = user.habits.concat(user.dailys).concat(user.todos).concat(user.rewards);
|
||||||
let found = _.some(user.tasks, {text: ''});
|
const found = _.some(user.tasks, { text: '' });
|
||||||
if (found) printjson({id: user._id, auth: user.auth});
|
if (found) printjson({ id: user._id, auth: user.auth });
|
||||||
});
|
});
|
||||||
@@ -1,32 +1,34 @@
|
|||||||
// mongo habitrpg ./node_modules/moment/moment.js ./migrations/freeMonth.js
|
// mongo habitrpg ./node_modules/moment/moment.js ./migrations/freeMonth.js
|
||||||
|
|
||||||
db.users.update(
|
db.users.update(
|
||||||
{_id: ''},
|
{ _id: '' },
|
||||||
{$set: {
|
{
|
||||||
'purchased.plan.customerId': 'temporary',
|
$set: {
|
||||||
'purchased.plan.paymentMethod': 'Stripe',
|
'purchased.plan.customerId': 'temporary',
|
||||||
'purchased.plan.planId': 'basic_earned',
|
'purchased.plan.paymentMethod': 'Stripe',
|
||||||
'purchased.plan.dateTerminated': moment().add('month', 1).toDate(),
|
'purchased.plan.planId': 'basic_earned',
|
||||||
}}
|
'purchased.plan.dateTerminated': moment().add('month', 1).toDate(),
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
// var m = 12;
|
// var m = 12;
|
||||||
// db.users.update(
|
// db.users.update(
|
||||||
// {_id:''},
|
// {_id:''},
|
||||||
// {$set:{'purchased.plan':{
|
// {$set:{'purchased.plan':{
|
||||||
// planId: 'basic_'+m+'mo',
|
// planId: 'basic_'+m+'mo',
|
||||||
// paymentMethod: 'Paypal',
|
// paymentMethod: 'Paypal',
|
||||||
// customerId: 'Gift',
|
// customerId: 'Gift',
|
||||||
// dateCreated: new Date(),
|
// dateCreated: new Date(),
|
||||||
// dateTerminated: moment().add('month',m).toDate(),
|
// dateTerminated: moment().add('month',m).toDate(),
|
||||||
// dateUpdated: new Date(),
|
// dateUpdated: new Date(),
|
||||||
// extraMonths: 0,
|
// extraMonths: 0,
|
||||||
// gemsBought: 0,
|
// gemsBought: 0,
|
||||||
// mysteryItems: [],
|
// mysteryItems: [],
|
||||||
// consecutive: {
|
// consecutive: {
|
||||||
// count: 0,
|
// count: 0,
|
||||||
// offset: m,
|
// offset: m,
|
||||||
// gemCapExtra: m/3*5,
|
// gemCapExtra: m/3*5,
|
||||||
// trinkets: m/3
|
// trinkets: m/3
|
||||||
// }
|
// }
|
||||||
// }}}
|
// }}}
|
||||||
// )
|
// )
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
db.users.update(
|
db.users.update(
|
||||||
{},
|
{},
|
||||||
{$inc: {'achievements.habiticaDays': 1}},
|
{ $inc: { 'achievements.habiticaDays': 1 } },
|
||||||
{multi: 1}
|
{ multi: 1 },
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
db.users.update({_id: ''}, {$inc: {balance: 5}});
|
db.users.update({ _id: '' }, { $inc: { balance: 5 } });
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { model as Group } from '../../website/server/models/group';
|
|||||||
|
|
||||||
// @TODO: this should probably be a GroupManager library method
|
// @TODO: this should probably be a GroupManager library method
|
||||||
async function addUnlimitedSubscription (groupId, dateTerminated) {
|
async function addUnlimitedSubscription (groupId, dateTerminated) {
|
||||||
let group = await Group.findOne({_id: groupId});
|
const group = await Group.findOne({ _id: groupId });
|
||||||
|
|
||||||
group.purchased.plan.customerId = 'group-unlimited';
|
group.purchased.plan.customerId = 'group-unlimited';
|
||||||
group.purchased.plan.dateCreated = new Date();
|
group.purchased.plan.dateCreated = new Date();
|
||||||
@@ -22,7 +22,7 @@ async function addUnlimitedSubscription (groupId, dateTerminated) {
|
|||||||
group.purchased.plan.planId = 'group_monthly';
|
group.purchased.plan.planId = 'group_monthly';
|
||||||
group.purchased.plan.dateTerminated = null;
|
group.purchased.plan.dateTerminated = null;
|
||||||
if (dateTerminated) {
|
if (dateTerminated) {
|
||||||
let dateToEnd = moment(dateTerminated).toDate();
|
const dateToEnd = moment(dateTerminated).toDate();
|
||||||
group.purchased.plan.dateTerminated = dateToEnd;
|
group.purchased.plan.dateTerminated = dateToEnd;
|
||||||
}
|
}
|
||||||
// group.purchased.plan.owner = ObjectId();
|
// group.purchased.plan.owner = ObjectId();
|
||||||
@@ -31,12 +31,12 @@ async function addUnlimitedSubscription (groupId, dateTerminated) {
|
|||||||
return group.save();
|
return group.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = async function addUnlimitedSubscriptionCreator () {
|
export default async function addUnlimitedSubscriptionCreator () {
|
||||||
let groupId = process.argv[2];
|
const groupId = process.argv[2];
|
||||||
|
|
||||||
if (!groupId) throw Error('Group ID is required');
|
if (!groupId) throw Error('Group ID is required');
|
||||||
|
|
||||||
let dateTerminated = process.argv[3];
|
const dateTerminated = process.argv[3];
|
||||||
|
|
||||||
await addUnlimitedSubscription(groupId, dateTerminated);
|
await addUnlimitedSubscription(groupId, dateTerminated);
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import { model as User } from '../../website/server/models/user';
|
|||||||
|
|
||||||
// @TODO: this should probably be a GroupManager library method
|
// @TODO: this should probably be a GroupManager library method
|
||||||
async function createGroup (name, privacy, type, leaderId) {
|
async function createGroup (name, privacy, type, leaderId) {
|
||||||
let user = await User.findOne({_id: leaderId});
|
const user = await User.findOne({ _id: leaderId });
|
||||||
|
|
||||||
let group = new Group({
|
const group = new Group({
|
||||||
name,
|
name,
|
||||||
privacy,
|
privacy,
|
||||||
type,
|
type,
|
||||||
@@ -17,13 +17,11 @@ async function createGroup (name, privacy, type, leaderId) {
|
|||||||
return Promise.all([group.save(), user.save()]);
|
return Promise.all([group.save(), user.save()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = async function groupCreator () {
|
export default async function groupCreator () {
|
||||||
let name = process.argv[2];
|
const name = process.argv[2];
|
||||||
let privacy = process.argv[3];
|
const privacy = process.argv[3];
|
||||||
let type = process.argv[4];
|
const type = process.argv[4];
|
||||||
let leaderId = process.argv[5];
|
const leaderId = process.argv[5];
|
||||||
|
|
||||||
await createGroup(name, privacy, type, leaderId);
|
await createGroup(name, privacy, type, leaderId);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +1,43 @@
|
|||||||
/* let migrationName = 'Jackalopes for Unlimited Subscribers'; */
|
/* let migrationName = 'Jackalopes for Unlimited Subscribers'; */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This migration will find users with unlimited subscriptions who are also eligible for Jackalope mounts, and award them
|
* This migration will find users with unlimited subscriptions who are also eligible
|
||||||
|
* for Jackalope mounts, and award them
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { model as Group } from '../../website/server/models/group';
|
import { model as Group } from '../../website/server/models/group';
|
||||||
import { model as User } from '../../website/server/models/user';
|
import { model as User } from '../../website/server/models/user';
|
||||||
|
|
||||||
async function handOutJackalopes () {
|
async function handOutJackalopes () {
|
||||||
let promises = [];
|
const promises = [];
|
||||||
let cursor = User.find({
|
const cursor = User.find({
|
||||||
'purchased.plan.customerId': 'habitrpg',
|
'purchased.plan.customerId': 'habitrpg',
|
||||||
}).cursor();
|
}).cursor();
|
||||||
|
|
||||||
cursor.on('data', async (user) => {
|
cursor.on('data', async user => {
|
||||||
console.log(`User: ${ user._id}`);
|
console.log(`User: ${user._id}`);
|
||||||
|
|
||||||
let groupList = [];
|
let groupList = [];
|
||||||
if (user.party._id) groupList.push(user.party._id);
|
if (user.party._id) groupList.push(user.party._id);
|
||||||
groupList = groupList.concat(user.guilds);
|
groupList = groupList.concat(user.guilds);
|
||||||
|
|
||||||
let subscribedGroup =
|
const subscribedGroup = await Group.findOne({
|
||||||
await Group.findOne({
|
_id: { $in: groupList },
|
||||||
_id: {$in: groupList},
|
'purchased.plan.planId': 'group_monthly',
|
||||||
'purchased.plan.planId': 'group_monthly',
|
'purchased.plan.dateTerminated': null,
|
||||||
'purchased.plan.dateTerminated': null,
|
},
|
||||||
},
|
{ _id: 1 });
|
||||||
{_id: 1}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (subscribedGroup) {
|
if (subscribedGroup) {
|
||||||
User.update({_id: user._id}, {$set: {'items.mounts.Jackalope-RoyalPurple': true}}).exec();
|
User.update({ _id: user._id }, { $set: { 'items.mounts.Jackalope-RoyalPurple': true } }).exec();
|
||||||
promises.push(user.save());
|
promises.push(user.save());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
cursor.on('close', async () => {
|
cursor.on('close', async () => {
|
||||||
console.log('done');
|
console.log('done');
|
||||||
return await Promise.all(promises);
|
return Promise.all(promises);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = handOutJackalopes;
|
export default handOutJackalopes;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { model as Group } from '../../website/server/models/group';
|
import { model as Group } from '../../website/server/models/group';
|
||||||
import { model as Chat } from '../../website/server/models/chat';
|
import { chatModel as Chat } from '../../website/server/models/message';
|
||||||
|
|
||||||
async function moveGroupChatToModel (skip = 0) {
|
async function moveGroupChatToModel (skip = 0) {
|
||||||
const groups = await Group.find({})
|
const groups = await Group.find({})
|
||||||
@@ -40,7 +40,7 @@ async function moveGroupChatToModel (skip = 0) {
|
|||||||
|
|
||||||
|
|
||||||
const reducedPromises = promises.reduce((acc, curr) => {
|
const reducedPromises = promises.reduce((acc, curr) => {
|
||||||
acc = acc.concat(curr);
|
acc = acc.concat(curr); // eslint-disable-line no-param-reassign
|
||||||
return acc;
|
return acc;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -49,4 +49,4 @@ async function moveGroupChatToModel (skip = 0) {
|
|||||||
moveGroupChatToModel(skip + 50);
|
moveGroupChatToModel(skip + 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = moveGroupChatToModel;
|
export default moveGroupChatToModel;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import monk from 'monk';
|
import monk from 'monk'; // eslint-disable-line import/no-extraneous-dependencies
|
||||||
import nconf from 'nconf';
|
import nconf from 'nconf';
|
||||||
import stripePayments from '../../website/server/libs/payments/stripe';
|
import stripePayments from '../../website/server/libs/payments/stripe';
|
||||||
|
|
||||||
@@ -12,8 +12,8 @@ import stripePayments from '../../website/server/libs/payments/stripe';
|
|||||||
|
|
||||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
|
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
|
||||||
|
|
||||||
let dbGroups = monk(CONNECTION_STRING).get('groups', { castIds: false });
|
const dbGroups = monk(CONNECTION_STRING).get('groups', { castIds: false });
|
||||||
let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
|
const dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
|
||||||
|
|
||||||
async function fixGroupPlanMembers () {
|
async function fixGroupPlanMembers () {
|
||||||
console.info('Group ID, Customer ID, Plan ID, Quantity, Recorded Member Count, Actual Member Count');
|
console.info('Group ID, Customer ID, Plan ID, Quantity, Recorded Member Count, Actual Member Count');
|
||||||
@@ -24,15 +24,15 @@ async function fixGroupPlanMembers () {
|
|||||||
{
|
{
|
||||||
$and:
|
$and:
|
||||||
[
|
[
|
||||||
{'purchased.plan.planId': {$ne: null}},
|
{ 'purchased.plan.planId': { $ne: null } },
|
||||||
{'purchased.plan.planId': {$ne: ''}},
|
{ 'purchased.plan.planId': { $ne: '' } },
|
||||||
{'purchased.plan.customerId': {$ne: 'cus_9f0DV4g7WHRzpM'}}, // Demo groups
|
{ 'purchased.plan.customerId': { $ne: 'cus_9f0DV4g7WHRzpM' } }, // Demo groups
|
||||||
{'purchased.plan.customerId': {$ne: 'cus_9maalqDOFTrvqx'}},
|
{ 'purchased.plan.customerId': { $ne: 'cus_9maalqDOFTrvqx' } },
|
||||||
],
|
],
|
||||||
$or:
|
$or:
|
||||||
[
|
[
|
||||||
{'purchased.plan.dateTerminated': null},
|
{ 'purchased.plan.dateTerminated': null },
|
||||||
{'purchased.plan.dateTerminated': ''},
|
{ 'purchased.plan.dateTerminated': '' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -40,19 +40,19 @@ async function fixGroupPlanMembers () {
|
|||||||
memberCount: 1,
|
memberCount: 1,
|
||||||
'purchased.plan': 1,
|
'purchased.plan': 1,
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
).each(async (group, {close, pause, resume}) => { // eslint-disable-line no-unused-vars
|
).each(async (group, { close, pause, resume }) => { // eslint-disable-line no-unused-vars
|
||||||
pause();
|
pause();
|
||||||
groupPlanCount++;
|
groupPlanCount += 1;
|
||||||
|
|
||||||
const canonicalMemberCount = await dbUsers.count(
|
const canonicalMemberCount = await dbUsers.count(
|
||||||
{
|
{
|
||||||
$or:
|
$or:
|
||||||
[
|
[
|
||||||
{'party._id': group._id},
|
{ 'party._id': group._id },
|
||||||
{guilds: group._id},
|
{ guilds: group._id },
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
const incorrectMemberCount = group.memberCount !== canonicalMemberCount;
|
const incorrectMemberCount = group.memberCount !== canonicalMemberCount;
|
||||||
|
|
||||||
@@ -73,24 +73,24 @@ async function fixGroupPlanMembers () {
|
|||||||
$set: {
|
$set: {
|
||||||
memberCount: canonicalMemberCount,
|
memberCount: canonicalMemberCount,
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!groupUpdate) return;
|
if (!groupUpdate) return;
|
||||||
|
|
||||||
fixedGroupCount++;
|
fixedGroupCount += 1;
|
||||||
if (group.purchased.plan.paymentMethod === 'Stripe') {
|
if (group.purchased.plan.paymentMethod === 'Stripe') {
|
||||||
await stripePayments.chargeForAdditionalGroupMember(group);
|
await stripePayments.chargeForAdditionalGroupMember(group);
|
||||||
await dbGroups.update(
|
await dbGroups.update(
|
||||||
{_id: group._id},
|
{ _id: group._id },
|
||||||
{$set: {'purchased.plan.quantity': canonicalMemberCount + 2}}
|
{ $set: { 'purchased.plan.quantity': canonicalMemberCount + 2 } },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (incorrectQuantity) {
|
if (incorrectQuantity) {
|
||||||
await dbGroups.update(
|
await dbGroups.update(
|
||||||
{_id: group._id},
|
{ _id: group._id },
|
||||||
{$set: {'purchased.plan.quantity': canonicalMemberCount + 2}}
|
{ $set: { 'purchased.plan.quantity': canonicalMemberCount + 2 } },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,10 +98,10 @@ async function fixGroupPlanMembers () {
|
|||||||
}).then(() => {
|
}).then(() => {
|
||||||
console.info(`Fixed ${fixedGroupCount} out of ${groupPlanCount} active Group Plans`);
|
console.info(`Fixed ${fixedGroupCount} out of ${groupPlanCount} active Group Plans`);
|
||||||
return process.exit(0);
|
return process.exit(0);
|
||||||
}).catch((err) => {
|
}).catch(err => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
return process.exit(1);
|
return process.exit(1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = fixGroupPlanMembers;
|
export default fixGroupPlanMembers;
|
||||||
|
|||||||
@@ -5,29 +5,27 @@ let authorUuid = ''; // ... own data is done
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This migrations will iterate through all groups with a group plan a subscription and resync the free
|
* This migrations will iterate through all groups with a group plan
|
||||||
* subscription to all members
|
* a subscription and resync the free subscription to all members
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { model as Group } from '../../website/server/models/group';
|
import { model as Group } from '../../website/server/models/group';
|
||||||
import * as payments from '../../website/server/libs/payments';
|
import payments from '../../website/server/libs/payments/payments';
|
||||||
|
|
||||||
async function updateGroupsWithGroupPlans () {
|
async function updateGroupsWithGroupPlans () {
|
||||||
let cursor = Group.find({
|
const cursor = Group.find({
|
||||||
'purchased.plan.planId': 'group_monthly',
|
'purchased.plan.planId': 'group_monthly',
|
||||||
'purchased.plan.dateTerminated': null,
|
'purchased.plan.dateTerminated': null,
|
||||||
}).cursor();
|
}).cursor();
|
||||||
|
|
||||||
let promises = [];
|
const promises = [];
|
||||||
|
|
||||||
cursor.on('data', (group) => {
|
cursor.on('data', group => {
|
||||||
promises.push(payments.addSubscriptionToGroupUsers(group));
|
promises.push(payments.addSubscriptionToGroupUsers(group));
|
||||||
promises.push(group.save());
|
promises.push(group.save());
|
||||||
});
|
});
|
||||||
|
|
||||||
cursor.on('close', async () => {
|
cursor.on('close', async () => Promise.all(promises));
|
||||||
return await Promise.all(promises);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = updateGroupsWithGroupPlans;
|
export default updateGroupsWithGroupPlans;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
require('babel-register');
|
/* eslint-disable import/no-commonjs */
|
||||||
|
require('@babel/register'); // eslint-disable-line import/no-extraneous-dependencies
|
||||||
|
|
||||||
// This file must use ES5, everything required can be in ES6
|
// This file must use ES5, everything required can be in ES6
|
||||||
|
|
||||||
@@ -17,12 +18,13 @@ function setUpServer () {
|
|||||||
setUpServer();
|
setUpServer();
|
||||||
|
|
||||||
// Replace this with your migration
|
// Replace this with your migration
|
||||||
const processUsers = require('');
|
const processUsers = () => {}; // require('').default;
|
||||||
|
|
||||||
processUsers()
|
processUsers()
|
||||||
.then(function success () {
|
.then(() => {
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
})
|
})
|
||||||
.catch(function failure (err) {
|
.catch(err => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
|
/* eslint-disable import/no-commonjs */
|
||||||
/* let migrationName = 'new_stuff.js'; */
|
/* let migrationName = 'new_stuff.js'; */
|
||||||
let authorName = 'Sabe'; // in case script author needs to know when their ...
|
const authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||||
let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
const authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set the newStuff flag in all user accounts so they see a Bailey message
|
* set the newStuff flag in all user accounts so they see a Bailey message
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let monk = require('monk');
|
const monk = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||||
let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
|
||||||
let dbUsers = monk(connectionString).get('users', { castIds: false });
|
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
|
const dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||||
|
|
||||||
function processUsers (lastId) {
|
function processUsers (lastId) {
|
||||||
// specify a query to limit the affected users (empty for all users):
|
// specify a query to limit the affected users (empty for all users):
|
||||||
let query = {
|
const query = {
|
||||||
'flags.newStuff': {$ne: true},
|
'flags.newStuff': { $ne: true },
|
||||||
};
|
};
|
||||||
|
|
||||||
if (lastId) {
|
if (lastId) {
|
||||||
@@ -23,29 +25,31 @@ function processUsers (lastId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbUsers.find(query, {
|
dbUsers.find(query, {
|
||||||
sort: {_id: 1},
|
sort: { _id: 1 },
|
||||||
limit: 250,
|
limit: 250,
|
||||||
fields: [], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
// specify fields we are interested in to limit retrieved data
|
||||||
|
// (empty if we're not reading data):
|
||||||
|
fields: [],
|
||||||
})
|
})
|
||||||
.then(updateUsers)
|
.then(updateUsers)
|
||||||
.catch((err) => {
|
.catch(err => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
return exiting(1, `ERROR! ${ err}`);
|
return exiting(1, `ERROR! ${err}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let progressCount = 1000;
|
const progressCount = 1000;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
function updateUsers (users) {
|
function updateUsers (users) {
|
||||||
if (!users || users.length === 0) {
|
if (!users || users.length === 0) {
|
||||||
console.warn('All appropriate users found and modified.');
|
console.warn('All appropriate users found and modified.');
|
||||||
displayData();
|
displayData();
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let userPromises = users.map(updateUser);
|
const userPromises = users.map(updateUser);
|
||||||
let lastUser = users[users.length - 1];
|
const lastUser = users[users.length - 1];
|
||||||
|
|
||||||
return Promise.all(userPromises)
|
return Promise.all(userPromises)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -54,30 +58,31 @@ function updateUsers (users) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateUser (user) {
|
function updateUser (user) {
|
||||||
count++;
|
count += 1;
|
||||||
|
|
||||||
let set = {'flags.newStuff': true};
|
const set = { 'flags.newStuff': true };
|
||||||
|
|
||||||
dbUsers.update({_id: user._id}, {$set: set});
|
dbUsers.update({ _id: user._id }, { $set: set });
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count } ${ user._id}`);
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
if (user._id === authorUuid) console.warn(`${authorName } processed`);
|
if (user._id === authorUuid) console.warn(`${authorName} processed`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayData () {
|
function displayData () {
|
||||||
console.warn(`\n${ count } users processed\n`);
|
console.warn(`\n${count} users processed\n`);
|
||||||
return exiting(0);
|
return exiting(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function exiting (code, msg) {
|
function exiting (code, msg) {
|
||||||
code = code || 0; // 0 = success
|
// 0 = success
|
||||||
|
code = code || 0; // eslint-disable-line no-param-reassign
|
||||||
if (code && !msg) {
|
if (code && !msg) {
|
||||||
msg = 'ERROR!';
|
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||||
}
|
}
|
||||||
if (msg) {
|
if (msg) {
|
||||||
if (code) {
|
if (code) {
|
||||||
console.error(msg);
|
console.error(msg);
|
||||||
} else {
|
} else {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
let migrationName = 'restock_armoire.js';
|
/* eslint-disable import/no-commonjs */
|
||||||
let authorName = 'Sabe'; // in case script author needs to know when their ...
|
const migrationName = 'restock_armoire.js';
|
||||||
let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
const authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||||
|
const authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove flag stating that the Enchanted Armoire is empty, for when new equipment is added
|
* Remove flag stating that the Enchanted Armoire is empty, for when new equipment is added
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let monk = require('monk');
|
const monk = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||||
let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
|
||||||
let dbUsers = monk(connectionString).get('users', { castIds: false });
|
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
|
const dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||||
|
|
||||||
function processUsers (lastId) {
|
function processUsers (lastId) {
|
||||||
// specify a query to limit the affected users (empty for all users):
|
// specify a query to limit the affected users (empty for all users):
|
||||||
let query = {
|
const query = {
|
||||||
'flags.armoireEmpty': true,
|
'flags.armoireEmpty': true,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -23,29 +25,31 @@ function processUsers (lastId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbUsers.find(query, {
|
dbUsers.find(query, {
|
||||||
sort: {_id: 1},
|
sort: { _id: 1 },
|
||||||
limit: 250,
|
limit: 250,
|
||||||
fields: [], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
// specify fields we are interested in to limit retrieved data
|
||||||
|
// (empty if we're not reading data):
|
||||||
|
fields: [],
|
||||||
})
|
})
|
||||||
.then(updateUsers)
|
.then(updateUsers)
|
||||||
.catch((err) => {
|
.catch(err => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
return exiting(1, `ERROR! ${ err}`);
|
return exiting(1, `ERROR! ${err}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let progressCount = 1000;
|
const progressCount = 1000;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
function updateUsers (users) {
|
function updateUsers (users) {
|
||||||
if (!users || users.length === 0) {
|
if (!users || users.length === 0) {
|
||||||
console.warn('All appropriate users found and modified.');
|
console.warn('All appropriate users found and modified.');
|
||||||
displayData();
|
displayData();
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let userPromises = users.map(updateUser);
|
const userPromises = users.map(updateUser);
|
||||||
let lastUser = users[users.length - 1];
|
const lastUser = users[users.length - 1];
|
||||||
|
|
||||||
return Promise.all(userPromises)
|
return Promise.all(userPromises)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -54,30 +58,31 @@ function updateUsers (users) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateUser (user) {
|
function updateUser (user) {
|
||||||
count++;
|
count += 1;
|
||||||
|
|
||||||
let set = {migration: migrationName, 'flags.armoireEmpty': false};
|
const set = { migration: migrationName, 'flags.armoireEmpty': false };
|
||||||
|
|
||||||
dbUsers.update({_id: user._id}, {$set: set});
|
dbUsers.update({ _id: user._id }, { $set: set });
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count } ${ user._id}`);
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
if (user._id === authorUuid) console.warn(`${authorName } processed`);
|
if (user._id === authorUuid) console.warn(`${authorName} processed`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayData () {
|
function displayData () {
|
||||||
console.warn(`\n${ count } users processed\n`);
|
console.warn(`\n${count} users processed\n`);
|
||||||
return exiting(0);
|
return exiting(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function exiting (code, msg) {
|
function exiting (code, msg) {
|
||||||
code = code || 0; // 0 = success
|
// 0 = success
|
||||||
|
code = code || 0; // eslint-disable-line no-param-reassign
|
||||||
if (code && !msg) {
|
if (code && !msg) {
|
||||||
msg = 'ERROR!';
|
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||||
}
|
}
|
||||||
if (msg) {
|
if (msg) {
|
||||||
if (code) {
|
if (code) {
|
||||||
console.error(msg);
|
console.error(msg);
|
||||||
} else {
|
} else {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
let migrationName = 'restock_armoire_for_users_that_need_it.js';
|
/* eslint-disable import/no-commonjs */
|
||||||
let authorName = 'Alys (ALittleYellowSpider)'; // in case script author needs to know when their ...
|
const migrationName = 'restock_armoire_for_users_that_need_it.js';
|
||||||
let authorUuid = '3e595299-3d8a-4a10-bfe0-88f555e4aa0c'; // ... own data is done
|
const authorName = 'Alys (ALittleYellowSpider)'; // in case script author needs to know when their ...
|
||||||
|
const authorUuid = '3e595299-3d8a-4a10-bfe0-88f555e4aa0c'; // ... own data is done
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove flag stating that the Enchanted Armoire is empty,
|
* Remove flag stating that the Enchanted Armoire is empty,
|
||||||
@@ -18,16 +19,17 @@ let authorUuid = '3e595299-3d8a-4a10-bfe0-88f555e4aa0c'; // ... own data is done
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
|
|
||||||
let monk = require('monk');
|
const monk = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||||
let dbUsers = monk(connectionString).get('users', { castIds: false });
|
|
||||||
|
const dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||||
|
|
||||||
|
|
||||||
function processUsers (lastId) {
|
function processUsers (lastId) {
|
||||||
// specify a query to limit the affected users (empty for all users):
|
// specify a query to limit the affected users (empty for all users):
|
||||||
let query = {
|
const query = {
|
||||||
'auth.timestamps.loggedin': {$gt: new Date('2016-01-04')},
|
'auth.timestamps.loggedin': { $gt: new Date('2016-01-04') },
|
||||||
// '_id': authorUuid // FOR TESTING
|
// '_id': authorUuid // FOR TESTING
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -35,7 +37,7 @@ function processUsers (lastId) {
|
|||||||
/* let fields = {
|
/* let fields = {
|
||||||
'flags.armoireEmpty': 1,
|
'flags.armoireEmpty': 1,
|
||||||
'items.gear.owned': 1,
|
'items.gear.owned': 1,
|
||||||
};*/
|
}; */
|
||||||
|
|
||||||
if (lastId) {
|
if (lastId) {
|
||||||
query._id = {
|
query._id = {
|
||||||
@@ -44,32 +46,34 @@ function processUsers (lastId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbUsers.find(query, {
|
dbUsers.find(query, {
|
||||||
sort: {_id: 1},
|
sort: { _id: 1 },
|
||||||
limit: 250,
|
limit: 250,
|
||||||
|
// specify fields we are interested in to limit retrieved data
|
||||||
|
// (empty if we're not reading data):
|
||||||
fields: {
|
fields: {
|
||||||
'flags.armoireEmpty': 1,
|
'flags.armoireEmpty': 1,
|
||||||
'items.gear.owned': 1,
|
'items.gear.owned': 1,
|
||||||
}, // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
},
|
||||||
})
|
})
|
||||||
.then(updateUsers)
|
.then(updateUsers)
|
||||||
.catch((err) => {
|
.catch(err => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
return exiting(1, `ERROR! ${ err}`);
|
return exiting(1, `ERROR! ${err}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let progressCount = 1000;
|
const progressCount = 1000;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
function updateUsers (users) {
|
function updateUsers (users) {
|
||||||
if (!users || users.length === 0) {
|
if (!users || users.length === 0) {
|
||||||
console.warn('All appropriate users found and modified.');
|
console.warn('All appropriate users found and modified.');
|
||||||
displayData();
|
displayData();
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let userPromises = users.map(updateUser);
|
const userPromises = users.map(updateUser);
|
||||||
let lastUser = users[users.length - 1];
|
const lastUser = users[users.length - 1];
|
||||||
|
|
||||||
return Promise.all(userPromises)
|
return Promise.all(userPromises)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -78,19 +82,69 @@ function updateUsers (users) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateUser (user) {
|
function updateUser (user) {
|
||||||
count++;
|
count += 1;
|
||||||
|
|
||||||
let set = {migration: migrationName, 'flags.armoireEmpty': false};
|
const set = { migration: migrationName, 'flags.armoireEmpty': false };
|
||||||
|
|
||||||
|
|
||||||
if (user.flags.armoireEmpty) {
|
if (user.flags.armoireEmpty) {
|
||||||
// this user believes their armoire has no more items in it
|
// this user believes their armoire has no more items in it
|
||||||
if (user.items.gear.owned.weapon_armoire_barristerGavel && user.items.gear.owned.armor_armoire_barristerRobes && user.items.gear.owned.head_armoire_jesterCap && user.items.gear.owned.armor_armoire_jesterCostume && user.items.gear.owned.head_armoire_barristerWig && user.items.gear.owned.weapon_armoire_jesterBaton && user.items.gear.owned.weapon_armoire_lunarSceptre && user.items.gear.owned.armor_armoire_gladiatorArmor && user.items.gear.owned.weapon_armoire_basicCrossbow && user.items.gear.owned.head_armoire_gladiatorHelm && user.items.gear.owned.armor_armoire_lunarArmor && user.items.gear.owned.head_armoire_redHairbow && user.items.gear.owned.head_armoire_violetFloppyHat && user.items.gear.owned.head_armoire_rancherHat && user.items.gear.owned.shield_armoire_gladiatorShield && user.items.gear.owned.head_armoire_blueHairbow && user.items.gear.owned.weapon_armoire_mythmakerSword && user.items.gear.owned.head_armoire_royalCrown && user.items.gear.owned.head_armoire_hornedIronHelm && user.items.gear.owned.weapon_armoire_rancherLasso && user.items.gear.owned.armor_armoire_rancherRobes && user.items.gear.owned.armor_armoire_hornedIronArmor && user.items.gear.owned.armor_armoire_goldenToga && user.items.gear.owned.weapon_armoire_ironCrook && user.items.gear.owned.head_armoire_goldenLaurels && user.items.gear.owned.head_armoire_redFloppyHat && user.items.gear.owned.armor_armoire_plagueDoctorOvercoat && user.items.gear.owned.head_armoire_plagueDoctorHat && user.items.gear.owned.weapon_armoire_goldWingStaff && user.items.gear.owned.head_armoire_yellowHairbow && user.items.gear.owned.eyewear_armoire_plagueDoctorMask && user.items.gear.owned.head_armoire_blackCat && user.items.gear.owned.weapon_armoire_batWand && user.items.gear.owned.head_armoire_orangeCat && user.items.gear.owned.shield_armoire_midnightShield && user.items.gear.owned.armor_armoire_royalRobes && user.items.gear.owned.head_armoire_blueFloppyHat && user.items.gear.owned.shield_armoire_royalCane && user.items.gear.owned.weapon_armoire_shepherdsCrook && user.items.gear.owned.armor_armoire_shepherdRobes && user.items.gear.owned.head_armoire_shepherdHeaddress && user.items.gear.owned.weapon_armoire_blueLongbow && user.items.gear.owned.weapon_armoire_crystalCrescentStaff && user.items.gear.owned.head_armoire_crystalCrescentHat && user.items.gear.owned.armor_armoire_dragonTamerArmor && user.items.gear.owned.head_armoire_dragonTamerHelm && user.items.gear.owned.armor_armoire_crystalCrescentRobes && user.items.gear.owned.shield_armoire_dragonTamerShield && user.items.gear.owned.weapon_armoire_glowingSpear) {
|
if (
|
||||||
|
user.items.gear.owned.weapon_armoire_barristerGavel
|
||||||
|
&& user.items.gear.owned.armor_armoire_barristerRobes
|
||||||
|
&& user.items.gear.owned.head_armoire_jesterCap
|
||||||
|
&& user.items.gear.owned.armor_armoire_jesterCostume
|
||||||
|
&& user.items.gear.owned.head_armoire_barristerWig
|
||||||
|
&& user.items.gear.owned.weapon_armoire_jesterBaton
|
||||||
|
&& user.items.gear.owned.weapon_armoire_lunarSceptre
|
||||||
|
&& user.items.gear.owned.armor_armoire_gladiatorArmor
|
||||||
|
&& user.items.gear.owned.weapon_armoire_basicCrossbow
|
||||||
|
&& user.items.gear.owned.head_armoire_gladiatorHelm
|
||||||
|
&& user.items.gear.owned.armor_armoire_lunarArmor
|
||||||
|
&& user.items.gear.owned.head_armoire_redHairbow
|
||||||
|
&& user.items.gear.owned.head_armoire_violetFloppyHat
|
||||||
|
&& user.items.gear.owned.head_armoire_rancherHat
|
||||||
|
&& user.items.gear.owned.shield_armoire_gladiatorShield
|
||||||
|
&& user.items.gear.owned.head_armoire_blueHairbow
|
||||||
|
&& user.items.gear.owned.weapon_armoire_mythmakerSword
|
||||||
|
&& user.items.gear.owned.head_armoire_royalCrown
|
||||||
|
&& user.items.gear.owned.head_armoire_hornedIronHelm
|
||||||
|
&& user.items.gear.owned.weapon_armoire_rancherLasso
|
||||||
|
&& user.items.gear.owned.armor_armoire_rancherRobes
|
||||||
|
&& user.items.gear.owned.armor_armoire_hornedIronArmor
|
||||||
|
&& user.items.gear.owned.armor_armoire_goldenToga
|
||||||
|
&& user.items.gear.owned.weapon_armoire_ironCrook
|
||||||
|
&& user.items.gear.owned.head_armoire_goldenLaurels
|
||||||
|
&& user.items.gear.owned.head_armoire_redFloppyHat
|
||||||
|
&& user.items.gear.owned.armor_armoire_plagueDoctorOvercoat
|
||||||
|
&& user.items.gear.owned.head_armoire_plagueDoctorHat
|
||||||
|
&& user.items.gear.owned.weapon_armoire_goldWingStaff
|
||||||
|
&& user.items.gear.owned.head_armoire_yellowHairbow
|
||||||
|
&& user.items.gear.owned.eyewear_armoire_plagueDoctorMask
|
||||||
|
&& user.items.gear.owned.head_armoire_blackCat
|
||||||
|
&& user.items.gear.owned.weapon_armoire_batWand
|
||||||
|
&& user.items.gear.owned.head_armoire_orangeCat
|
||||||
|
&& user.items.gear.owned.shield_armoire_midnightShield
|
||||||
|
&& user.items.gear.owned.armor_armoire_royalRobes
|
||||||
|
&& user.items.gear.owned.head_armoire_blueFloppyHat
|
||||||
|
&& user.items.gear.owned.shield_armoire_royalCane
|
||||||
|
&& user.items.gear.owned.weapon_armoire_shepherdsCrook
|
||||||
|
&& user.items.gear.owned.armor_armoire_shepherdRobes
|
||||||
|
&& user.items.gear.owned.head_armoire_shepherdHeaddress
|
||||||
|
&& user.items.gear.owned.weapon_armoire_blueLongbow
|
||||||
|
&& user.items.gear.owned.weapon_armoire_crystalCrescentStaff
|
||||||
|
&& user.items.gear.owned.head_armoire_crystalCrescentHat
|
||||||
|
&& user.items.gear.owned.armor_armoire_dragonTamerArmor
|
||||||
|
&& user.items.gear.owned.head_armoire_dragonTamerHelm
|
||||||
|
&& user.items.gear.owned.armor_armoire_crystalCrescentRobes
|
||||||
|
&& user.items.gear.owned.shield_armoire_dragonTamerShield
|
||||||
|
&& user.items.gear.owned.weapon_armoire_glowingSpear
|
||||||
|
) {
|
||||||
// this user does have all the armoire items so we don't change the flag
|
// this user does have all the armoire items so we don't change the flag
|
||||||
// console.log("don't change: " + user._id); // FOR TESTING
|
// console.log("don't change: " + user._id); // FOR TESTING
|
||||||
} else {
|
} else {
|
||||||
// console.log("change: " + user._id); // FOR TESTING
|
// console.log("change: " + user._id); // FOR TESTING
|
||||||
dbUsers.update({_id: user._id}, {$set: set});
|
dbUsers.update({ _id: user._id }, { $set: set });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// this user already has armoire marked as containing items to be bought
|
// this user already has armoire marked as containing items to be bought
|
||||||
@@ -98,24 +152,25 @@ function updateUser (user) {
|
|||||||
// console.log("DON'T CHANGE: " + user._id); // FOR TESTING
|
// console.log("DON'T CHANGE: " + user._id); // FOR TESTING
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count } ${ user._id}`);
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
if (user._id === authorUuid) console.warn(`${authorName } processed`);
|
if (user._id === authorUuid) console.warn(`${authorName} processed`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayData () {
|
function displayData () {
|
||||||
console.warn(`\n${ count } users processed\n`);
|
console.warn(`\n${count} users processed\n`);
|
||||||
return exiting(0);
|
return exiting(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function exiting (code, msg) {
|
function exiting (code, msg) {
|
||||||
code = code || 0; // 0 = success
|
// 0 = success
|
||||||
|
code = code || 0; // eslint-disable-line no-param-reassign
|
||||||
if (code && !msg) {
|
if (code && !msg) {
|
||||||
msg = 'ERROR!';
|
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||||
}
|
}
|
||||||
if (msg) {
|
if (msg) {
|
||||||
if (code) {
|
if (code) {
|
||||||
console.error(msg);
|
console.error(msg);
|
||||||
} else {
|
} else {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,25 @@
|
|||||||
|
/* eslint-disable import/no-commonjs */
|
||||||
/* let migrationName = 'restore_profile_data.js'; */
|
/* let migrationName = 'restore_profile_data.js'; */
|
||||||
let authorName = 'ThehollidayInn'; // in case script author needs to know when their ...
|
const authorName = 'ThehollidayInn'; // in case script author needs to know when their ...
|
||||||
let authorUuid = ''; // ... own data is done
|
const authorUuid = ''; // ... own data is done
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if users have empty profile data in new database and update it with old database info
|
* Check if users have empty profile data in new database and update it with old database info
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let monk = require('monk');
|
const monk = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||||
let connectionString = ''; // FOR TEST DATABASE
|
|
||||||
let dbUsers = monk(connectionString).get('users', { castIds: false });
|
|
||||||
|
|
||||||
let monk2 = require('monk');
|
const connectionString = ''; // FOR TEST DATABASE
|
||||||
let oldDbConnectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
const dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||||
let olDbUsers = monk2(oldDbConnectionString).get('users', { castIds: false });
|
|
||||||
|
const monk2 = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||||
|
|
||||||
|
const oldDbConnectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
|
const olDbUsers = monk2(oldDbConnectionString).get('users', { castIds: false });
|
||||||
|
|
||||||
function processUsers (lastId) {
|
function processUsers (lastId) {
|
||||||
// specify a query to limit the affected users (empty for all users):
|
// specify a query to limit the affected users (empty for all users):
|
||||||
let query = {
|
const query = {
|
||||||
// 'profile.name': 'profile name not found',
|
// 'profile.name': 'profile name not found',
|
||||||
'profile.blurb': null,
|
'profile.blurb': null,
|
||||||
// 'auth.timestamps.loggedin': {$gt: new Date('11/30/2016')},
|
// 'auth.timestamps.loggedin': {$gt: new Date('11/30/2016')},
|
||||||
@@ -29,49 +32,47 @@ function processUsers (lastId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbUsers.find(query, {
|
dbUsers.find(query, {
|
||||||
sort: {_id: 1},
|
sort: { _id: 1 },
|
||||||
limit: 250,
|
limit: 250,
|
||||||
fields: ['_id', 'profile', 'auth.timestamps.loggedin'], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
fields: ['_id', 'profile', 'auth.timestamps.loggedin'], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||||
})
|
})
|
||||||
.then(updateUsers)
|
.then(updateUsers)
|
||||||
.catch((err) => {
|
.catch(err => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
return exiting(1, `ERROR! ${ err}`);
|
return exiting(1, `ERROR! ${err}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let progressCount = 1000;
|
const progressCount = 1000;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
function updateUsers (users) {
|
function updateUsers (users) {
|
||||||
if (!users || users.length === 0) {
|
if (!users || users.length === 0) {
|
||||||
console.warn('All appropriate users found and modified.');
|
console.warn('All appropriate users found and modified.');
|
||||||
setTimeout(displayData, 300000);
|
setTimeout(displayData, 300000);
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let userPaymentPromises = users.map(updateUser);
|
const userPaymentPromises = users.map(updateUser);
|
||||||
let lastUser = users[users.length - 1];
|
const lastUser = users[users.length - 1];
|
||||||
|
|
||||||
return Promise.all(userPaymentPromises)
|
return Promise.all(userPaymentPromises)
|
||||||
.then(() => {
|
.then(() => processUsers(lastUser._id));
|
||||||
return processUsers(lastUser._id);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateUser (user) {
|
function updateUser (user) {
|
||||||
count++;
|
count += 1;
|
||||||
|
|
||||||
if (!user.profile.name || user.profile.name === 'profile name not found' || !user.profile.imageUrl || !user.profile.blurb) {
|
if (!user.profile.name || user.profile.name === 'profile name not found' || !user.profile.imageUrl || !user.profile.blurb) {
|
||||||
return olDbUsers.findOne({_id: user._id}, '_id profile')
|
return olDbUsers.findOne({ _id: user._id }, '_id profile')
|
||||||
.then((oldUserData) => {
|
.then(oldUserData => {
|
||||||
if (!oldUserData) return;
|
if (!oldUserData) return null;
|
||||||
// specify user data to change:
|
// specify user data to change:
|
||||||
let set = {};
|
const set = {};
|
||||||
|
|
||||||
if (oldUserData.profile.name === 'profile name not found') return;
|
if (oldUserData.profile.name === 'profile name not found') return null;
|
||||||
|
|
||||||
let userNeedsProfileName = !user.profile.name || user.profile.name === 'profile name not found';
|
const userNeedsProfileName = !user.profile.name || user.profile.name === 'profile name not found';
|
||||||
if (userNeedsProfileName && oldUserData.profile.name) {
|
if (userNeedsProfileName && oldUserData.profile.name) {
|
||||||
set['profile.name'] = oldUserData.profile.name;
|
set['profile.name'] = oldUserData.profile.name;
|
||||||
}
|
}
|
||||||
@@ -86,29 +87,34 @@ function updateUser (user) {
|
|||||||
|
|
||||||
if (Object.keys(set).length !== 0 && set.constructor === Object) {
|
if (Object.keys(set).length !== 0 && set.constructor === Object) {
|
||||||
console.log(set);
|
console.log(set);
|
||||||
return dbUsers.update({_id: user._id}, {$set: set});
|
return dbUsers.update({ _id: user._id }, { $set: set });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count } ${ user._id}`);
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
if (user._id === authorUuid) console.warn(`${authorName } processed`);
|
if (user._id === authorUuid) console.warn(`${authorName} processed`);
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayData () {
|
function displayData () {
|
||||||
console.warn(`\n${ count } users processed\n`);
|
console.warn(`\n${count} users processed\n`);
|
||||||
return exiting(0);
|
return exiting(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function exiting (code, msg) {
|
function exiting (code, msg) {
|
||||||
code = code || 0; // 0 = success
|
// 0 = success
|
||||||
|
code = code || 0; // eslint-disable-line no-param-reassign
|
||||||
if (code && !msg) {
|
if (code && !msg) {
|
||||||
msg = 'ERROR!';
|
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||||
}
|
}
|
||||||
if (msg) {
|
if (msg) {
|
||||||
if (code) {
|
if (code) {
|
||||||
console.error(msg);
|
console.error(msg);
|
||||||
} else {
|
} else {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
let request = require('superagent');
|
/* eslint-disable import/no-commonjs */
|
||||||
let last = require('lodash/last');
|
const request = require('superagent');
|
||||||
let AWS = require('aws-sdk');
|
const last = require('lodash/last');
|
||||||
|
const AWS = require('aws-sdk');
|
||||||
|
|
||||||
|
const config = require('../config');
|
||||||
|
|
||||||
let config = require('../config');
|
|
||||||
const S3_DIRECTORY = 'mobileApp/images'; // config.S3.SPRITES_DIRECTORY;
|
const S3_DIRECTORY = 'mobileApp/images'; // config.S3.SPRITES_DIRECTORY;
|
||||||
|
|
||||||
AWS.config.update({
|
AWS.config.update({
|
||||||
@@ -11,8 +13,8 @@ AWS.config.update({
|
|||||||
// region: config.get('S3_REGION'),
|
// region: config.get('S3_REGION'),
|
||||||
});
|
});
|
||||||
|
|
||||||
let BUCKET_NAME = config.S3.bucket;
|
const BUCKET_NAME = config.S3.bucket;
|
||||||
let s3 = new AWS.S3();
|
const s3 = new AWS.S3();
|
||||||
|
|
||||||
// Adapted from http://stackoverflow.com/a/22210077/2601552
|
// Adapted from http://stackoverflow.com/a/22210077/2601552
|
||||||
function uploadFile (buffer, fileName) {
|
function uploadFile (buffer, fileName) {
|
||||||
@@ -21,7 +23,7 @@ function uploadFile (buffer, fileName) {
|
|||||||
Body: buffer,
|
Body: buffer,
|
||||||
Key: fileName,
|
Key: fileName,
|
||||||
Bucket: BUCKET_NAME,
|
Bucket: BUCKET_NAME,
|
||||||
}, (error) => {
|
}, error => {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
@@ -33,9 +35,9 @@ function uploadFile (buffer, fileName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getFileName (file) {
|
function getFileName (file) {
|
||||||
let piecesOfPath = file.split('/');
|
const piecesOfPath = file.split('/');
|
||||||
let name = last(piecesOfPath);
|
const name = last(piecesOfPath);
|
||||||
let fullName = S3_DIRECTORY + name;
|
const fullName = S3_DIRECTORY + name;
|
||||||
|
|
||||||
return fullName;
|
return fullName;
|
||||||
}
|
}
|
||||||
@@ -44,36 +46,32 @@ function getFileFromUrl (url) {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
request.get(url).end((err, res) => {
|
request.get(url).end((err, res) => {
|
||||||
if (err) return reject(err);
|
if (err) return reject(err);
|
||||||
let file = res.body;
|
const file = res.body;
|
||||||
resolve(file);
|
return resolve(file);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let commit = '78f94e365c72cc58f66857d5941105638db7d35c';
|
let commit = '78f94e365c72cc58f66857d5941105638db7d35c';
|
||||||
commit = 'df0dbaba636c9ce424cc7040f7bd7fc1aa311015';
|
commit = 'df0dbaba636c9ce424cc7040f7bd7fc1aa311015';
|
||||||
let gihuburl = `https://api.github.com/repos/HabitRPG/habitica/commits/${commit}`;
|
const gihuburl = `https://api.github.com/repos/HabitRPG/habitica/commits/${commit}`;
|
||||||
|
|
||||||
|
|
||||||
let currentIndex = 0;
|
let currentIndex = 0;
|
||||||
|
|
||||||
function uploadToS3 (start, end, filesUrls) {
|
function uploadToS3 (start, end, filesUrls) {
|
||||||
let urls = filesUrls.slice(start, end);
|
const urls = filesUrls.slice(start, end);
|
||||||
|
|
||||||
if (urls.length === 0) {
|
if (urls.length === 0) {
|
||||||
console.log('done');
|
console.log('done');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let promises = urls.map(fullUrl => {
|
const promises = urls.map(fullUrl => getFileFromUrl(fullUrl)
|
||||||
return getFileFromUrl(fullUrl)
|
.then(buffer => uploadFile(buffer, getFileName(fullUrl))));
|
||||||
.then((buffer) => {
|
|
||||||
return uploadFile(buffer, getFileName(fullUrl));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
console.log(promises.length);
|
console.log(promises.length);
|
||||||
|
|
||||||
return Promise.all(promises)
|
Promise.all(promises)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
currentIndex += 50;
|
currentIndex += 50;
|
||||||
uploadToS3(currentIndex, currentIndex + 50, filesUrls);
|
uploadToS3(currentIndex, currentIndex + 50, filesUrls);
|
||||||
@@ -86,12 +84,10 @@ function uploadToS3 (start, end, filesUrls) {
|
|||||||
request.get(gihuburl)
|
request.get(gihuburl)
|
||||||
.end((err, res) => {
|
.end((err, res) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
let files = res.body.files;
|
const { files } = res.body;
|
||||||
|
|
||||||
let filesUrls = [''];
|
let filesUrls = [''];
|
||||||
filesUrls = files.map(file => {
|
filesUrls = files.map(file => file.raw_url);
|
||||||
return file.raw_url;
|
|
||||||
});
|
|
||||||
|
|
||||||
uploadToS3(currentIndex, currentIndex + 50, filesUrls);
|
uploadToS3(currentIndex, currentIndex + 50, filesUrls);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
|
/* eslint-disable import/no-commonjs */
|
||||||
// const migrationName = 'habits-one-history-entry-per-day';
|
// const migrationName = 'habits-one-history-entry-per-day';
|
||||||
// const authorName = 'paglias'; // in case script author needs to know when their ...
|
// const authorName = 'paglias'; // in case script author needs to know when their ...
|
||||||
// const authorUuid = 'ed4c688c-6652-4a92-9d03-a5a79844174a'; // ... own data is done
|
// 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
|
* Iterates over all habits and condense multiple history entries for the same day into a single one
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const monk = require('monk');
|
const monk = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
|
|
||||||
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
const dbTasks = monk(connectionString).get('tasks', { castIds: false });
|
const dbTasks = monk(connectionString).get('tasks', { castIds: false });
|
||||||
|
|
||||||
function processChallengeHabits (lastId) {
|
function processChallengeHabits (lastId) {
|
||||||
let query = {
|
const query = {
|
||||||
'challenge.id': {$exists: true},
|
'challenge.id': { $exists: true },
|
||||||
userId: {$exists: false},
|
userId: { $exists: false },
|
||||||
type: 'habit',
|
type: 'habit',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -26,37 +28,35 @@ function processChallengeHabits (lastId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbTasks.find(query, {
|
dbTasks.find(query, {
|
||||||
sort: {_id: 1},
|
sort: { _id: 1 },
|
||||||
limit: 500,
|
limit: 500,
|
||||||
})
|
})
|
||||||
.then(updateChallengeHabits)
|
.then(updateChallengeHabits)
|
||||||
.catch((err) => {
|
.catch(err => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
return exiting(1, `ERROR! ${ err}`);
|
return exiting(1, `ERROR! ${err}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let progressCount = 1000;
|
const progressCount = 1000;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
function updateChallengeHabits (habits) {
|
function updateChallengeHabits (habits) {
|
||||||
if (!habits || habits.length === 0) {
|
if (!habits || habits.length === 0) {
|
||||||
console.warn('All appropriate challenge habits found and modified.');
|
console.warn('All appropriate challenge habits found and modified.');
|
||||||
displayData();
|
displayData();
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let habitsPromises = habits.map(updateChallengeHabit);
|
const habitsPromises = habits.map(updateChallengeHabit);
|
||||||
let lastHabit = habits[habits.length - 1];
|
const lastHabit = habits[habits.length - 1];
|
||||||
|
|
||||||
return Promise.all(habitsPromises)
|
return Promise.all(habitsPromises)
|
||||||
.then(() => {
|
.then(() => processChallengeHabits(lastHabit._id));
|
||||||
return processChallengeHabits(lastHabit._id);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateChallengeHabit (habit) {
|
function updateChallengeHabit (habit) {
|
||||||
count++;
|
count += 1;
|
||||||
|
|
||||||
if (habit && habit.history && habit.history.length > 0) {
|
if (habit && habit.history && habit.history.length > 0) {
|
||||||
// First remove missing entries
|
// First remove missing entries
|
||||||
@@ -76,13 +76,12 @@ function updateChallengeHabit (habit) {
|
|||||||
entry.scoreDirection = entry.value > previousValue ? 'up' : 'down';
|
entry.scoreDirection = entry.value > previousValue ? 'up' : 'down';
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.groupBy(entry => { // group entries by aggregateBy
|
// group entries by aggregateBy
|
||||||
return moment(entry.date).format('YYYYMMDD');
|
.groupBy(entry => moment(entry.date).format('YYYYMMDD'))
|
||||||
})
|
|
||||||
.toPairs() // [key, entry]
|
.toPairs() // [key, entry]
|
||||||
.sortBy(([key]) => key) // sort by date
|
.sortBy(([key]) => key) // sort by date
|
||||||
.map(keyEntryPair => {
|
.map(keyEntryPair => {
|
||||||
let entries = keyEntryPair[1]; // 1 is entry, 0 is key
|
const entries = keyEntryPair[1]; // 1 is entry, 0 is key
|
||||||
let scoredUp = 0;
|
let scoredUp = 0;
|
||||||
let scoredDown = 0;
|
let scoredDown = 0;
|
||||||
|
|
||||||
@@ -107,32 +106,34 @@ function updateChallengeHabit (habit) {
|
|||||||
})
|
})
|
||||||
.value();
|
.value();
|
||||||
|
|
||||||
return dbTasks.update({_id: habit._id}, {
|
return dbTasks.update({ _id: habit._id }, {
|
||||||
$set: {history: habit.history},
|
$set: { history: habit.history },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count } habits processed`);
|
if (count % progressCount === 0) console.warn(`${count} habits processed`);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayData () {
|
function displayData () {
|
||||||
console.warn(`\n${ count } tasks processed\n`);
|
console.warn(`\n${count} tasks processed\n`);
|
||||||
return exiting(0);
|
return exiting(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function exiting (code, msg) {
|
function exiting (code, msg) {
|
||||||
code = code || 0; // 0 = success
|
// 0 = success
|
||||||
|
code = code || 0; // eslint-disable-line no-param-reassign
|
||||||
if (code && !msg) {
|
if (code && !msg) {
|
||||||
msg = 'ERROR!';
|
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||||
}
|
}
|
||||||
if (msg) {
|
if (msg) {
|
||||||
if (code) {
|
if (code) {
|
||||||
console.error(msg);
|
console.error(msg);
|
||||||
} else {
|
} else {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
process.exit(code);
|
process.exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = processChallengeHabits;
|
export default processChallengeHabits;
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
|
/* eslint-disable import/no-commonjs */
|
||||||
const migrationName = 'habits-one-history-entry-per-day';
|
const migrationName = 'habits-one-history-entry-per-day';
|
||||||
const authorName = 'paglias'; // in case script author needs to know when their ...
|
const authorName = 'paglias'; // in case script author needs to know when their ...
|
||||||
const authorUuid = 'ed4c688c-6652-4a92-9d03-a5a79844174a'; // ... own data is done
|
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
|
* Iterates over all habits and condense multiple history entries for the same day into a single one
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const monk = require('monk');
|
const monk = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
|
|
||||||
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
const dbTasks = monk(connectionString).get('tasks', { castIds: false });
|
const dbTasks = monk(connectionString).get('tasks', { castIds: false });
|
||||||
const dbUsers = monk(connectionString).get('users', { castIds: false });
|
const dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||||
|
|
||||||
function processUsers (lastId) {
|
function processUsers (lastId) {
|
||||||
let query = {
|
const query = {
|
||||||
migration: {$ne: migrationName},
|
migration: { $ne: migrationName },
|
||||||
};
|
};
|
||||||
|
|
||||||
if (lastId) {
|
if (lastId) {
|
||||||
@@ -25,34 +27,32 @@ function processUsers (lastId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbUsers.find(query, {
|
dbUsers.find(query, {
|
||||||
sort: {_id: 1},
|
sort: { _id: 1 },
|
||||||
limit: 50, // just 50 users per time since we have to process all their habits as well
|
limit: 50, // just 50 users per time since we have to process all their habits as well
|
||||||
fields: ['_id', 'preferences.timezoneOffset', 'preferences.dayStart'],
|
fields: ['_id', 'preferences.timezoneOffset', 'preferences.dayStart'],
|
||||||
})
|
})
|
||||||
.then(updateUsers)
|
.then(updateUsers)
|
||||||
.catch((err) => {
|
.catch(err => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
return exiting(1, `ERROR! ${ err}`);
|
return exiting(1, `ERROR! ${err}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let progressCount = 1000;
|
const progressCount = 1000;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
function updateUsers (users) {
|
function updateUsers (users) {
|
||||||
if (!users || users.length === 0) {
|
if (!users || users.length === 0) {
|
||||||
console.warn('All appropriate users and their tasks found and modified.');
|
console.warn('All appropriate users and their tasks found and modified.');
|
||||||
displayData();
|
displayData();
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let usersPromises = users.map(updateUser);
|
const usersPromises = users.map(updateUser);
|
||||||
let lastUser = users[users.length - 1];
|
const lastUser = users[users.length - 1];
|
||||||
|
|
||||||
return Promise.all(usersPromises)
|
return Promise.all(usersPromises)
|
||||||
.then(() => {
|
.then(() => processUsers(lastUser._id));
|
||||||
return processUsers(lastUser._id);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateHabit (habit, timezoneOffset, dayStart) {
|
function updateHabit (habit, timezoneOffset, dayStart) {
|
||||||
@@ -82,7 +82,7 @@ function updateHabit (habit, timezoneOffset, dayStart) {
|
|||||||
.toPairs() // [key, entry]
|
.toPairs() // [key, entry]
|
||||||
.sortBy(([key]) => key) // sort by date
|
.sortBy(([key]) => key) // sort by date
|
||||||
.map(keyEntryPair => {
|
.map(keyEntryPair => {
|
||||||
let entries = keyEntryPair[1]; // 1 is entry, 0 is key
|
const entries = keyEntryPair[1]; // 1 is entry, 0 is key
|
||||||
let scoredUp = 0;
|
let scoredUp = 0;
|
||||||
let scoredDown = 0;
|
let scoredDown = 0;
|
||||||
|
|
||||||
@@ -107,57 +107,56 @@ function updateHabit (habit, timezoneOffset, dayStart) {
|
|||||||
})
|
})
|
||||||
.value();
|
.value();
|
||||||
|
|
||||||
return dbTasks.update({_id: habit._id}, {
|
return dbTasks.update({ _id: habit._id }, {
|
||||||
$set: {history: habit.history},
|
$set: { history: habit.history },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateUser (user) {
|
function updateUser (user) {
|
||||||
count++;
|
count += 1;
|
||||||
|
|
||||||
const timezoneOffset = user.preferences.timezoneOffset;
|
const { timezoneOffset } = user.preferences;
|
||||||
const dayStart = user.preferences.dayStart;
|
const { dayStart } = user.preferences;
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count } ${ user._id}`);
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
if (user._id === authorUuid) console.warn(`${authorName } being processed`);
|
if (user._id === authorUuid) console.warn(`${authorName} being processed`);
|
||||||
|
|
||||||
return dbTasks.find({
|
return dbTasks.find({
|
||||||
type: 'habit',
|
type: 'habit',
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
})
|
})
|
||||||
.then(habits => {
|
.then(habits => Promise.all(habits.map(habit => updateHabit(habit, timezoneOffset, dayStart))))
|
||||||
return Promise.all(habits.map(habit => updateHabit(habit, timezoneOffset, dayStart)));
|
.then(() => dbUsers.update({ _id: user._id }, {
|
||||||
})
|
$set: { migration: migrationName },
|
||||||
.then(() => {
|
}))
|
||||||
return dbUsers.update({_id: user._id}, {
|
.catch(err => {
|
||||||
$set: {migration: migrationName},
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err);
|
console.log(err);
|
||||||
return exiting(1, `ERROR! ${ err}`);
|
return exiting(1, `ERROR! ${err}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayData () {
|
function displayData () {
|
||||||
console.warn(`\n${ count } tasks processed\n`);
|
console.warn(`\n${count} tasks processed\n`);
|
||||||
return exiting(0);
|
return exiting(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function exiting (code, msg) {
|
function exiting (code, msg) {
|
||||||
code = code || 0; // 0 = success
|
// 0 = success
|
||||||
|
code = code || 0; // eslint-disable-line no-param-reassign
|
||||||
if (code && !msg) {
|
if (code && !msg) {
|
||||||
msg = 'ERROR!';
|
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||||
}
|
}
|
||||||
if (msg) {
|
if (msg) {
|
||||||
if (code) {
|
if (code) {
|
||||||
console.error(msg);
|
console.error(msg);
|
||||||
} else {
|
} else {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
process.exit(code);
|
process.exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = processUsers;
|
export default processUsers;
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
|
import monk from 'monk'; // eslint-disable-line import/no-extraneous-dependencies
|
||||||
/* let migrationName = 'tasks-set-everyX'; */
|
/* let migrationName = 'tasks-set-everyX'; */
|
||||||
let authorName = 'Sabe'; // in case script author needs to know when their ...
|
const authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||||
let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
const authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterates over all tasks and sets invalid everyX values (less than 0 or more than 9999 or not an int) field to 0
|
* Iterates over all tasks and sets invalid everyX values
|
||||||
|
* (less than 0 or more than 9999 or not an int) field to 0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let monk = require('monk');
|
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true';
|
||||||
let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true';
|
const dbTasks = monk(connectionString).get('tasks', { castIds: false });
|
||||||
let dbTasks = monk(connectionString).get('tasks', { castIds: false });
|
|
||||||
|
|
||||||
function processTasks (lastId) {
|
function processTasks (lastId) {
|
||||||
// specify a query to limit the affected tasks (empty for all tasks):
|
// specify a query to limit the affected tasks (empty for all tasks):
|
||||||
let query = {
|
const query = {
|
||||||
type: 'daily',
|
type: 'daily',
|
||||||
everyX: {
|
everyX: {
|
||||||
$not: {
|
$not: {
|
||||||
@@ -30,64 +31,63 @@ function processTasks (lastId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbTasks.find(query, {
|
dbTasks.find(query, {
|
||||||
sort: {_id: 1},
|
sort: { _id: 1 },
|
||||||
limit: 250,
|
limit: 250,
|
||||||
fields: [],
|
fields: [],
|
||||||
})
|
})
|
||||||
.then(updateTasks)
|
.then(updateTasks)
|
||||||
.catch((err) => {
|
.catch(err => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
return exiting(1, `ERROR! ${ err}`);
|
return exiting(1, `ERROR! ${err}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let progressCount = 1000;
|
const progressCount = 1000;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
function updateTasks (tasks) {
|
function updateTasks (tasks) {
|
||||||
if (!tasks || tasks.length === 0) {
|
if (!tasks || tasks.length === 0) {
|
||||||
console.warn('All appropriate tasks found and modified.');
|
console.warn('All appropriate tasks found and modified.');
|
||||||
displayData();
|
displayData();
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let taskPromises = tasks.map(updatetask);
|
const taskPromises = tasks.map(updatetask);
|
||||||
let lasttask = tasks[tasks.length - 1];
|
const lasttask = tasks[tasks.length - 1];
|
||||||
|
|
||||||
return Promise.all(taskPromises)
|
return Promise.all(taskPromises)
|
||||||
.then(() => {
|
.then(() => processTasks(lasttask._id));
|
||||||
return processTasks(lasttask._id);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updatetask (task) {
|
function updatetask (task) {
|
||||||
count++;
|
count += 1;
|
||||||
let set = {everyX: 0};
|
const set = { everyX: 0 };
|
||||||
|
|
||||||
dbTasks.update({_id: task._id}, {$set: set});
|
dbTasks.update({ _id: task._id }, { $set: set });
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count } ${ task._id}`);
|
if (count % progressCount === 0) console.warn(`${count} ${task._id}`);
|
||||||
if (task._id === authorUuid) console.warn(`${authorName } processed`);
|
if (task._id === authorUuid) console.warn(`${authorName} processed`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayData () {
|
function displayData () {
|
||||||
console.warn(`\n${ count } tasks processed\n`);
|
console.warn(`\n${count} tasks processed\n`);
|
||||||
return exiting(0);
|
return exiting(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function exiting (code, msg) {
|
function exiting (code, msg) {
|
||||||
code = code || 0; // 0 = success
|
// 0 = success
|
||||||
|
code = code || 0; // eslint-disable-line no-param-reassign
|
||||||
if (code && !msg) {
|
if (code && !msg) {
|
||||||
msg = 'ERROR!';
|
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||||
}
|
}
|
||||||
if (msg) {
|
if (msg) {
|
||||||
if (code) {
|
if (code) {
|
||||||
console.error(msg);
|
console.error(msg);
|
||||||
} else {
|
} else {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
process.exit(code);
|
process.exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = processTasks;
|
export default processTasks;
|
||||||
|
|||||||
@@ -1,28 +1,31 @@
|
|||||||
/* let migrationName = 'tasks-set-yesterdaily'; */
|
/* let migrationName = 'tasks-set-yesterdaily'; */
|
||||||
let authorName = 'TheHollidayInn'; // in case script author needs to know when their ...
|
// ... own data is done
|
||||||
let authorUuid = ''; // ... own data is done
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterates over all tasks and sets the yseterDaily field to True
|
* Iterates over all tasks and sets the yseterDaily field to True
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import monk from 'monk';
|
import monk from 'monk'; // eslint-disable-line import/no-extraneous-dependencies
|
||||||
|
|
||||||
let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
const authorName = 'TheHollidayInn'; // in case script author needs to know when their ...
|
||||||
let dbTasks = monk(connectionString).get('tasks', { castIds: false });
|
const authorUuid = '';
|
||||||
|
|
||||||
let progressCount = 1000;
|
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
|
const dbTasks = monk(connectionString).get('tasks', { castIds: false });
|
||||||
|
|
||||||
|
const progressCount = 1000;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
function exiting (code, msg) {
|
function exiting (code, msg) {
|
||||||
code = code || 0; // 0 = success
|
// 0 = success
|
||||||
|
code = code || 0; // eslint-disable-line no-param-reassign
|
||||||
if (code && !msg) {
|
if (code && !msg) {
|
||||||
msg = 'ERROR!';
|
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||||
}
|
}
|
||||||
if (msg) {
|
if (msg) {
|
||||||
if (code) {
|
if (code) {
|
||||||
console.error(msg);
|
console.error(msg);
|
||||||
} else {
|
} else {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,39 +33,37 @@ function exiting (code, msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function displayData () {
|
function displayData () {
|
||||||
console.warn(`\n${ count } tasks processed\n`);
|
console.warn(`\n${count} tasks processed\n`);
|
||||||
return exiting(0);
|
return exiting(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updatetask (task) {
|
function updatetask (task) {
|
||||||
count++;
|
count += 1;
|
||||||
let set = {yesterDaily: true};
|
const set = { yesterDaily: true };
|
||||||
|
|
||||||
dbTasks.update({_id: task._id}, {$set: set});
|
dbTasks.update({ _id: task._id }, { $set: set });
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count } ${ task._id}`);
|
if (count % progressCount === 0) console.warn(`${count} ${task._id}`);
|
||||||
if (task._id === authorUuid) console.warn(`${authorName } processed`);
|
if (task._id === authorUuid) console.warn(`${authorName} processed`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTasks (tasks) {
|
function updateTasks (tasks) {
|
||||||
if (!tasks || tasks.length === 0) {
|
if (!tasks || tasks.length === 0) {
|
||||||
console.warn('All appropriate tasks found and modified.');
|
console.warn('All appropriate tasks found and modified.');
|
||||||
displayData();
|
displayData();
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let taskPromises = tasks.map(updatetask);
|
const taskPromises = tasks.map(updatetask);
|
||||||
let lasttask = tasks[tasks.length - 1];
|
const lasttask = tasks[tasks.length - 1];
|
||||||
|
|
||||||
return Promise.all(taskPromises)
|
return Promise.all(taskPromises)
|
||||||
.then(() => {
|
.then(() => processTasks(lasttask._id)); // eslint-disable-line no-use-before-define
|
||||||
return processTasks(lasttask._id); // eslint-disable-line no-use-before-define
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function processTasks (lastId) {
|
function processTasks (lastId) {
|
||||||
// specify a query to limit the affected tasks (empty for all tasks):
|
// specify a query to limit the affected tasks (empty for all tasks):
|
||||||
let query = {
|
const query = {
|
||||||
yesterDaily: false,
|
yesterDaily: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -73,16 +74,18 @@ function processTasks (lastId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbTasks.find(query, {
|
dbTasks.find(query, {
|
||||||
sort: {_id: 1},
|
sort: { _id: 1 },
|
||||||
limit: 250,
|
limit: 250,
|
||||||
fields: [ // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
// specify fields we are interested in to limit retrieved data
|
||||||
|
// (empty if we're not reading data):
|
||||||
|
fields: [
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
.then(updateTasks)
|
.then(updateTasks)
|
||||||
.catch((err) => {
|
.catch(err => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
return exiting(1, `ERROR! ${ err}`);
|
return exiting(1, `ERROR! ${err}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = processTasks;
|
export default processTasks;
|
||||||
|
|||||||
@@ -8,29 +8,30 @@ let authorUuid = ''; // ... own data is done
|
|||||||
* This migraition will copy user data from prod to test
|
* This migraition will copy user data from prod to test
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const monk = require('monk');
|
import monk from 'monk'; // eslint-disable-line import/no-extraneous-dependencies
|
||||||
|
|
||||||
const connectionString = '';
|
const connectionString = '';
|
||||||
const Users = monk(connectionString).get('users', { castIds: false });
|
const Users = monk(connectionString).get('users', { castIds: false });
|
||||||
|
|
||||||
module.exports = async function accountTransfer () {
|
export default async function accountTransfer () {
|
||||||
const fromAccountId = '';
|
const fromAccountId = '';
|
||||||
const toAccountId = '';
|
const toAccountId = '';
|
||||||
|
|
||||||
const fromAccount = await Users.findOne({_id: fromAccountId});
|
const fromAccount = await Users.findOne({ _id: fromAccountId });
|
||||||
const toAccount = await Users.findOne({_id: toAccountId});
|
const toAccount = await Users.findOne({ _id: toAccountId });
|
||||||
|
|
||||||
const newMounts = Object.assign({}, fromAccount.items.mounts, toAccount.items.mounts);
|
const newMounts = { ...fromAccount.items.mounts, ...toAccount.items.mounts };
|
||||||
const newPets = Object.assign({}, fromAccount.items.pets, toAccount.items.pets);
|
const newPets = { ...fromAccount.items.pets, ...toAccount.items.pets };
|
||||||
const newBackgrounds = Object.assign({}, fromAccount.purchased.background, toAccount.purchased.background);
|
const newBackgrounds = { ...fromAccount.purchased.background, ...toAccount.purchased.background };
|
||||||
|
|
||||||
await Users.update({_id: toAccountId}, {
|
await Users.update({ _id: toAccountId }, {
|
||||||
$set: {
|
$set: {
|
||||||
'items.pets': newPets,
|
'items.pets': newPets,
|
||||||
'items.mounts': newMounts,
|
'items.mounts': newMounts,
|
||||||
'purchased.background': newBackgrounds,
|
'purchased.background': newBackgrounds,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then(result => {
|
||||||
console.log(result);
|
console.log(result);
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ const authorUuid = ''; // ... own data is done
|
|||||||
* This migraition will copy user data from prod to test
|
* This migraition will copy user data from prod to test
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const monk = require('monk');
|
import monk from 'monk'; // eslint-disable-line import/no-extraneous-dependencies
|
||||||
|
|
||||||
const connectionString = 'mongodb://localhost/new-habit';
|
const connectionString = 'mongodb://localhost/new-habit';
|
||||||
const Users = monk(connectionString).get('users', { castIds: false });
|
const Users = monk(connectionString).get('users', { castIds: false });
|
||||||
|
|
||||||
@@ -19,15 +20,17 @@ function getAchievementUpdate (newUser, oldUser) {
|
|||||||
const oldAchievements = oldUser.achievements;
|
const oldAchievements = oldUser.achievements;
|
||||||
const newAchievements = newUser.achievements;
|
const newAchievements = newUser.achievements;
|
||||||
|
|
||||||
let achievementsUpdate = Object.assign({}, newAchievements);
|
const achievementsUpdate = { ...newAchievements };
|
||||||
|
|
||||||
// ultimateGearSets
|
// ultimateGearSets
|
||||||
if (!achievementsUpdate.ultimateGearSets && oldAchievements.ultimateGearSets) {
|
if (!achievementsUpdate.ultimateGearSets && oldAchievements.ultimateGearSets) {
|
||||||
achievementsUpdate.ultimateGearSets = oldAchievements.ultimateGearSets;
|
achievementsUpdate.ultimateGearSets = oldAchievements.ultimateGearSets;
|
||||||
} else if (oldAchievements.ultimateGearSets) {
|
} else if (oldAchievements.ultimateGearSets) {
|
||||||
for (let index in oldAchievements.ultimateGearSets) {
|
Object.keys(oldAchievements.ultimateGearSets).forEach(index => {
|
||||||
if (oldAchievements.ultimateGearSets[index]) achievementsUpdate.ultimateGearSets[index] = true;
|
if (oldAchievements.ultimateGearSets[index]) {
|
||||||
}
|
achievementsUpdate.ultimateGearSets[index] = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// challenges
|
// challenges
|
||||||
@@ -37,57 +40,57 @@ function getAchievementUpdate (newUser, oldUser) {
|
|||||||
|
|
||||||
// Quests
|
// Quests
|
||||||
if (!achievementsUpdate.quests) achievementsUpdate.quests = {};
|
if (!achievementsUpdate.quests) achievementsUpdate.quests = {};
|
||||||
for (let index in oldAchievements.quests) {
|
Object.keys(oldAchievements.quests).forEach(index => {
|
||||||
if (!achievementsUpdate.quests[index]) {
|
if (!achievementsUpdate.quests[index]) {
|
||||||
achievementsUpdate.quests[index] = oldAchievements.quests[index];
|
achievementsUpdate.quests[index] = oldAchievements.quests[index];
|
||||||
} else {
|
} else {
|
||||||
achievementsUpdate.quests[index] += oldAchievements.quests[index];
|
achievementsUpdate.quests[index] += oldAchievements.quests[index];
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
// Rebirth level
|
// Rebirth level
|
||||||
if (achievementsUpdate.rebirthLevel) {
|
if (achievementsUpdate.rebirthLevel) {
|
||||||
achievementsUpdate.rebirthLevel = Math.max(achievementsUpdate.rebirthLevel, oldAchievements.rebirthLevel);
|
achievementsUpdate.rebirthLevel = Math.max(
|
||||||
|
achievementsUpdate.rebirthLevel, oldAchievements.rebirthLevel,
|
||||||
|
);
|
||||||
} else if (oldAchievements.rebirthLevel) {
|
} else if (oldAchievements.rebirthLevel) {
|
||||||
achievementsUpdate.rebirthLevel = oldAchievements.rebirthLevel;
|
achievementsUpdate.rebirthLevel = oldAchievements.rebirthLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// All others
|
// All others
|
||||||
const indexsToIgnore = ['ultimateGearSets', 'challenges', 'quests', 'rebirthLevel'];
|
const indexsToIgnore = ['ultimateGearSets', 'challenges', 'quests', 'rebirthLevel'];
|
||||||
for (let index in oldAchievements) {
|
Object.keys(oldAchievements).forEach(index => {
|
||||||
if (indexsToIgnore.indexOf(index) !== -1) continue; // eslint-disable-line no-continue
|
if (indexsToIgnore.indexOf(index) !== -1) return;
|
||||||
|
|
||||||
if (!achievementsUpdate[index]) {
|
if (!achievementsUpdate[index]) {
|
||||||
achievementsUpdate[index] = oldAchievements[index];
|
achievementsUpdate[index] = oldAchievements[index];
|
||||||
continue; // eslint-disable-line no-continue
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Number.isInteger(oldAchievements[index])) {
|
if (Number.isInteger(oldAchievements[index])) {
|
||||||
achievementsUpdate[index] += oldAchievements[index];
|
achievementsUpdate[index] += oldAchievements[index];
|
||||||
} else if (oldAchievements[index] === true) achievementsUpdate[index] = true;
|
} else if (oldAchievements[index] === true) achievementsUpdate[index] = true;
|
||||||
}
|
});
|
||||||
|
|
||||||
return achievementsUpdate;
|
return achievementsUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = async function achievementRestore () {
|
export default async function achievementRestore () {
|
||||||
const userIds = [
|
const userIds = [
|
||||||
];
|
];
|
||||||
|
|
||||||
/* eslint-disable no-await-in-loop */
|
await Promise.all(userIds.map(userId => (async () => {
|
||||||
for (let index in userIds) {
|
const oldUser = await UsersOld.findOne({ _id: userId }, 'achievements');
|
||||||
const userId = userIds[index];
|
const newUser = await Users.findOne({ _id: userId }, 'achievements');
|
||||||
const oldUser = await UsersOld.findOne({_id: userId}, 'achievements');
|
|
||||||
const newUser = await Users.findOne({_id: userId}, 'achievements');
|
|
||||||
const achievementUpdate = getAchievementUpdate(newUser, oldUser);
|
const achievementUpdate = getAchievementUpdate(newUser, oldUser);
|
||||||
await Users.update(
|
await Users.update(
|
||||||
{_id: userId},
|
{ _id: userId },
|
||||||
{
|
{
|
||||||
$set: {
|
$set: {
|
||||||
achievements: achievementUpdate,
|
achievements: achievementUpdate,
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
|
);
|
||||||
console.log(`Updated ${userId}`);
|
console.log(`Updated ${userId}`);
|
||||||
/* eslint-enable no-await-in-loop */
|
})()));
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
import { sendTxn } from '../../website/server/libs/email';
|
|
||||||
import { model as User } from '../../website/server/models/user';
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import nconf from 'nconf';
|
import nconf from 'nconf';
|
||||||
|
import { sendTxn } from '../../website/server/libs/email';
|
||||||
|
import { model as User } from '../../website/server/models/user';
|
||||||
|
|
||||||
const BASE_URL = nconf.get('BASE_URL');
|
const BASE_URL = nconf.get('BASE_URL');
|
||||||
const EMAIL_SLUG = 'mandrill-email-slug'; // Set email template to send
|
const EMAIL_SLUG = 'mandrill-email-slug'; // Set email template to send
|
||||||
const MIGRATION_NAME = 'bulk-email';
|
const MIGRATION_NAME = 'bulk-email';
|
||||||
@@ -11,23 +12,23 @@ const progressCount = 1000;
|
|||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
async function updateUser (user) {
|
async function updateUser (user) {
|
||||||
count++;
|
count += 1;
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
|
||||||
sendTxn(
|
sendTxn(
|
||||||
user,
|
user,
|
||||||
EMAIL_SLUG,
|
EMAIL_SLUG,
|
||||||
[{name: 'BASE_URL', content: BASE_URL}] // Add variables from template
|
[{ name: 'BASE_URL', content: BASE_URL }], // Add variables from template
|
||||||
);
|
);
|
||||||
|
|
||||||
return await User.update({_id: user._id}, {$set: {migration: MIGRATION_NAME}}).exec();
|
return User.update({ _id: user._id }, { $set: { migration: MIGRATION_NAME } }).exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = async function processUsers () {
|
export default async function processUsers () {
|
||||||
let query = {
|
const query = {
|
||||||
migration: {$ne: MIGRATION_NAME},
|
migration: { $ne: MIGRATION_NAME },
|
||||||
'auth.timestamps.loggedin': {$gt: moment().subtract(2, 'weeks').toDate()}, // customize or remove to target different populations
|
'auth.timestamps.loggedin': { $gt: moment().subtract(2, 'weeks').toDate() }, // customize or remove to target different populations
|
||||||
};
|
};
|
||||||
|
|
||||||
const fields = {
|
const fields = {
|
||||||
@@ -41,7 +42,7 @@ module.exports = async function processUsers () {
|
|||||||
const users = await User // eslint-disable-line no-await-in-loop
|
const users = await User // eslint-disable-line no-await-in-loop
|
||||||
.find(query)
|
.find(query)
|
||||||
.limit(250)
|
.limit(250)
|
||||||
.sort({_id: 1})
|
.sort({ _id: 1 })
|
||||||
.select(fields)
|
.select(fields)
|
||||||
.lean()
|
.lean()
|
||||||
.exec();
|
.exec();
|
||||||
@@ -58,4 +59,4 @@ module.exports = async function processUsers () {
|
|||||||
|
|
||||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
const MIGRATION_NAME = 'full-stable';
|
|
||||||
import each from 'lodash/each';
|
import each from 'lodash/each';
|
||||||
import keys from 'lodash/keys';
|
import keys from 'lodash/keys';
|
||||||
import content from '../../website/common/script/content/index';
|
import content from '../../website/common/script/content/index';
|
||||||
|
|
||||||
import { model as User } from '../../website/server/models/user';
|
import { model as User } from '../../website/server/models/user';
|
||||||
|
|
||||||
|
const MIGRATION_NAME = 'full-stable';
|
||||||
|
|
||||||
const progressCount = 1000;
|
const progressCount = 1000;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
@@ -14,45 +15,45 @@ let count = 0;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
async function updateUser (user) {
|
async function updateUser (user) {
|
||||||
count++;
|
count += 1;
|
||||||
|
|
||||||
const set = {};
|
const set = {};
|
||||||
|
|
||||||
set.migration = MIGRATION_NAME;
|
set.migration = MIGRATION_NAME;
|
||||||
|
|
||||||
each(keys(content.pets), (pet) => {
|
each(keys(content.pets), pet => {
|
||||||
set[`items.pets.${pet}`] = 5;
|
set[`items.pets.${pet}`] = 5;
|
||||||
});
|
});
|
||||||
each(keys(content.premiumPets), (pet) => {
|
each(keys(content.premiumPets), pet => {
|
||||||
set[`items.pets.${pet}`] = 5;
|
set[`items.pets.${pet}`] = 5;
|
||||||
});
|
});
|
||||||
each(keys(content.questPets), (pet) => {
|
each(keys(content.questPets), pet => {
|
||||||
set[`items.pets.${pet}`] = 5;
|
set[`items.pets.${pet}`] = 5;
|
||||||
});
|
});
|
||||||
each(keys(content.specialPets), (pet) => {
|
each(keys(content.specialPets), pet => {
|
||||||
set[`items.pets.${pet}`] = 5;
|
set[`items.pets.${pet}`] = 5;
|
||||||
});
|
});
|
||||||
each(keys(content.mounts), (mount) => {
|
each(keys(content.mounts), mount => {
|
||||||
set[`items.mounts.${mount}`] = true;
|
set[`items.mounts.${mount}`] = true;
|
||||||
});
|
});
|
||||||
each(keys(content.premiumMounts), (mount) => {
|
each(keys(content.premiumMounts), mount => {
|
||||||
set[`items.mounts.${mount}`] = true;
|
set[`items.mounts.${mount}`] = true;
|
||||||
});
|
});
|
||||||
each(keys(content.questMounts), (mount) => {
|
each(keys(content.questMounts), mount => {
|
||||||
set[`items.mounts.${mount}`] = true;
|
set[`items.mounts.${mount}`] = true;
|
||||||
});
|
});
|
||||||
each(keys(content.specialMounts), (mount) => {
|
each(keys(content.specialMounts), mount => {
|
||||||
set[`items.mounts.${mount}`] = true;
|
set[`items.mounts.${mount}`] = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
|
||||||
return await User.update({_id: user._id}, {$set: set}).exec();
|
return User.update({ _id: user._id }, { $set: set }).exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = async function processUsers () {
|
export default async function processUsers () {
|
||||||
let query = {
|
const query = {
|
||||||
migration: {$ne: MIGRATION_NAME},
|
migration: { $ne: MIGRATION_NAME },
|
||||||
'auth.local.username': 'olson22',
|
'auth.local.username': 'olson22',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -64,7 +65,7 @@ module.exports = async function processUsers () {
|
|||||||
const users = await User // eslint-disable-line no-await-in-loop
|
const users = await User // eslint-disable-line no-await-in-loop
|
||||||
.find(query)
|
.find(query)
|
||||||
.limit(250)
|
.limit(250)
|
||||||
.sort({_id: 1})
|
.sort({ _id: 1 })
|
||||||
.select(fields)
|
.select(fields)
|
||||||
.lean()
|
.lean()
|
||||||
.exec();
|
.exec();
|
||||||
@@ -81,4 +82,4 @@ module.exports = async function processUsers () {
|
|||||||
|
|
||||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
const MIGRATION_NAME = 'mystery_items_201909';
|
|
||||||
const MYSTERY_ITEMS = ['armor_mystery_201909', 'head_mystery_201909'];
|
|
||||||
import { model as User } from '../../website/server/models/user';
|
import { model as User } from '../../website/server/models/user';
|
||||||
import { model as UserNotification } from '../../website/server/models/userNotification';
|
import { model as UserNotification } from '../../website/server/models/userNotification';
|
||||||
|
|
||||||
|
const MIGRATION_NAME = 'mystery_items_201910';
|
||||||
|
const MYSTERY_ITEMS = ['armor_mystery_201910', 'head_mystery_201910'];
|
||||||
|
|
||||||
const progressCount = 1000;
|
const progressCount = 1000;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
async function updateUser (user) {
|
async function updateUser (user) {
|
||||||
count++;
|
count += 1;
|
||||||
|
|
||||||
const addToSet = {
|
const addToSet = {
|
||||||
'purchased.plan.mysteryItems': {
|
'purchased.plan.mysteryItems': {
|
||||||
@@ -29,12 +30,12 @@ async function updateUser (user) {
|
|||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
|
||||||
return await User.update({_id: user._id}, {$set: set, $push: push, $addToSet: addToSet}).exec();
|
return User.update({ _id: user._id }, { $set: set, $push: push, $addToSet: addToSet }).exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = async function processUsers () {
|
export default async function processUsers () {
|
||||||
let query = {
|
const query = {
|
||||||
migration: {$ne: MIGRATION_NAME},
|
migration: { $ne: MIGRATION_NAME },
|
||||||
'purchased.plan.customerId': { $ne: null },
|
'purchased.plan.customerId': { $ne: null },
|
||||||
$or: [
|
$or: [
|
||||||
{ 'purchased.plan.dateTerminated': { $gte: new Date() } },
|
{ 'purchased.plan.dateTerminated': { $gte: new Date() } },
|
||||||
@@ -51,7 +52,7 @@ module.exports = async function processUsers () {
|
|||||||
const users = await User // eslint-disable-line no-await-in-loop
|
const users = await User // eslint-disable-line no-await-in-loop
|
||||||
.find(query)
|
.find(query)
|
||||||
.limit(250)
|
.limit(250)
|
||||||
.sort({_id: 1})
|
.sort({ _id: 1 })
|
||||||
.select(fields)
|
.select(fields)
|
||||||
.lean()
|
.lean()
|
||||||
.exec();
|
.exec();
|
||||||
@@ -68,4 +69,4 @@ module.exports = async function processUsers () {
|
|||||||
|
|
||||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
const MIGRATION_NAME = '20190314_pi_day';
|
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
import { model as User } from '../../website/server/models/user';
|
import { model as User } from '../../website/server/models/user';
|
||||||
|
|
||||||
|
const MIGRATION_NAME = '20190314_pi_day';
|
||||||
|
|
||||||
const progressCount = 1000;
|
const progressCount = 1000;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
async function updateUser (user) {
|
async function updateUser (user) {
|
||||||
count++;
|
count *= 1;
|
||||||
|
|
||||||
const inc = {
|
const inc = {
|
||||||
'items.food.Pie_Skeleton': 1,
|
'items.food.Pie_Skeleton': 1,
|
||||||
@@ -29,19 +30,21 @@ async function updateUser (user) {
|
|||||||
set['items.gear.owned.head_special_piDay'] = false;
|
set['items.gear.owned.head_special_piDay'] = false;
|
||||||
set['items.gear.owned.shield_special_piDay'] = false;
|
set['items.gear.owned.shield_special_piDay'] = false;
|
||||||
const push = [
|
const push = [
|
||||||
{type: 'marketGear', path: 'gear.flat.head_special_piDay', _id: uuid()},
|
{ type: 'marketGear', path: 'gear.flat.head_special_piDay', _id: uuid() },
|
||||||
{type: 'marketGear', path: 'gear.flat.shield_special_piDay', _id: uuid()},
|
{ type: 'marketGear', path: 'gear.flat.shield_special_piDay', _id: uuid() },
|
||||||
];
|
];
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
|
||||||
return await User.update({_id: user._id}, {$inc: inc, $set: set, $push: {pinnedItems: {$each: push}}}).exec();
|
return User
|
||||||
|
.update({ _id: user._id }, { $inc: inc, $set: set, $push: { pinnedItems: { $each: push } } })
|
||||||
|
.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = async function processUsers () {
|
export default async function processUsers () {
|
||||||
let query = {
|
const query = {
|
||||||
migration: {$ne: MIGRATION_NAME},
|
migration: { $ne: MIGRATION_NAME },
|
||||||
'auth.timestamps.loggedin': {$gt: new Date('2019-02-15')},
|
'auth.timestamps.loggedin': { $gt: new Date('2019-02-15') },
|
||||||
};
|
};
|
||||||
|
|
||||||
const fields = {
|
const fields = {
|
||||||
@@ -53,7 +56,7 @@ module.exports = async function processUsers () {
|
|||||||
const users = await User // eslint-disable-line no-await-in-loop
|
const users = await User // eslint-disable-line no-await-in-loop
|
||||||
.find(query)
|
.find(query)
|
||||||
.limit(250)
|
.limit(250)
|
||||||
.sort({_id: 1})
|
.sort({ _id: 1 })
|
||||||
.select(fields)
|
.select(fields)
|
||||||
.lean()
|
.lean()
|
||||||
.exec();
|
.exec();
|
||||||
@@ -70,4 +73,4 @@ module.exports = async function processUsers () {
|
|||||||
|
|
||||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import monk from 'monk'; // eslint-disable-line import/no-extraneous-dependencies
|
||||||
|
|
||||||
const migrationName = 'remove-social-users-extra-data.js';
|
const migrationName = 'remove-social-users-extra-data.js';
|
||||||
const authorName = 'paglias'; // in case script author needs to know when their ...
|
const authorName = 'paglias'; // in case script author needs to know when their ...
|
||||||
const authorUuid = 'ed4c688c-6652-4a92-9d03-a5a79844174a'; // ... own data is done
|
const authorUuid = 'ed4c688c-6652-4a92-9d03-a5a79844174a'; // ... own data is done
|
||||||
@@ -7,13 +9,13 @@ const authorUuid = 'ed4c688c-6652-4a92-9d03-a5a79844174a'; // ... own data is do
|
|||||||
*/
|
*/
|
||||||
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
|
|
||||||
const monk = require('monk');
|
|
||||||
const dbUsers = monk(connectionString).get('users', { castIds: false });
|
const dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||||
|
|
||||||
function processUsers (lastId) {
|
function processUsers (lastId) {
|
||||||
// specify a query to limit the affected users (empty for all users):
|
// specify a query to limit the affected users (empty for all users):
|
||||||
let query = {
|
const query = {
|
||||||
migration: {$ne: migrationName},
|
migration: { $ne: migrationName },
|
||||||
$or: [
|
$or: [
|
||||||
{ 'auth.facebook.id': { $exists: true } },
|
{ 'auth.facebook.id': { $exists: true } },
|
||||||
{ 'auth.google.id': { $exists: true } },
|
{ 'auth.google.id': { $exists: true } },
|
||||||
@@ -27,28 +29,28 @@ function processUsers (lastId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbUsers.find(query, {
|
dbUsers.find(query, {
|
||||||
sort: {_id: 1},
|
sort: { _id: 1 },
|
||||||
limit: 250,
|
limit: 250,
|
||||||
})
|
})
|
||||||
.then(updateUsers)
|
.then(updateUsers)
|
||||||
.catch((err) => {
|
.catch(err => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
return exiting(1, `ERROR! ${ err}`);
|
return exiting(1, `ERROR! ${err}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let progressCount = 1000;
|
const progressCount = 1000;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
function updateUsers (users) {
|
function updateUsers (users) {
|
||||||
if (!users || users.length === 0) {
|
if (!users || users.length === 0) {
|
||||||
console.warn('All appropriate users found and modified.');
|
console.warn('All appropriate users found and modified.');
|
||||||
displayData();
|
displayData();
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let userPromises = users.map(updateUser);
|
const userPromises = users.map(updateUser);
|
||||||
let lastUser = users[users.length - 1];
|
const lastUser = users[users.length - 1];
|
||||||
|
|
||||||
return Promise.all(userPromises)
|
return Promise.all(userPromises)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -57,7 +59,7 @@ function updateUsers (users) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateUser (user) {
|
function updateUser (user) {
|
||||||
count++;
|
count *= 1;
|
||||||
|
|
||||||
const isFacebook = user.auth.facebook && user.auth.facebook.id;
|
const isFacebook = user.auth.facebook && user.auth.facebook.id;
|
||||||
const isGoogle = user.auth.google && user.auth.google.id;
|
const isGoogle = user.auth.google && user.auth.google.id;
|
||||||
@@ -82,28 +84,29 @@ function updateUser (user) {
|
|||||||
_id: user._id,
|
_id: user._id,
|
||||||
}, update);
|
}, update);
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count } ${ user._id}`);
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
if (user._id === authorUuid) console.warn(`${authorName } processed`);
|
if (user._id === authorUuid) console.warn(`${authorName} processed`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayData () {
|
function displayData () {
|
||||||
console.warn(`\n${ count } users processed\n`);
|
console.warn(`\n${count} users processed\n`);
|
||||||
return exiting(0);
|
return exiting(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function exiting (code, msg) {
|
function exiting (code, msg) {
|
||||||
code = code || 0; // 0 = success
|
// 0 = success
|
||||||
|
code = code || 0; // eslint-disable-line no-param-reassign
|
||||||
if (code && !msg) {
|
if (code && !msg) {
|
||||||
msg = 'ERROR!';
|
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||||
}
|
}
|
||||||
if (msg) {
|
if (msg) {
|
||||||
if (code) {
|
if (code) {
|
||||||
console.error(msg);
|
console.error(msg);
|
||||||
} else {
|
} else {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
process.exit(code);
|
process.exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = processUsers;
|
export default processUsers;
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
const MIGRATION_NAME = '20181203_take_this';
|
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
import { model as User } from '../../website/server/models/user';
|
import { model as User } from '../../website/server/models/user';
|
||||||
|
|
||||||
|
const MIGRATION_NAME = '20181203_take_this';
|
||||||
|
|
||||||
const progressCount = 1000;
|
const progressCount = 1000;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
async function updateUser (user) {
|
async function updateUser (user) {
|
||||||
count++;
|
count += 1;
|
||||||
|
|
||||||
const set = {};
|
const set = {};
|
||||||
let push;
|
let push;
|
||||||
@@ -19,36 +20,35 @@ async function updateUser (user) {
|
|||||||
push = false;
|
push = false;
|
||||||
} else if (typeof user.items.gear.owned.body_special_takeThis !== 'undefined') {
|
} else if (typeof user.items.gear.owned.body_special_takeThis !== 'undefined') {
|
||||||
set['items.gear.owned.back_special_takeThis'] = false;
|
set['items.gear.owned.back_special_takeThis'] = false;
|
||||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.back_special_takeThis', _id: uuid()}};
|
push = { pinnedItems: { type: 'marketGear', path: 'gear.flat.back_special_takeThis', _id: uuid() } };
|
||||||
} else if (typeof user.items.gear.owned.head_special_takeThis !== 'undefined') {
|
} else if (typeof user.items.gear.owned.head_special_takeThis !== 'undefined') {
|
||||||
set['items.gear.owned.body_special_takeThis'] = false;
|
set['items.gear.owned.body_special_takeThis'] = false;
|
||||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.body_special_takeThis', _id: uuid()}};
|
push = { pinnedItems: { type: 'marketGear', path: 'gear.flat.body_special_takeThis', _id: uuid() } };
|
||||||
} else if (typeof user.items.gear.owned.armor_special_takeThis !== 'undefined') {
|
} else if (typeof user.items.gear.owned.armor_special_takeThis !== 'undefined') {
|
||||||
set['items.gear.owned.head_special_takeThis'] = false;
|
set['items.gear.owned.head_special_takeThis'] = false;
|
||||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_takeThis', _id: uuid()}};
|
push = { pinnedItems: { type: 'marketGear', path: 'gear.flat.head_special_takeThis', _id: uuid() } };
|
||||||
} else if (typeof user.items.gear.owned.weapon_special_takeThis !== 'undefined') {
|
} else if (typeof user.items.gear.owned.weapon_special_takeThis !== 'undefined') {
|
||||||
set['items.gear.owned.armor_special_takeThis'] = false;
|
set['items.gear.owned.armor_special_takeThis'] = false;
|
||||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_takeThis', _id: uuid()}};
|
push = { pinnedItems: { type: 'marketGear', path: 'gear.flat.armor_special_takeThis', _id: uuid() } };
|
||||||
} else if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') {
|
} else if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') {
|
||||||
set['items.gear.owned.weapon_special_takeThis'] = false;
|
set['items.gear.owned.weapon_special_takeThis'] = false;
|
||||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.weapon_special_takeThis', _id: uuid()}};
|
push = { pinnedItems: { type: 'marketGear', path: 'gear.flat.weapon_special_takeThis', _id: uuid() } };
|
||||||
} else {
|
} else {
|
||||||
set['items.gear.owned.shield_special_takeThis'] = false;
|
set['items.gear.owned.shield_special_takeThis'] = false;
|
||||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.shield_special_takeThis', _id: uuid()}};
|
push = { pinnedItems: { type: 'marketGear', path: 'gear.flat.shield_special_takeThis', _id: uuid() } };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||||
|
|
||||||
if (push) {
|
if (push) {
|
||||||
return await User.update({_id: user._id}, {$set: set, $push: push}).exec();
|
return User.update({ _id: user._id }, { $set: set, $push: push }).exec();
|
||||||
} else {
|
|
||||||
return await User.update({_id: user._id}, {$set: set}).exec();
|
|
||||||
}
|
}
|
||||||
|
return User.update({ _id: user._id }, { $set: set }).exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = async function processUsers () {
|
export default async function processUsers () {
|
||||||
let query = {
|
const query = {
|
||||||
migration: {$ne: MIGRATION_NAME},
|
migration: { $ne: MIGRATION_NAME },
|
||||||
challenges: '00708425-d477-41a5-bf27-6270466e7976',
|
challenges: '00708425-d477-41a5-bf27-6270466e7976',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ module.exports = async function processUsers () {
|
|||||||
const users = await User // eslint-disable-line no-await-in-loop
|
const users = await User // eslint-disable-line no-await-in-loop
|
||||||
.find(query)
|
.find(query)
|
||||||
.limit(250)
|
.limit(250)
|
||||||
.sort({_id: 1})
|
.sort({ _id: 1 })
|
||||||
.select(fields)
|
.select(fields)
|
||||||
.lean()
|
.lean()
|
||||||
.exec();
|
.exec();
|
||||||
@@ -78,4 +78,4 @@ module.exports = async function processUsers () {
|
|||||||
|
|
||||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable import/no-commonjs */
|
||||||
/*
|
/*
|
||||||
let migrationName = 'UserFromProdToTest';
|
let migrationName = 'UserFromProdToTest';
|
||||||
let authorName = 'TheHollidayInn'; // in case script author needs to know when their ...
|
let authorName = 'TheHollidayInn'; // in case script author needs to know when their ...
|
||||||
@@ -8,22 +9,24 @@ let authorUuid = ''; // ... own data is done
|
|||||||
* This migraition will copy user data from prod to test
|
* This migraition will copy user data from prod to test
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let monk = require('monk');
|
|
||||||
let testConnectionSting = ''; // FOR TEST DATABASE
|
|
||||||
let usersTest = monk(testConnectionSting).get('users', { castIds: false });
|
|
||||||
let groupsTest = monk(testConnectionSting).get('groups', { castIds: false });
|
|
||||||
let challengesTest = monk(testConnectionSting).get('challenges', { castIds: false });
|
|
||||||
let tasksTest = monk(testConnectionSting).get('tasks', { castIds: false });
|
|
||||||
|
|
||||||
let monk2 = require('monk');
|
|
||||||
let liveConnectString = ''; // FOR TEST DATABASE
|
|
||||||
let userLive = monk2(liveConnectString).get('users', { castIds: false });
|
|
||||||
let groupsLive = monk2(liveConnectString).get('groups', { castIds: false });
|
|
||||||
let challengesLive = monk2(liveConnectString).get('challenges', { castIds: false });
|
|
||||||
let tasksLive = monk2(liveConnectString).get('tasks', { castIds: false });
|
|
||||||
|
|
||||||
import uniq from 'lodash/uniq';
|
import uniq from 'lodash/uniq';
|
||||||
|
|
||||||
|
const monk = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||||
|
|
||||||
|
const testConnectionSting = ''; // FOR TEST DATABASE
|
||||||
|
const usersTest = monk(testConnectionSting).get('users', { castIds: false });
|
||||||
|
const groupsTest = monk(testConnectionSting).get('groups', { castIds: false });
|
||||||
|
const challengesTest = monk(testConnectionSting).get('challenges', { castIds: false });
|
||||||
|
const tasksTest = monk(testConnectionSting).get('tasks', { castIds: false });
|
||||||
|
|
||||||
|
const monk2 = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||||
|
|
||||||
|
const liveConnectString = ''; // FOR TEST DATABASE
|
||||||
|
const userLive = monk2(liveConnectString).get('users', { castIds: false });
|
||||||
|
const groupsLive = monk2(liveConnectString).get('groups', { castIds: false });
|
||||||
|
const challengesLive = monk2(liveConnectString).get('challenges', { castIds: false });
|
||||||
|
const tasksLive = monk2(liveConnectString).get('tasks', { castIds: false });
|
||||||
|
|
||||||
// Variabls for updating
|
// Variabls for updating
|
||||||
/*
|
/*
|
||||||
let userIds = [
|
let userIds = [
|
||||||
@@ -36,11 +39,11 @@ let challengeIds = [];
|
|||||||
let tasksIds = [];
|
let tasksIds = [];
|
||||||
|
|
||||||
async function processUsers () {
|
async function processUsers () {
|
||||||
let userPromises = [];
|
const userPromises = [];
|
||||||
// {_id: {$in: userIds}}
|
// {_id: {$in: userIds}}
|
||||||
|
|
||||||
return userLive.find({guilds: 'b0764d64-8276-45a1-afa5-5ca9a5c64ca0'})
|
return userLive.find({ guilds: 'b0764d64-8276-45a1-afa5-5ca9a5c64ca0' })
|
||||||
.each((user) => {
|
.each(user => {
|
||||||
if (user.guilds.length > 0) groupIds = groupIds.concat(user.guilds);
|
if (user.guilds.length > 0) groupIds = groupIds.concat(user.guilds);
|
||||||
if (user.party._id) groupIds.push(user.party._id);
|
if (user.party._id) groupIds.push(user.party._id);
|
||||||
if (user.challenges.length > 0) challengeIds = challengeIds.concat(user.challenges);
|
if (user.challenges.length > 0) challengeIds = challengeIds.concat(user.challenges);
|
||||||
@@ -49,64 +52,56 @@ async function processUsers () {
|
|||||||
if (user.tasksOrder.dailys.length > 0) tasksIds = tasksIds.concat(user.tasksOrder.dailys);
|
if (user.tasksOrder.dailys.length > 0) tasksIds = tasksIds.concat(user.tasksOrder.dailys);
|
||||||
if (user.tasksOrder.habits.length > 0) tasksIds = tasksIds.concat(user.tasksOrder.habits);
|
if (user.tasksOrder.habits.length > 0) tasksIds = tasksIds.concat(user.tasksOrder.habits);
|
||||||
|
|
||||||
let userPromise = usersTest.update({_id: user._id}, user, {upsert: true});
|
const userPromise = usersTest.update({ _id: user._id }, user, { upsert: true });
|
||||||
userPromises.push(userPromise);
|
userPromises.push(userPromise);
|
||||||
}).then(() => {
|
}).then(() => Promise.all(userPromises))
|
||||||
return Promise.all(userPromises);
|
|
||||||
})
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
console.log('Done User');
|
console.log('Done User');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function processGroups () {
|
function processGroups () {
|
||||||
let promises = [];
|
const promises = [];
|
||||||
let groupsToQuery = uniq(groupIds);
|
const groupsToQuery = uniq(groupIds);
|
||||||
return groupsLive.find({_id: {$in: groupsToQuery}})
|
return groupsLive.find({ _id: { $in: groupsToQuery } })
|
||||||
.each((group) => {
|
.each(group => {
|
||||||
let promise = groupsTest.update({_id: group._id}, group, {upsert: true});
|
const promise = groupsTest.update({ _id: group._id }, group, { upsert: true });
|
||||||
promises.push(promise);
|
promises.push(promise);
|
||||||
}).then(() => {
|
}).then(() => Promise.all(promises))
|
||||||
return Promise.all(promises);
|
|
||||||
})
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
console.log('Done Group');
|
console.log('Done Group');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function processChallenges () {
|
function processChallenges () {
|
||||||
let promises = [];
|
const promises = [];
|
||||||
let challengesToQuery = uniq(challengeIds);
|
const challengesToQuery = uniq(challengeIds);
|
||||||
return challengesLive.find({_id: {$in: challengesToQuery}})
|
return challengesLive.find({ _id: { $in: challengesToQuery } })
|
||||||
.each((challenge) => {
|
.each(challenge => {
|
||||||
let promise = challengesTest.update({_id: challenge._id}, challenge, {upsert: true});
|
const promise = challengesTest.update({ _id: challenge._id }, challenge, { upsert: true });
|
||||||
promises.push(promise);
|
promises.push(promise);
|
||||||
}).then(() => {
|
}).then(() => Promise.all(promises))
|
||||||
return Promise.all(promises);
|
|
||||||
})
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
console.log('Done Challenge');
|
console.log('Done Challenge');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function processTasks () {
|
function processTasks () {
|
||||||
let promises = [];
|
const promises = [];
|
||||||
let tasksToQuery = uniq(tasksIds);
|
const tasksToQuery = uniq(tasksIds);
|
||||||
return tasksLive.find({_id: {$in: tasksToQuery}})
|
return tasksLive.find({ _id: { $in: tasksToQuery } })
|
||||||
.each((task) => {
|
.each(task => {
|
||||||
let promise = tasksTest.update({_id: task._id}, task, {upsert: true});
|
const promise = tasksTest.update({ _id: task._id }, task, { upsert: true });
|
||||||
promises.push(promise);
|
promises.push(promise);
|
||||||
}).then(() => {
|
}).then(() => Promise.all(promises))
|
||||||
return Promise.all(promises);
|
|
||||||
})
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
console.log('Done Tasks');
|
console.log('Done Tasks');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = async function prodToTest () {
|
export default async function prodToTest () {
|
||||||
await processUsers();
|
await processUsers();
|
||||||
await processGroups();
|
await processGroups();
|
||||||
await processChallenges();
|
await processChallenges();
|
||||||
await processTasks();
|
await processTasks();
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
'use strict';
|
/* eslint-disable import/no-commonjs */
|
||||||
|
const { MongoClient } = require('mongodb'); // eslint-disable-line import/no-extraneous-dependencies
|
||||||
const MongoClient = require('mongodb').MongoClient;
|
|
||||||
const logger = require('./logger');
|
const logger = require('./logger');
|
||||||
|
|
||||||
let dbConnection;
|
let dbConnection;
|
||||||
@@ -17,7 +16,7 @@ function connectToDb (dbUri) {
|
|||||||
|
|
||||||
logger.success(`Connected to ${dbUri}`);
|
logger.success(`Connected to ${dbUri}`);
|
||||||
|
|
||||||
resolve(database);
|
return resolve(database);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
'use strict';
|
/* eslint-disable import/no-commonjs */
|
||||||
|
const chalk = require('chalk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||||
const chalk = require('chalk');
|
|
||||||
|
|
||||||
function loggerGenerator (type, color) {
|
function loggerGenerator (type, color) {
|
||||||
return function logger () {
|
return function logger () {
|
||||||
let args = Array.from(arguments).map(arg => chalk[color](arg));
|
const args = Array
|
||||||
|
.from(arguments) // eslint-disable-line prefer-rest-params
|
||||||
|
.map(arg => chalk[color](arg));
|
||||||
console[type].apply(null, args);
|
console[type].apply(null, args);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
'use strict';
|
/* eslint-disable import/no-commonjs */
|
||||||
|
const logger = require('./logger');
|
||||||
let logger = require('./logger');
|
|
||||||
|
|
||||||
class Timer {
|
class Timer {
|
||||||
constructor (options) {
|
constructor (options = {}) {
|
||||||
options = options || {};
|
const warningThreshold = options.minutesWarningThreshold || 10;
|
||||||
let warningThreshold = options.minutesWarningThreshold || 10;
|
|
||||||
|
|
||||||
this.count = 0;
|
this.count = 0;
|
||||||
this._minutesWarningThreshold = warningThreshold * 60;
|
this._minutesWarningThreshold = warningThreshold * 60;
|
||||||
|
|
||||||
if (!options.disableAutoStart) this.start();
|
if (!options.disableAutoStart) this.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
start () {
|
start () {
|
||||||
this._internalTimer = setInterval(() => {
|
this._internalTimer = setInterval(() => {
|
||||||
this.count++;
|
this.count *= 1;
|
||||||
|
|
||||||
let shouldWarn = this._minutesWarningThreshold < this.count;
|
const shouldWarn = this._minutesWarningThreshold < this.count;
|
||||||
let logStyle = shouldWarn ? 'error' : 'warn';
|
const logStyle = shouldWarn ? 'error' : 'warn';
|
||||||
let dangerMessage = shouldWarn ? 'DANGER: ' : '';
|
const dangerMessage = shouldWarn ? 'DANGER: ' : '';
|
||||||
|
|
||||||
if (this.count % 30 === 0) {
|
if (this.count % 30 === 0) {
|
||||||
logger[logStyle](`${dangerMessage}Process has been running for`, this.count / 60, 'minutes');
|
logger[logStyle](`${dangerMessage}Process has been running for`, this.count / 60, 'minutes');
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
stop () {
|
stop () {
|
||||||
if (!this._internalTimer) {
|
if (!this._internalTimer) {
|
||||||
throw new Error('Timer has not started');
|
throw new Error('Timer has not started');
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
'use strict';
|
/* eslint-disable import/no-commonjs */
|
||||||
|
|
||||||
function unique (array) {
|
function unique (array) {
|
||||||
return Array.from(new Set(array));
|
return Array.from(new Set(array));
|
||||||
}
|
}
|
||||||
|
|||||||
19760
package-lock.json
generated
19760
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
133
package.json
133
package.json
@@ -1,76 +1,49 @@
|
|||||||
{
|
{
|
||||||
"name": "habitica",
|
"name": "habitica",
|
||||||
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
||||||
"version": "4.116.2",
|
"version": "4.118.0",
|
||||||
"main": "./website/server/index.js",
|
"main": "./website/server/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@google-cloud/trace-agent": "^4.0.0",
|
"@google-cloud/trace-agent": "^4.2.2",
|
||||||
"@slack/client": "^3.8.1",
|
"@slack/client": "^3.8.1",
|
||||||
"accepts": "^1.3.5",
|
"accepts": "^1.3.5",
|
||||||
"amazon-payments": "^0.2.7",
|
"amazon-payments": "^0.2.7",
|
||||||
"amplitude": "^3.5.0",
|
"amplitude": "^3.5.0",
|
||||||
"amplitude-js": "^5.2.2",
|
|
||||||
"apidoc": "^0.17.5",
|
"apidoc": "^0.17.5",
|
||||||
"apn": "^2.2.0",
|
"apn": "^2.2.0",
|
||||||
"autoprefixer": "^9.4.0",
|
"aws-sdk": "^2.556.0",
|
||||||
"aws-sdk": "^2.432.0",
|
|
||||||
"axios": "^0.19.0",
|
|
||||||
"axios-progress-bar": "^1.2.0",
|
|
||||||
"babel-core": "^6.26.3",
|
|
||||||
"babel-eslint": "^8.2.3",
|
|
||||||
"babel-loader": "^7.1.4",
|
|
||||||
"babel-plugin-syntax-async-functions": "^6.13.0",
|
|
||||||
"babel-plugin-syntax-dynamic-import": "^6.18.0",
|
|
||||||
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
|
|
||||||
"babel-plugin-transform-object-rest-spread": "^6.16.0",
|
|
||||||
"babel-plugin-transform-regenerator": "^6.16.1",
|
|
||||||
"babel-polyfill": "^6.6.1",
|
|
||||||
"babel-preset-es2015": "^6.6.0",
|
|
||||||
"babel-register": "^6.6.0",
|
|
||||||
"babel-runtime": "^6.11.6",
|
|
||||||
"bcrypt": "^3.0.6",
|
"bcrypt": "^3.0.6",
|
||||||
"body-parser": "^1.18.3",
|
"body-parser": "^1.18.3",
|
||||||
"bootstrap": "^4.1.1",
|
|
||||||
"bootstrap-vue": "^2.0.2",
|
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"cookie-session": "^1.3.3",
|
"cookie-session": "^1.3.3",
|
||||||
"coupon-code": "^0.4.5",
|
"coupon-code": "^0.4.5",
|
||||||
"cross-env": "^6.0.0",
|
|
||||||
"css-loader": "^0.28.11",
|
|
||||||
"csv-stringify": "^5.1.0",
|
"csv-stringify": "^5.1.0",
|
||||||
"cwait": "^1.1.1",
|
"cwait": "^1.1.1",
|
||||||
"domain-middleware": "~0.1.0",
|
"domain-middleware": "~0.1.0",
|
||||||
"express": "^4.16.3",
|
"express": "^4.16.3",
|
||||||
"express-basic-auth": "^1.1.5",
|
"express-basic-auth": "^1.1.5",
|
||||||
"express-validator": "^5.2.0",
|
"express-validator": "^5.2.0",
|
||||||
"extract-text-webpack-plugin": "^3.0.2",
|
"glob": "^7.1.5",
|
||||||
"glob": "^7.1.2",
|
|
||||||
"got": "^9.0.0",
|
"got": "^9.0.0",
|
||||||
"gulp": "^4.0.0",
|
"gulp": "^4.0.0",
|
||||||
"gulp-babel": "^7.0.1",
|
"gulp-babel": "^8.0.0",
|
||||||
"gulp-imagemin": "^6.0.0",
|
"gulp-imagemin": "^6.1.1",
|
||||||
"gulp-nodemon": "^2.4.1",
|
"gulp-nodemon": "^2.4.1",
|
||||||
"gulp.spritesmith": "^6.9.0",
|
"gulp.spritesmith": "^6.9.0",
|
||||||
"habitica-markdown": "^1.3.0",
|
"habitica-markdown": "^1.3.0",
|
||||||
"hellojs": "^1.18.1",
|
"helmet": "^3.21.2",
|
||||||
"helmet": "^3.21.0",
|
"image-size": "^0.8.3",
|
||||||
"html-webpack-plugin": "^3.2.0",
|
|
||||||
"image-size": "^0.8.0",
|
|
||||||
"in-app-purchase": "^1.11.3",
|
"in-app-purchase": "^1.11.3",
|
||||||
"intro.js": "^2.9.3",
|
|
||||||
"jquery": ">=3.0.0",
|
|
||||||
"js2xmlparser": "^4.0.0",
|
"js2xmlparser": "^4.0.0",
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.15",
|
||||||
"merge-stream": "^2.0.0",
|
"merge-stream": "^2.0.0",
|
||||||
"method-override": "^3.0.0",
|
"method-override": "^3.0.0",
|
||||||
"moment": "^2.22.1",
|
"moment": "^2.24.0",
|
||||||
"moment-recur": "^1.0.7",
|
"moment-recur": "^1.0.7",
|
||||||
"mongoose": "^5.6.9",
|
"mongoose": "^5.7.7",
|
||||||
"morgan": "^1.7.0",
|
"morgan": "^1.7.0",
|
||||||
"nconf": "^0.10.0",
|
"nconf": "^0.10.0",
|
||||||
"node-gcm": "^1.0.2",
|
"node-gcm": "^1.0.2",
|
||||||
"node-sass": "^4.12.0",
|
|
||||||
"ora": "^3.2.0",
|
|
||||||
"pageres": "^5.1.0",
|
"pageres": "^5.1.0",
|
||||||
"passport": "^0.4.0",
|
"passport": "^0.4.0",
|
||||||
"passport-facebook": "^3.0.0",
|
"passport-facebook": "^3.0.0",
|
||||||
@@ -78,40 +51,17 @@
|
|||||||
"passport-google-oauth20": "1.0.0",
|
"passport-google-oauth20": "1.0.0",
|
||||||
"paypal-ipn": "3.0.0",
|
"paypal-ipn": "3.0.0",
|
||||||
"paypal-rest-sdk": "^1.8.1",
|
"paypal-rest-sdk": "^1.8.1",
|
||||||
"popper.js": "^1.14.3",
|
|
||||||
"postcss-easy-import": "^3.0.0",
|
|
||||||
"ps-tree": "^1.0.0",
|
"ps-tree": "^1.0.0",
|
||||||
"pug": "^2.0.3",
|
|
||||||
"regenerator-runtime": "^0.13.3",
|
"regenerator-runtime": "^0.13.3",
|
||||||
"rimraf": "^2.4.3",
|
"rimraf": "^3.0.0",
|
||||||
"sass-loader": "^7.0.3",
|
|
||||||
"shelljs": "^0.8.2",
|
|
||||||
"short-uuid": "^3.0.0",
|
"short-uuid": "^3.0.0",
|
||||||
"smartbanner.js": "^1.11.0",
|
"stripe": "^7.10.0",
|
||||||
"stripe": "^7.9.0",
|
|
||||||
"superagent": "^5.0.2",
|
"superagent": "^5.0.2",
|
||||||
"svg-inline-loader": "^0.8.0",
|
|
||||||
"svg-url-loader": "^3.0.0",
|
|
||||||
"svgo": "^1.2.0",
|
|
||||||
"svgo-loader": "^2.1.0",
|
|
||||||
"universal-analytics": "^0.4.17",
|
"universal-analytics": "^0.4.17",
|
||||||
"update": "^0.7.4",
|
|
||||||
"upgrade": "^1.1.0",
|
|
||||||
"url-loader": "^1.0.0",
|
|
||||||
"useragent": "^2.1.9",
|
"useragent": "^2.1.9",
|
||||||
"uuid": "^3.0.1",
|
"uuid": "^3.3.3",
|
||||||
"validator": "^11.0.0",
|
"validator": "^11.0.0",
|
||||||
"vinyl-buffer": "^1.0.1",
|
"vinyl-buffer": "^1.0.1",
|
||||||
"vue": "^2.6.10",
|
|
||||||
"vue-loader": "^14.2.2",
|
|
||||||
"vue-mugen-scroll": "^0.2.1",
|
|
||||||
"vue-router": "^3.0.0",
|
|
||||||
"vue-style-loader": "^4.1.0",
|
|
||||||
"vue-template-compiler": "^2.6.10",
|
|
||||||
"vuedraggable": "^2.20.0",
|
|
||||||
"vuejs-datepicker": "git://github.com/habitrpg/vuejs-datepicker.git#5d237615463a84a23dd6f3f77c6ab577d68593ec",
|
|
||||||
"webpack": "^3.12.0",
|
|
||||||
"webpack-merge": "^4.1.3",
|
|
||||||
"winston": "^2.4.3",
|
"winston": "^2.4.3",
|
||||||
"winston-loggly-bulk": "^2.0.2",
|
"winston-loggly-bulk": "^2.0.2",
|
||||||
"xml2js": "^0.4.4"
|
"xml2js": "^0.4.4"
|
||||||
@@ -122,7 +72,8 @@
|
|||||||
"npm": "^6"
|
"npm": "^6"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "eslint --ext .js,.vue .",
|
"lint": "eslint --ext .js --fix . && cd website/client && npm run lint",
|
||||||
|
"lint-no-fix": "eslint --ext .js . && cd website/client && npm run lint --no-fix",
|
||||||
"test": "npm run lint && gulp test && gulp apidoc",
|
"test": "npm run lint && gulp test && gulp apidoc",
|
||||||
"test:build": "gulp test:prepare:build",
|
"test:build": "gulp test:prepare:build",
|
||||||
"test:api-v3": "gulp test:api-v3",
|
"test:api-v3": "gulp test:api-v3",
|
||||||
@@ -137,60 +88,32 @@
|
|||||||
"test:nodemon": "gulp test:nodemon",
|
"test:nodemon": "gulp test:nodemon",
|
||||||
"coverage": "COVERAGE=true mocha --require register-handlers.js --reporter html-cov > coverage.html; open coverage.html",
|
"coverage": "COVERAGE=true mocha --require register-handlers.js --reporter html-cov > coverage.html; open coverage.html",
|
||||||
"sprites": "gulp sprites:compile",
|
"sprites": "gulp sprites:compile",
|
||||||
"client:dev": "node webpack/dev-server.js",
|
"client:dev": "cd website/client && npm run serve",
|
||||||
"client:build": "gulp build:client",
|
"client:build": "cd website/client && npm run build",
|
||||||
"client:unit": "cross-env NODE_ENV=test karma start test/client/unit/karma.conf.js --single-run",
|
"client:unit": "cd website/client && npm run test:unit",
|
||||||
"client:unit:watch": "cross-env NODE_ENV=test karma start test/client/unit/karma.conf.js",
|
|
||||||
"client:e2e": "node test/client/e2e/runner.js",
|
|
||||||
"client:test": "npm run client:unit && npm run client:e2e",
|
|
||||||
"start": "gulp nodemon",
|
"start": "gulp nodemon",
|
||||||
"postinstall": "gulp build",
|
"postinstall": "gulp build && cd website/client && npm install",
|
||||||
"apidoc": "gulp apidoc"
|
"apidoc": "gulp apidoc"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/test-utils": "^1.0.0-beta.29",
|
"@babel/core": "^7.6.4",
|
||||||
"babel-plugin-istanbul": "^4.1.6",
|
"@babel/preset-env": "^7.6.3",
|
||||||
"babel-plugin-syntax-object-rest-spread": "^6.13.0",
|
"@babel/register": "^7.6.2",
|
||||||
|
"axios": "^0.19.0",
|
||||||
"chai": "^4.1.2",
|
"chai": "^4.1.2",
|
||||||
"chai-as-promised": "^7.1.1",
|
"chai-as-promised": "^7.1.1",
|
||||||
"chalk": "^2.4.1",
|
"chalk": "^2.4.1",
|
||||||
"chromedriver": "^77.0.0",
|
"eslint": "^6.6.0",
|
||||||
"connect-history-api-fallback": "^1.1.0",
|
"eslint-config-habitrpg": "^6.2.0",
|
||||||
"cross-spawn": "^7.0.0",
|
|
||||||
"eslint": "^4.19.1",
|
|
||||||
"eslint-config-habitrpg": "^4.0.0",
|
|
||||||
"eslint-friendly-formatter": "^4.0.1",
|
|
||||||
"eslint-loader": "^2.0.0",
|
|
||||||
"eslint-plugin-html": "^4.0.3",
|
|
||||||
"eslint-plugin-mocha": "^5.0.0",
|
"eslint-plugin-mocha": "^5.0.0",
|
||||||
"eventsource-polyfill": "^0.9.6",
|
|
||||||
"expect.js": "^0.3.1",
|
"expect.js": "^0.3.1",
|
||||||
"http-proxy-middleware": "^0.20.0",
|
|
||||||
"istanbul": "^1.1.0-alpha.1",
|
"istanbul": "^1.1.0-alpha.1",
|
||||||
"karma": "^4.0.1",
|
|
||||||
"karma-babel-preprocessor": "^7.0.0",
|
|
||||||
"karma-chai-plugins": "^0.9.0",
|
|
||||||
"karma-chrome-launcher": "^3.0.0",
|
|
||||||
"karma-coverage": "^1.1.2",
|
|
||||||
"karma-mocha": "^1.3.0",
|
|
||||||
"karma-mocha-reporter": "^2.2.5",
|
|
||||||
"karma-sinon-chai": "^2.0.0",
|
|
||||||
"karma-sinon-stub-promise": "^1.0.0",
|
|
||||||
"karma-sourcemap-loader": "^0.3.7",
|
|
||||||
"karma-spec-reporter": "0.0.32",
|
|
||||||
"karma-webpack": "^3.0.0",
|
|
||||||
"mocha": "^5.1.1",
|
"mocha": "^5.1.1",
|
||||||
"monk": "^6.0.6",
|
"monk": "^7.1.1",
|
||||||
"nightwatch": "^1.0.16",
|
|
||||||
"puppeteer": "^1.14.0",
|
|
||||||
"require-again": "^2.0.0",
|
"require-again": "^2.0.0",
|
||||||
"selenium-server": "^3.12.0",
|
|
||||||
"sinon": "^7.2.4",
|
"sinon": "^7.2.4",
|
||||||
"sinon-chai": "^3.0.0",
|
"sinon-chai": "^3.0.0",
|
||||||
"sinon-stub-promise": "^4.0.0",
|
"sinon-stub-promise": "^4.0.0"
|
||||||
"webpack-bundle-analyzer": "^2.12.0",
|
|
||||||
"webpack-dev-middleware": "^2.0.5",
|
|
||||||
"webpack-hot-middleware": "^2.22.2"
|
|
||||||
},
|
},
|
||||||
"optionalDependencies": {}
|
"optionalDependencies": {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console, import/no-commonjs */
|
||||||
import axios from 'axios';
|
import axios from 'axios'; // eslint-disable-line import/no-extraneous-dependencies
|
||||||
import { model as User } from '../website/server/models/user';
|
|
||||||
import nconf from 'nconf';
|
import nconf from 'nconf';
|
||||||
|
import { model as User } from '../website/server/models/user';
|
||||||
|
|
||||||
const AMPLITUDE_KEY = nconf.get('AMPLITUDE_KEY');
|
const AMPLITUDE_KEY = nconf.get('AMPLITUDE_KEY');
|
||||||
const AMPLITUDE_SECRET = nconf.get('AMPLITUDE_SECRET');
|
const AMPLITUDE_SECRET = nconf.get('AMPLITUDE_SECRET');
|
||||||
const BASE_URL = nconf.get('BASE_URL');
|
const BASE_URL = nconf.get('BASE_URL');
|
||||||
|
|
||||||
async function _deleteAmplitudeData (userId, email) {
|
async function deleteAmplitudeData (userId, email) {
|
||||||
const response = await axios.post(
|
const response = await axios.post(
|
||||||
'https://amplitude.com/api/2/deletions/users',
|
'https://amplitude.com/api/2/deletions/users',
|
||||||
{
|
{
|
||||||
@@ -19,22 +19,24 @@ async function _deleteAmplitudeData (userId, email) {
|
|||||||
username: AMPLITUDE_KEY,
|
username: AMPLITUDE_KEY,
|
||||||
password: AMPLITUDE_SECRET,
|
password: AMPLITUDE_SECRET,
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
).catch((err) => {
|
).catch(err => {
|
||||||
console.log(err.response.data);
|
console.log(err.response.data);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response) console.log(`${response.status} ${response.statusText}`);
|
if (response) console.log(`${response.status} ${response.statusText}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _deleteHabiticaData (user, email) {
|
async function deleteHabiticaData (user, email) {
|
||||||
await User.update(
|
await User.update(
|
||||||
{_id: user._id},
|
{ _id: user._id },
|
||||||
{$set: {
|
{
|
||||||
'auth.local.email': email,
|
$set: {
|
||||||
'auth.local.hashed_password': '$2a$10$QDnNh1j1yMPnTXDEOV38xOePEWFd4X8DSYwAM8XTmqmacG5X0DKjW',
|
'auth.local.email': email,
|
||||||
'auth.local.passwordHashMethod': 'bcrypt',
|
'auth.local.hashed_password': '$2a$10$QDnNh1j1yMPnTXDEOV38xOePEWFd4X8DSYwAM8XTmqmacG5X0DKjW',
|
||||||
}}
|
'auth.local.passwordHashMethod': 'bcrypt',
|
||||||
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
const response = await axios.delete(
|
const response = await axios.delete(
|
||||||
`${BASE_URL}/api/v3/user`,
|
`${BASE_URL}/api/v3/user`,
|
||||||
@@ -46,8 +48,8 @@ async function _deleteHabiticaData (user, email) {
|
|||||||
'x-api-user': user._id,
|
'x-api-user': user._id,
|
||||||
'x-api-key': user.apiToken,
|
'x-api-key': user.apiToken,
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
).catch((err) => {
|
).catch(err => {
|
||||||
console.log(err.response.data);
|
console.log(err.response.data);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -57,14 +59,15 @@ async function _deleteHabiticaData (user, email) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _processEmailAddress (email) {
|
async function processEmailAddress (email) {
|
||||||
const emailRegex = new RegExp(`^${email}$`, 'i');
|
const emailRegex = new RegExp(`^${email}$`, 'i');
|
||||||
const users = await User.find({
|
const users = await User.find({
|
||||||
$or: [
|
$or: [
|
||||||
{'auth.local.email': emailRegex},
|
{ 'auth.local.email': emailRegex },
|
||||||
{'auth.facebook.emails.value': emailRegex},
|
{ 'auth.facebook.emails.value': emailRegex },
|
||||||
{'auth.google.emails.value': emailRegex},
|
{ 'auth.google.emails.value': emailRegex },
|
||||||
]},
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
_id: 1,
|
_id: 1,
|
||||||
apiToken: 1,
|
apiToken: 1,
|
||||||
@@ -74,15 +77,15 @@ async function _processEmailAddress (email) {
|
|||||||
if (users.length < 1) {
|
if (users.length < 1) {
|
||||||
console.log(`No users found with email address ${email}`);
|
console.log(`No users found with email address ${email}`);
|
||||||
} else {
|
} else {
|
||||||
for (const user of users) {
|
Promise.all(users.map(user => (async () => {
|
||||||
await _deleteAmplitudeData(user._id, email); // eslint-disable-line no-await-in-loop
|
await deleteAmplitudeData(user._id, email); // eslint-disable-line no-await-in-loop
|
||||||
await _deleteHabiticaData(user, email); // eslint-disable-line no-await-in-loop
|
await deleteHabiticaData(user, email); // eslint-disable-line no-await-in-loop
|
||||||
}
|
})()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteUserData (emails) {
|
function deleteUserData (emails) {
|
||||||
const emailPromises = emails.map(_processEmailAddress);
|
const emailPromises = emails.map(processEmailAddress);
|
||||||
return Promise.all(emailPromises);
|
return Promise.all(emailPromises);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
require('babel-register');
|
/* eslint-disable import/no-commonjs */
|
||||||
|
require('@babel/register'); // eslint-disable-line import/no-extraneous-dependencies
|
||||||
|
|
||||||
// This file is used for creating paypal billing plans. PayPal doesn't have a web interface for setting up recurring
|
// This file is used for creating paypal billing plans.
|
||||||
// payment plan definitions, instead you have to create it via their REST SDK and keep it updated the same way. So this
|
// PayPal doesn't have a web interface for setting up recurring
|
||||||
// file will be used once for initing your billing plan (then you get the resultant plan.id to store in config.json),
|
// payment plan definitions, instead you have to create it
|
||||||
|
// via their REST SDK and keep it updated the same way. So this
|
||||||
|
// file will be used once for initing your billing plan
|
||||||
|
// (then you get the resultant plan.id to store in config.json),
|
||||||
// and once for any time you need to edit the plan thereafter
|
// and once for any time you need to edit the plan thereafter
|
||||||
|
|
||||||
/* eslint-disable no-console, camelcase, no-case-declarations */
|
/* eslint-disable no-console, camelcase, no-case-declarations */
|
||||||
@@ -12,11 +16,12 @@ const nconf = require('nconf');
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const paypal = require('paypal-rest-sdk');
|
const paypal = require('paypal-rest-sdk');
|
||||||
const blocks = require('../website/common').content.subscriptionBlocks;
|
const blocks = require('../website/common').content.subscriptionBlocks;
|
||||||
|
|
||||||
const live = nconf.get('PAYPAL_MODE') === 'live';
|
const live = nconf.get('PAYPAL_MODE') === 'live';
|
||||||
|
|
||||||
nconf.argv().env().file('user', path.join(path.resolve(__dirname, '../config.json')));
|
nconf.argv().env().file('user', path.join(path.resolve(__dirname, '../config.json')));
|
||||||
|
|
||||||
let OP = 'create'; // list get update create create-webprofile
|
const OP = 'create'; // list get update create create-webprofile
|
||||||
|
|
||||||
paypal.configure({
|
paypal.configure({
|
||||||
mode: nconf.get('PAYPAL_MODE'), // sandbox or live
|
mode: nconf.get('PAYPAL_MODE'), // sandbox or live
|
||||||
@@ -25,8 +30,8 @@ paypal.configure({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// https://developer.paypal.com/docs/api/#billing-plans-and-agreements
|
// https://developer.paypal.com/docs/api/#billing-plans-and-agreements
|
||||||
let billingPlanTitle = 'Habitica Subscription';
|
const billingPlanTitle = 'Habitica Subscription';
|
||||||
let billingPlanAttributes = {
|
const billingPlanAttributes = {
|
||||||
description: billingPlanTitle,
|
description: billingPlanTitle,
|
||||||
type: 'INFINITE',
|
type: 'INFINITE',
|
||||||
merchant_preferences: {
|
merchant_preferences: {
|
||||||
@@ -41,7 +46,7 @@ let billingPlanAttributes = {
|
|||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
|
|
||||||
_.each(blocks, (block) => {
|
_.each(blocks, block => {
|
||||||
block.definition = _.cloneDeep(billingPlanAttributes);
|
block.definition = _.cloneDeep(billingPlanAttributes);
|
||||||
_.merge(block.definition.payment_definitions[0], {
|
_.merge(block.definition.payment_definitions[0], {
|
||||||
name: `${billingPlanTitle} ($${block.price} every ${block.months} months, recurring)`,
|
name: `${billingPlanTitle} ($${block.price} every ${block.months} months, recurring)`,
|
||||||
@@ -57,17 +62,17 @@ _.each(blocks, (block) => {
|
|||||||
|
|
||||||
switch (OP) {
|
switch (OP) {
|
||||||
case 'list':
|
case 'list':
|
||||||
paypal.billingPlan.list({status: 'ACTIVE'}, (err, plans) => {
|
paypal.billingPlan.list({ status: 'ACTIVE' }, (err, plans) => {
|
||||||
console.log({err, plans});
|
console.log({ err, plans });
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'get':
|
case 'get':
|
||||||
paypal.billingPlan.get(nconf.get('PAYPAL_BILLING_PLANS_basic_12mo'), (err, plan) => {
|
paypal.billingPlan.get(nconf.get('PAYPAL_BILLING_PLANS_basic_12mo'), (err, plan) => {
|
||||||
console.log({err, plan});
|
console.log({ err, plan });
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'update':
|
case 'update':
|
||||||
let updatePayload = {
|
const updatePayload = {
|
||||||
op: 'replace',
|
op: 'replace',
|
||||||
path: '/merchant_preferences',
|
path: '/merchant_preferences',
|
||||||
value: {
|
value: {
|
||||||
@@ -75,7 +80,7 @@ switch (OP) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
paypal.billingPlan.update(nconf.get('PAYPAL_BILLING_PLANS_basic_12mo'), updatePayload, (err, res) => {
|
paypal.billingPlan.update(nconf.get('PAYPAL_BILLING_PLANS_basic_12mo'), updatePayload, (err, res) => {
|
||||||
console.log({err, plan: res});
|
console.log({ err, plan: res });
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'create':
|
case 'create':
|
||||||
@@ -83,10 +88,10 @@ switch (OP) {
|
|||||||
if (err) return console.log(err);
|
if (err) return console.log(err);
|
||||||
|
|
||||||
if (plan.state === 'ACTIVE') {
|
if (plan.state === 'ACTIVE') {
|
||||||
return console.log({err, plan});
|
return console.log({ err, plan });
|
||||||
}
|
}
|
||||||
|
|
||||||
let billingPlanUpdateAttributes = [{
|
const billingPlanUpdateAttributes = [{
|
||||||
op: 'replace',
|
op: 'replace',
|
||||||
path: '/',
|
path: '/',
|
||||||
value: {
|
value: {
|
||||||
@@ -96,12 +101,14 @@ switch (OP) {
|
|||||||
|
|
||||||
// Activate the plan by changing status to Active
|
// Activate the plan by changing status to Active
|
||||||
paypal.billingPlan.update(plan.id, billingPlanUpdateAttributes, (err2, response) => {
|
paypal.billingPlan.update(plan.id, billingPlanUpdateAttributes, (err2, response) => {
|
||||||
console.log({err: err2, response, id: plan.id});
|
console.log({ err: err2, response, id: plan.id });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return null;
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'create-webprofile':
|
case 'create-webprofile':
|
||||||
let webexpinfo = {
|
const webexpinfo = {
|
||||||
name: 'HabiticaProfile',
|
name: 'HabiticaProfile',
|
||||||
input_fields: {
|
input_fields: {
|
||||||
no_shipping: 1,
|
no_shipping: 1,
|
||||||
@@ -112,4 +119,6 @@ switch (OP) {
|
|||||||
console.log(error, result);
|
console.log(error, result);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error('Invalid op');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": [
|
|
||||||
"habitrpg/mocha",
|
|
||||||
"habitrpg/esnext"
|
|
||||||
],
|
|
||||||
"env": {
|
|
||||||
"node": true,
|
|
||||||
},
|
|
||||||
"globals": {
|
|
||||||
"_": true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
12
test/.eslintrc.js
Normal file
12
test/.eslintrc.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: [
|
||||||
|
'habitrpg/lib/mocha',
|
||||||
|
],
|
||||||
|
globals: {
|
||||||
|
_: true,
|
||||||
|
chai: true,
|
||||||
|
expect: true,
|
||||||
|
sinon: true,
|
||||||
|
sandbox: true
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
import analyticsService from '../../../../website/server/libs/analyticsService';
|
|
||||||
import Amplitude from 'amplitude';
|
import Amplitude from 'amplitude';
|
||||||
import { Visitor } from 'universal-analytics';
|
import { Visitor } from 'universal-analytics';
|
||||||
|
import * as analyticsService from '../../../../website/server/libs/analyticsService';
|
||||||
|
|
||||||
describe('analyticsService', () => {
|
describe('analyticsService', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -16,7 +16,8 @@ describe('analyticsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('#track', () => {
|
describe('#track', () => {
|
||||||
let eventType, data;
|
let eventType; let
|
||||||
|
data;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
Visitor.prototype.event.yields();
|
Visitor.prototype.event.yields();
|
||||||
@@ -35,12 +36,10 @@ describe('analyticsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
context('Amplitude', () => {
|
context('Amplitude', () => {
|
||||||
it('calls out to amplitude', () => {
|
it('calls out to amplitude', () => analyticsService.track(eventType, data)
|
||||||
return analyticsService.track(eventType, data)
|
.then(() => {
|
||||||
.then(() => {
|
expect(Amplitude.prototype.track).to.be.calledOnce;
|
||||||
expect(Amplitude.prototype.track).to.be.calledOnce;
|
}));
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('uses a dummy user id if none is provided', () => {
|
it('uses a dummy user id if none is provided', () => {
|
||||||
delete data.uuid;
|
delete data.uuid;
|
||||||
@@ -55,7 +54,7 @@ describe('analyticsService', () => {
|
|||||||
|
|
||||||
context('platform', () => {
|
context('platform', () => {
|
||||||
it('logs web platform', () => {
|
it('logs web platform', () => {
|
||||||
data.headers = {'x-client': 'habitica-web'};
|
data.headers = { 'x-client': 'habitica-web' };
|
||||||
|
|
||||||
return analyticsService.track(eventType, data)
|
return analyticsService.track(eventType, data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -66,7 +65,7 @@ describe('analyticsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('logs iOS platform', () => {
|
it('logs iOS platform', () => {
|
||||||
data.headers = {'x-client': 'habitica-ios'};
|
data.headers = { 'x-client': 'habitica-ios' };
|
||||||
|
|
||||||
return analyticsService.track(eventType, data)
|
return analyticsService.track(eventType, data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -77,7 +76,7 @@ describe('analyticsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('logs Android platform', () => {
|
it('logs Android platform', () => {
|
||||||
data.headers = {'x-client': 'habitica-android'};
|
data.headers = { 'x-client': 'habitica-android' };
|
||||||
|
|
||||||
return analyticsService.track(eventType, data)
|
return analyticsService.track(eventType, data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -88,7 +87,7 @@ describe('analyticsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('logs 3rd Party platform', () => {
|
it('logs 3rd Party platform', () => {
|
||||||
data.headers = {'x-client': 'some-third-party'};
|
data.headers = { 'x-client': 'some-third-party' };
|
||||||
|
|
||||||
return analyticsService.track(eventType, data)
|
return analyticsService.track(eventType, data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -169,18 +168,16 @@ describe('analyticsService', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends details about event', () => {
|
it('sends details about event', () => analyticsService.track(eventType, data)
|
||||||
return analyticsService.track(eventType, data)
|
.then(() => {
|
||||||
.then(() => {
|
expect(Amplitude.prototype.track).to.be.calledWithMatch({
|
||||||
expect(Amplitude.prototype.track).to.be.calledWithMatch({
|
event_properties: {
|
||||||
event_properties: {
|
category: 'behavior',
|
||||||
category: 'behavior',
|
resting: true,
|
||||||
resting: true,
|
cronCount: 5,
|
||||||
cronCount: 5,
|
},
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
}));
|
||||||
|
|
||||||
it('sends english item name for gear if itemKey is provided', () => {
|
it('sends english item name for gear if itemKey is provided', () => {
|
||||||
data.itemKey = 'headAccessory_special_foxEars';
|
data.itemKey = 'headAccessory_special_foxEars';
|
||||||
@@ -267,16 +264,18 @@ describe('analyticsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('sends user data if provided', () => {
|
it('sends user data if provided', () => {
|
||||||
let stats = { class: 'wizard', exp: 5, gp: 23, hp: 10, lvl: 4, mp: 30 };
|
const stats = {
|
||||||
let user = {
|
class: 'wizard', exp: 5, gp: 23, hp: 10, lvl: 4, mp: 30,
|
||||||
|
};
|
||||||
|
const user = {
|
||||||
stats,
|
stats,
|
||||||
contributor: { level: 1 },
|
contributor: { level: 1 },
|
||||||
purchased: { plan: { planId: 'foo-plan' } },
|
purchased: { plan: { planId: 'foo-plan' } },
|
||||||
flags: {tour: {intro: -2}},
|
flags: { tour: { intro: -2 } },
|
||||||
habits: [{_id: 'habit'}],
|
habits: [{ _id: 'habit' }],
|
||||||
dailys: [{_id: 'daily'}],
|
dailys: [{ _id: 'daily' }],
|
||||||
todos: [{_id: 'todo'}],
|
todos: [{ _id: 'todo' }],
|
||||||
rewards: [{_id: 'reward'}],
|
rewards: [{ _id: 'reward' }],
|
||||||
balance: 12,
|
balance: 12,
|
||||||
loginIncentives: 1,
|
loginIncentives: 1,
|
||||||
};
|
};
|
||||||
@@ -312,27 +311,24 @@ describe('analyticsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
context('GA', () => {
|
context('GA', () => {
|
||||||
it('calls out to GA', () => {
|
it('calls out to GA', () => analyticsService.track(eventType, data)
|
||||||
return analyticsService.track(eventType, data)
|
.then(() => {
|
||||||
.then(() => {
|
expect(Visitor.prototype.event).to.be.calledOnce;
|
||||||
expect(Visitor.prototype.event).to.be.calledOnce;
|
}));
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sends details about event', () => {
|
it('sends details about event', () => analyticsService.track(eventType, data)
|
||||||
return analyticsService.track(eventType, data)
|
.then(() => {
|
||||||
.then(() => {
|
expect(Visitor.prototype.event).to.be.calledWith({
|
||||||
expect(Visitor.prototype.event).to.be.calledWith({
|
ea: 'Cron',
|
||||||
ea: 'Cron',
|
ec: 'behavior',
|
||||||
ec: 'behavior',
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#trackPurchase', () => {
|
describe('#trackPurchase', () => {
|
||||||
let data, itemSpy;
|
let data; let
|
||||||
|
itemSpy;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
Visitor.prototype.event.yields();
|
Visitor.prototype.event.yields();
|
||||||
@@ -361,12 +357,10 @@ describe('analyticsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
context('Amplitude', () => {
|
context('Amplitude', () => {
|
||||||
it('calls out to amplitude', () => {
|
it('calls out to amplitude', () => analyticsService.trackPurchase(data)
|
||||||
return analyticsService.trackPurchase(data)
|
.then(() => {
|
||||||
.then(() => {
|
expect(Amplitude.prototype.track).to.be.calledOnce;
|
||||||
expect(Amplitude.prototype.track).to.be.calledOnce;
|
}));
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('uses a dummy user id if none is provided', () => {
|
it('uses a dummy user id if none is provided', () => {
|
||||||
delete data.uuid;
|
delete data.uuid;
|
||||||
@@ -381,7 +375,7 @@ describe('analyticsService', () => {
|
|||||||
|
|
||||||
context('platform', () => {
|
context('platform', () => {
|
||||||
it('logs web platform', () => {
|
it('logs web platform', () => {
|
||||||
data.headers = {'x-client': 'habitica-web'};
|
data.headers = { 'x-client': 'habitica-web' };
|
||||||
|
|
||||||
return analyticsService.trackPurchase(data)
|
return analyticsService.trackPurchase(data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -392,7 +386,7 @@ describe('analyticsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('logs iOS platform', () => {
|
it('logs iOS platform', () => {
|
||||||
data.headers = {'x-client': 'habitica-ios'};
|
data.headers = { 'x-client': 'habitica-ios' };
|
||||||
|
|
||||||
return analyticsService.trackPurchase(data)
|
return analyticsService.trackPurchase(data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -403,7 +397,7 @@ describe('analyticsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('logs Android platform', () => {
|
it('logs Android platform', () => {
|
||||||
data.headers = {'x-client': 'habitica-android'};
|
data.headers = { 'x-client': 'habitica-android' };
|
||||||
|
|
||||||
return analyticsService.trackPurchase(data)
|
return analyticsService.trackPurchase(data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -414,7 +408,7 @@ describe('analyticsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('logs 3rd Party platform', () => {
|
it('logs 3rd Party platform', () => {
|
||||||
data.headers = {'x-client': 'some-third-party'};
|
data.headers = { 'x-client': 'some-third-party' };
|
||||||
|
|
||||||
return analyticsService.trackPurchase(data)
|
return analyticsService.trackPurchase(data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -495,33 +489,33 @@ describe('analyticsService', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends details about purchase', () => {
|
it('sends details about purchase', () => analyticsService.trackPurchase(data)
|
||||||
return analyticsService.trackPurchase(data)
|
.then(() => {
|
||||||
.then(() => {
|
expect(Amplitude.prototype.track).to.be.calledWithMatch({
|
||||||
expect(Amplitude.prototype.track).to.be.calledWithMatch({
|
event_properties: {
|
||||||
event_properties: {
|
gift: false,
|
||||||
gift: false,
|
itemPurchased: 'Gems',
|
||||||
itemPurchased: 'Gems',
|
paymentMethod: 'PayPal',
|
||||||
paymentMethod: 'PayPal',
|
purchaseType: 'checkout',
|
||||||
purchaseType: 'checkout',
|
quantity: 1,
|
||||||
quantity: 1,
|
sku: 'paypal-checkout',
|
||||||
sku: 'paypal-checkout',
|
},
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
}));
|
||||||
|
|
||||||
it('sends user data if provided', () => {
|
it('sends user data if provided', () => {
|
||||||
let stats = { class: 'wizard', exp: 5, gp: 23, hp: 10, lvl: 4, mp: 30 };
|
const stats = {
|
||||||
let user = {
|
class: 'wizard', exp: 5, gp: 23, hp: 10, lvl: 4, mp: 30,
|
||||||
|
};
|
||||||
|
const user = {
|
||||||
stats,
|
stats,
|
||||||
contributor: { level: 1 },
|
contributor: { level: 1 },
|
||||||
purchased: { plan: { planId: 'foo-plan' } },
|
purchased: { plan: { planId: 'foo-plan' } },
|
||||||
flags: {tour: {intro: -2}},
|
flags: { tour: { intro: -2 } },
|
||||||
habits: [{_id: 'habit'}],
|
habits: [{ _id: 'habit' }],
|
||||||
dailys: [{_id: 'daily'}],
|
dailys: [{ _id: 'daily' }],
|
||||||
todos: [{_id: 'todo'}],
|
todos: [{ _id: 'todo' }],
|
||||||
rewards: [{_id: 'reward'}],
|
rewards: [{ _id: 'reward' }],
|
||||||
};
|
};
|
||||||
|
|
||||||
data.user = user;
|
data.user = user;
|
||||||
@@ -552,27 +546,23 @@ describe('analyticsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
context('GA', () => {
|
context('GA', () => {
|
||||||
it('calls out to GA', () => {
|
it('calls out to GA', () => analyticsService.trackPurchase(data)
|
||||||
return analyticsService.trackPurchase(data)
|
.then(() => {
|
||||||
.then(() => {
|
expect(Visitor.prototype.event).to.be.calledOnce;
|
||||||
expect(Visitor.prototype.event).to.be.calledOnce;
|
expect(Visitor.prototype.transaction).to.be.calledOnce;
|
||||||
expect(Visitor.prototype.transaction).to.be.calledOnce;
|
}));
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sends details about purchase', () => {
|
it('sends details about purchase', () => analyticsService.trackPurchase(data)
|
||||||
return analyticsService.trackPurchase(data)
|
.then(() => {
|
||||||
.then(() => {
|
expect(Visitor.prototype.event).to.be.calledWith({
|
||||||
expect(Visitor.prototype.event).to.be.calledWith({
|
ea: 'checkout',
|
||||||
ea: 'checkout',
|
ec: 'commerce',
|
||||||
ec: 'commerce',
|
el: 'PayPal',
|
||||||
el: 'PayPal',
|
ev: 8,
|
||||||
ev: 8,
|
|
||||||
});
|
|
||||||
expect(Visitor.prototype.transaction).to.be.calledWith('user-id', 8);
|
|
||||||
expect(itemSpy).to.be.calledWith(8, 1, 'paypal-checkout', 'Gems', 'checkout');
|
|
||||||
});
|
});
|
||||||
});
|
expect(Visitor.prototype.transaction).to.be.calledWith('user-id', 8);
|
||||||
|
expect(itemSpy).to.be.calledWith(8, 1, 'paypal-checkout', 'Gems', 'checkout');
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ describe('API Messages', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('clones the passed variables', () => {
|
it('clones the passed variables', () => {
|
||||||
let vars = {a: 1};
|
const vars = { a: 1 };
|
||||||
sandbox.stub(_, 'clone').returns({});
|
sandbox.stub(_, 'clone').returns({});
|
||||||
apiError('guildsOnlyPaginate', vars);
|
apiError('guildsOnlyPaginate', vars);
|
||||||
expect(_.clone).to.have.been.calledOnce;
|
expect(_.clone).to.have.been.calledOnce;
|
||||||
@@ -19,8 +19,8 @@ describe('API Messages', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('pass the message through _.template', () => {
|
it('pass the message through _.template', () => {
|
||||||
let vars = {a: 1};
|
const vars = { a: 1 };
|
||||||
let stub = sinon.stub().returns('string');
|
const stub = sinon.stub().returns('string');
|
||||||
sandbox.stub(_, 'template').returns(stub);
|
sandbox.stub(_, 'template').returns(stub);
|
||||||
apiError('guildsOnlyPaginate', vars);
|
apiError('guildsOnlyPaginate', vars);
|
||||||
expect(_.template).to.have.been.calledOnce;
|
expect(_.template).to.have.been.calledOnce;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import baseModel from '../../../../website/server/libs/baseModel';
|
|
||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
|
import baseModel from '../../../../website/server/libs/baseModel';
|
||||||
|
|
||||||
describe('Base model plugin', () => {
|
describe('Base model plugin', () => {
|
||||||
let schema;
|
let schema;
|
||||||
@@ -25,7 +25,7 @@ describe('Base model plugin', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('can add timestamps fields', () => {
|
it('can add timestamps fields', () => {
|
||||||
schema.plugin(baseModel, {timestamps: true});
|
schema.plugin(baseModel, { timestamps: true });
|
||||||
|
|
||||||
expect(schema.add).to.be.calledTwice;
|
expect(schema.add).to.be.calledTwice;
|
||||||
});
|
});
|
||||||
@@ -36,7 +36,7 @@ describe('Base model plugin', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(schema.statics.sanitize).to.exist;
|
expect(schema.statics.sanitize).to.exist;
|
||||||
let sanitized = schema.statics.sanitize({ok: true, noUpdateForMe: true});
|
const sanitized = schema.statics.sanitize({ ok: true, noUpdateForMe: true });
|
||||||
|
|
||||||
expect(sanitized).to.have.property('ok');
|
expect(sanitized).to.have.property('ok');
|
||||||
expect(sanitized).not.to.have.property('noUpdateForMe');
|
expect(sanitized).not.to.have.property('noUpdateForMe');
|
||||||
@@ -49,7 +49,7 @@ describe('Base model plugin', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(schema.statics.sanitize).to.exist;
|
expect(schema.statics.sanitize).to.exist;
|
||||||
let sanitized = schema.statics.sanitize({ok: true, noUpdateForMe: true, usuallySettable: true}, ['usuallySettable']);
|
const sanitized = schema.statics.sanitize({ ok: true, noUpdateForMe: true, usuallySettable: true }, ['usuallySettable']);
|
||||||
|
|
||||||
expect(sanitized).to.have.property('ok');
|
expect(sanitized).to.have.property('ok');
|
||||||
expect(sanitized).not.to.have.property('noUpdateForMe');
|
expect(sanitized).not.to.have.property('noUpdateForMe');
|
||||||
@@ -63,31 +63,31 @@ describe('Base model plugin', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(schema.options.toJSON.transform).to.exist;
|
expect(schema.options.toJSON.transform).to.exist;
|
||||||
let objToTransform = {ok: true, amPrivate: true};
|
const objToTransform = { ok: true, amPrivate: true };
|
||||||
let privatized = schema.options.toJSON.transform({}, objToTransform);
|
const privatized = schema.options.toJSON.transform({}, objToTransform);
|
||||||
|
|
||||||
expect(privatized).to.have.property('ok');
|
expect(privatized).to.have.property('ok');
|
||||||
expect(privatized).not.to.have.property('amPrivate');
|
expect(privatized).not.to.have.property('amPrivate');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('accepts a further transform function for toJSON', () => {
|
it('accepts a further transform function for toJSON', () => {
|
||||||
let options = {
|
const options = {
|
||||||
private: ['amPrivate'],
|
private: ['amPrivate'],
|
||||||
toJSONTransform: sandbox.stub().returns(true),
|
toJSONTransform: sandbox.stub().returns(true),
|
||||||
};
|
};
|
||||||
|
|
||||||
schema.plugin(baseModel, options);
|
schema.plugin(baseModel, options);
|
||||||
|
|
||||||
let objToTransform = {ok: true, amPrivate: true};
|
const objToTransform = { ok: true, amPrivate: true };
|
||||||
let doc = {doc: true};
|
const doc = { doc: true };
|
||||||
let privatized = schema.options.toJSON.transform(doc, objToTransform);
|
const privatized = schema.options.toJSON.transform(doc, objToTransform);
|
||||||
|
|
||||||
expect(privatized).to.equals(true);
|
expect(privatized).to.equals(true);
|
||||||
expect(options.toJSONTransform).to.be.calledWith(objToTransform, doc);
|
expect(options.toJSONTransform).to.be.calledWith(objToTransform, doc);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('accepts a transform function for sanitize', () => {
|
it('accepts a transform function for sanitize', () => {
|
||||||
let options = {
|
const options = {
|
||||||
private: ['amPrivate'],
|
private: ['amPrivate'],
|
||||||
sanitizeTransform: sandbox.stub().returns(true),
|
sanitizeTransform: sandbox.stub().returns(true),
|
||||||
};
|
};
|
||||||
@@ -95,8 +95,8 @@ describe('Base model plugin', () => {
|
|||||||
schema.plugin(baseModel, options);
|
schema.plugin(baseModel, options);
|
||||||
|
|
||||||
expect(schema.options.toJSON.transform).to.exist;
|
expect(schema.options.toJSON.transform).to.exist;
|
||||||
let objToSanitize = {ok: true, noUpdateForMe: true};
|
const objToSanitize = { ok: true, noUpdateForMe: true };
|
||||||
let sanitized = schema.statics.sanitize(objToSanitize);
|
const sanitized = schema.statics.sanitize(objToSanitize);
|
||||||
|
|
||||||
expect(sanitized).to.equals(true);
|
expect(sanitized).to.equals(true);
|
||||||
expect(options.sanitizeTransform).to.be.calledWith(objToSanitize);
|
expect(options.sanitizeTransform).to.be.calledWith(objToSanitize);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
describe('Collection Manipulators', () => {
|
describe('Collection Manipulators', () => {
|
||||||
describe('removeFromArray', () => {
|
describe('removeFromArray', () => {
|
||||||
it('removes element from array', () => {
|
it('removes element from array', () => {
|
||||||
let array = ['a', 'b', 'c', 'd'];
|
const array = ['a', 'b', 'c', 'd'];
|
||||||
|
|
||||||
removeFromArray(array, 'c');
|
removeFromArray(array, 'c');
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ describe('Collection Manipulators', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('removes object from array', () => {
|
it('removes object from array', () => {
|
||||||
let array = [
|
const array = [
|
||||||
{ id: 'a', foo: 'bar' },
|
{ id: 'a', foo: 'bar' },
|
||||||
{ id: 'b', foo: 'bar' },
|
{ id: 'b', foo: 'bar' },
|
||||||
{ id: 'c', foo: 'bar' },
|
{ id: 'c', foo: 'bar' },
|
||||||
@@ -28,7 +28,7 @@ describe('Collection Manipulators', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('does not change array if value is not found', () => {
|
it('does not change array if value is not found', () => {
|
||||||
let array = ['a', 'b', 'c', 'd'];
|
const array = ['a', 'b', 'c', 'd'];
|
||||||
|
|
||||||
removeFromArray(array, 'z');
|
removeFromArray(array, 'z');
|
||||||
|
|
||||||
@@ -40,15 +40,15 @@ describe('Collection Manipulators', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('returns the removed element', () => {
|
it('returns the removed element', () => {
|
||||||
let array = ['a', 'b', 'c'];
|
const array = ['a', 'b', 'c'];
|
||||||
|
|
||||||
let result = removeFromArray(array, 'b');
|
const result = removeFromArray(array, 'b');
|
||||||
|
|
||||||
expect(result).to.eql('b');
|
expect(result).to.eql('b');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the removed object element', () => {
|
it('returns the removed object element', () => {
|
||||||
let array = [
|
const array = [
|
||||||
{ id: 'a', foo: 'bar' },
|
{ id: 'a', foo: 'bar' },
|
||||||
{ id: 'b', foo: 'bar' },
|
{ id: 'b', foo: 'bar' },
|
||||||
{ id: 'c', foo: 'bar' },
|
{ id: 'c', foo: 'bar' },
|
||||||
@@ -56,31 +56,31 @@ describe('Collection Manipulators', () => {
|
|||||||
{ id: 'e', foo: 'bar' },
|
{ id: 'e', foo: 'bar' },
|
||||||
];
|
];
|
||||||
|
|
||||||
let result = removeFromArray(array, { id: 'c' });
|
const result = removeFromArray(array, { id: 'c' });
|
||||||
|
|
||||||
expect(result).to.eql({ id: 'c', foo: 'bar' });
|
expect(result).to.eql({ id: 'c', foo: 'bar' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false if item is not found', () => {
|
it('returns false if item is not found', () => {
|
||||||
let array = ['a', 'b', 'c'];
|
const array = ['a', 'b', 'c'];
|
||||||
|
|
||||||
let result = removeFromArray(array, 'z');
|
const result = removeFromArray(array, 'z');
|
||||||
|
|
||||||
expect(result).to.eql(false);
|
expect(result).to.eql(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('persists removal of element when mongoose document is saved', async () => {
|
it('persists removal of element when mongoose document is saved', async () => {
|
||||||
let schema = new mongoose.Schema({
|
const schema = new mongoose.Schema({
|
||||||
array: Array,
|
array: Array,
|
||||||
});
|
});
|
||||||
let Model = mongoose.model('ModelToTestRemoveFromArray', schema);
|
const Model = mongoose.model('ModelToTestRemoveFromArray', schema);
|
||||||
let model = await new Model({
|
const model = await new Model({
|
||||||
array: ['a', 'b', 'c'],
|
array: ['a', 'b', 'c'],
|
||||||
}).save(); // Initial creation
|
}).save(); // Initial creation
|
||||||
|
|
||||||
removeFromArray(model.array, 'b');
|
removeFromArray(model.array, 'b');
|
||||||
|
|
||||||
let savedModel = await model.save();
|
const savedModel = await model.save();
|
||||||
|
|
||||||
expect(savedModel.array).to.not.include('b');
|
expect(savedModel.array).to.not.include('b');
|
||||||
});
|
});
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -31,20 +31,20 @@ function getUser () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('emails', () => {
|
describe('emails', () => {
|
||||||
let pathToEmailLib = '../../../../website/server/libs/email';
|
const pathToEmailLib = '../../../../website/server/libs/email';
|
||||||
|
|
||||||
describe('getUserInfo', () => {
|
describe('getUserInfo', () => {
|
||||||
it('returns an empty object if no field request', () => {
|
it('returns an empty object if no field request', () => {
|
||||||
let attachEmail = requireAgain(pathToEmailLib);
|
const attachEmail = requireAgain(pathToEmailLib);
|
||||||
let getUserInfo = attachEmail.getUserInfo;
|
const { getUserInfo } = attachEmail;
|
||||||
expect(getUserInfo({}, [])).to.be.empty;
|
expect(getUserInfo({}, [])).to.be.empty;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns correct user data', () => {
|
it('returns correct user data', () => {
|
||||||
let attachEmail = requireAgain(pathToEmailLib);
|
const attachEmail = requireAgain(pathToEmailLib);
|
||||||
let getUserInfo = attachEmail.getUserInfo;
|
const { getUserInfo } = attachEmail;
|
||||||
let user = getUser();
|
const user = getUser();
|
||||||
let data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
|
const data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
|
||||||
|
|
||||||
expect(data).to.have.property('name', user.auth.local.username);
|
expect(data).to.have.property('name', user.auth.local.username);
|
||||||
expect(data).to.have.property('email', user.auth.local.email);
|
expect(data).to.have.property('email', user.auth.local.email);
|
||||||
@@ -53,13 +53,13 @@ describe('emails', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('returns correct user data [facebook users]', () => {
|
it('returns correct user data [facebook users]', () => {
|
||||||
let attachEmail = requireAgain(pathToEmailLib);
|
const attachEmail = requireAgain(pathToEmailLib);
|
||||||
let getUserInfo = attachEmail.getUserInfo;
|
const { getUserInfo } = attachEmail;
|
||||||
let user = getUser();
|
const user = getUser();
|
||||||
delete user.profile.name;
|
delete user.profile.name;
|
||||||
delete user.auth.local.email;
|
delete user.auth.local.email;
|
||||||
|
|
||||||
let data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
|
const data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
|
||||||
|
|
||||||
expect(data).to.have.property('name', user.auth.local.username);
|
expect(data).to.have.property('name', user.auth.local.username);
|
||||||
expect(data).to.have.property('email', user.auth.facebook.emails[0].value);
|
expect(data).to.have.property('email', user.auth.facebook.emails[0].value);
|
||||||
@@ -68,13 +68,13 @@ describe('emails', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('has fallbacks for missing data', () => {
|
it('has fallbacks for missing data', () => {
|
||||||
let attachEmail = requireAgain(pathToEmailLib);
|
const attachEmail = requireAgain(pathToEmailLib);
|
||||||
let getUserInfo = attachEmail.getUserInfo;
|
const { getUserInfo } = attachEmail;
|
||||||
let user = getUser();
|
const user = getUser();
|
||||||
delete user.auth.local.email;
|
delete user.auth.local.email;
|
||||||
delete user.auth.facebook;
|
delete user.auth.facebook;
|
||||||
|
|
||||||
let data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
|
const data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
|
||||||
|
|
||||||
expect(data).to.have.property('name', user.auth.local.username);
|
expect(data).to.have.property('name', user.auth.local.username);
|
||||||
expect(data).not.to.have.property('email');
|
expect(data).not.to.have.property('email');
|
||||||
@@ -85,18 +85,18 @@ describe('emails', () => {
|
|||||||
|
|
||||||
describe('getGroupUrl', () => {
|
describe('getGroupUrl', () => {
|
||||||
it('returns correct url if group is the tavern', () => {
|
it('returns correct url if group is the tavern', () => {
|
||||||
let getGroupUrl = require(pathToEmailLib).getGroupUrl;
|
const { getGroupUrl } = require(pathToEmailLib); // eslint-disable-line import/no-dynamic-require, max-len
|
||||||
expect(getGroupUrl({_id: TAVERN_ID, type: 'guild'})).to.eql('/groups/tavern');
|
expect(getGroupUrl({ _id: TAVERN_ID, type: 'guild' })).to.eql('/groups/tavern');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns correct url if group is a guild', () => {
|
it('returns correct url if group is a guild', () => {
|
||||||
let getGroupUrl = require(pathToEmailLib).getGroupUrl;
|
const { getGroupUrl } = require(pathToEmailLib); // eslint-disable-line import/no-dynamic-require, max-len
|
||||||
expect(getGroupUrl({_id: 'random _id', type: 'guild'})).to.eql('/groups/guild/random _id');
|
expect(getGroupUrl({ _id: 'random _id', type: 'guild' })).to.eql('/groups/guild/random _id');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns correct url if group is a party', () => {
|
it('returns correct url if group is a party', () => {
|
||||||
let getGroupUrl = require(pathToEmailLib).getGroupUrl;
|
const { getGroupUrl } = require(pathToEmailLib); // eslint-disable-line import/no-dynamic-require, max-len
|
||||||
expect(getGroupUrl({_id: 'random _id', type: 'party'})).to.eql('party');
|
expect(getGroupUrl({ _id: 'random _id', type: 'party' })).to.eql('party');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -111,10 +111,10 @@ describe('emails', () => {
|
|||||||
|
|
||||||
it('can send a txn email to one recipient', () => {
|
it('can send a txn email to one recipient', () => {
|
||||||
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(true);
|
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(true);
|
||||||
let attachEmail = requireAgain(pathToEmailLib);
|
const attachEmail = requireAgain(pathToEmailLib);
|
||||||
let sendTxnEmail = attachEmail.sendTxn;
|
const sendTxnEmail = attachEmail.sendTxn;
|
||||||
let emailType = 'an email type';
|
const emailType = 'an email type';
|
||||||
let mailingInfo = {
|
const mailingInfo = {
|
||||||
name: 'my name',
|
name: 'my name',
|
||||||
email: 'my@email',
|
email: 'my@email',
|
||||||
};
|
};
|
||||||
@@ -125,9 +125,7 @@ describe('emails', () => {
|
|||||||
body: {
|
body: {
|
||||||
data: {
|
data: {
|
||||||
emailType: sinon.match.same(emailType),
|
emailType: sinon.match.same(emailType),
|
||||||
to: sinon.match((value) => {
|
to: sinon.match(value => Array.isArray(value) && value[0].name === mailingInfo.name, 'matches mailing info array'),
|
||||||
return Array.isArray(value) && value[0].name === mailingInfo.name;
|
|
||||||
}, 'matches mailing info array'),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
@@ -135,10 +133,10 @@ describe('emails', () => {
|
|||||||
|
|
||||||
it('does not send email if address is missing', () => {
|
it('does not send email if address is missing', () => {
|
||||||
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(true);
|
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(true);
|
||||||
let attachEmail = requireAgain(pathToEmailLib);
|
const attachEmail = requireAgain(pathToEmailLib);
|
||||||
let sendTxnEmail = attachEmail.sendTxn;
|
const sendTxnEmail = attachEmail.sendTxn;
|
||||||
let emailType = 'an email type';
|
const emailType = 'an email type';
|
||||||
let mailingInfo = {
|
const mailingInfo = {
|
||||||
name: 'my name',
|
name: 'my name',
|
||||||
// email: 'my@email',
|
// email: 'my@email',
|
||||||
};
|
};
|
||||||
@@ -149,10 +147,10 @@ describe('emails', () => {
|
|||||||
|
|
||||||
it('uses getUserInfo in case of user data', () => {
|
it('uses getUserInfo in case of user data', () => {
|
||||||
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(true);
|
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(true);
|
||||||
let attachEmail = requireAgain(pathToEmailLib);
|
const attachEmail = requireAgain(pathToEmailLib);
|
||||||
let sendTxnEmail = attachEmail.sendTxn;
|
const sendTxnEmail = attachEmail.sendTxn;
|
||||||
let emailType = 'an email type';
|
const emailType = 'an email type';
|
||||||
let mailingInfo = getUser();
|
const mailingInfo = getUser();
|
||||||
|
|
||||||
sendTxnEmail(mailingInfo, emailType);
|
sendTxnEmail(mailingInfo, emailType);
|
||||||
expect(got.post).to.be.calledWith('undefined/job', sinon.match({
|
expect(got.post).to.be.calledWith('undefined/job', sinon.match({
|
||||||
@@ -168,28 +166,24 @@ describe('emails', () => {
|
|||||||
|
|
||||||
it('sends email with some default variables', () => {
|
it('sends email with some default variables', () => {
|
||||||
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(true);
|
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(true);
|
||||||
let attachEmail = requireAgain(pathToEmailLib);
|
const attachEmail = requireAgain(pathToEmailLib);
|
||||||
let sendTxnEmail = attachEmail.sendTxn;
|
const sendTxnEmail = attachEmail.sendTxn;
|
||||||
let emailType = 'an email type';
|
const emailType = 'an email type';
|
||||||
let mailingInfo = {
|
const mailingInfo = {
|
||||||
name: 'my name',
|
name: 'my name',
|
||||||
email: 'my@email',
|
email: 'my@email',
|
||||||
};
|
};
|
||||||
let variables = [1, 2, 3];
|
const variables = [1, 2, 3];
|
||||||
|
|
||||||
sendTxnEmail(mailingInfo, emailType, variables);
|
sendTxnEmail(mailingInfo, emailType, variables);
|
||||||
expect(got.post).to.be.calledWith('undefined/job', sinon.match({
|
expect(got.post).to.be.calledWith('undefined/job', sinon.match({
|
||||||
json: true,
|
json: true,
|
||||||
body: {
|
body: {
|
||||||
data: {
|
data: {
|
||||||
variables: sinon.match((value) => {
|
variables: sinon.match(value => value[0].name === 'BASE_URL', 'matches variables'),
|
||||||
return value[0].name === 'BASE_URL';
|
personalVariables: sinon.match(value => value[0].rcpt === mailingInfo.email
|
||||||
}, 'matches variables'),
|
&& value[0].vars[0].name === 'RECIPIENT_NAME'
|
||||||
personalVariables: sinon.match((value) => {
|
&& value[0].vars[1].name === 'RECIPIENT_UNSUB_URL', 'matches personal variables'),
|
||||||
return value[0].rcpt === mailingInfo.email &&
|
|
||||||
value[0].vars[0].name === 'RECIPIENT_NAME' &&
|
|
||||||
value[0].vars[1].name === 'RECIPIENT_UNSUB_URL';
|
|
||||||
}, 'matches personal variables'),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import {
|
|||||||
|
|
||||||
describe('encryption', () => {
|
describe('encryption', () => {
|
||||||
it('can encrypt and decrypt', () => {
|
it('can encrypt and decrypt', () => {
|
||||||
let data = 'some secret text';
|
const data = 'some secret text';
|
||||||
let encrypted = encrypt(data);
|
const encrypted = encrypt(data);
|
||||||
let decrypted = decrypt(encrypted);
|
const decrypted = decrypt(encrypted);
|
||||||
|
|
||||||
expect(encrypted).not.to.equal(data);
|
expect(encrypted).not.to.equal(data);
|
||||||
expect(data).to.equal(decrypted);
|
expect(data).to.equal(decrypted);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import i18n from '../../../../website/common/script/i18n';
|
|||||||
describe('Custom Errors', () => {
|
describe('Custom Errors', () => {
|
||||||
describe('CustomError', () => {
|
describe('CustomError', () => {
|
||||||
it('is an instance of Error', () => {
|
it('is an instance of Error', () => {
|
||||||
let customError = new CustomError();
|
const customError = new CustomError();
|
||||||
|
|
||||||
expect(customError).to.be.an.instanceOf(Error);
|
expect(customError).to.be.an.instanceOf(Error);
|
||||||
});
|
});
|
||||||
@@ -20,25 +20,25 @@ describe('Custom Errors', () => {
|
|||||||
|
|
||||||
describe('NotAuthorized', () => {
|
describe('NotAuthorized', () => {
|
||||||
it('is an instance of CustomError', () => {
|
it('is an instance of CustomError', () => {
|
||||||
let notAuthorizedError = new NotAuthorized();
|
const notAuthorizedError = new NotAuthorized();
|
||||||
|
|
||||||
expect(notAuthorizedError).to.be.an.instanceOf(CustomError);
|
expect(notAuthorizedError).to.be.an.instanceOf(CustomError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('it returns an http code of 401', () => {
|
it('it returns an http code of 401', () => {
|
||||||
let notAuthorizedError = new NotAuthorized();
|
const notAuthorizedError = new NotAuthorized();
|
||||||
|
|
||||||
expect(notAuthorizedError.httpCode).to.eql(401);
|
expect(notAuthorizedError.httpCode).to.eql(401);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns a default message', () => {
|
it('returns a default message', () => {
|
||||||
let notAuthorizedError = new NotAuthorized();
|
const notAuthorizedError = new NotAuthorized();
|
||||||
|
|
||||||
expect(notAuthorizedError.message).to.eql('Not authorized.');
|
expect(notAuthorizedError.message).to.eql('Not authorized.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows a custom message', () => {
|
it('allows a custom message', () => {
|
||||||
let notAuthorizedError = new NotAuthorized('Custom Error Message');
|
const notAuthorizedError = new NotAuthorized('Custom Error Message');
|
||||||
|
|
||||||
expect(notAuthorizedError.message).to.eql('Custom Error Message');
|
expect(notAuthorizedError.message).to.eql('Custom Error Message');
|
||||||
});
|
});
|
||||||
@@ -46,25 +46,25 @@ describe('Custom Errors', () => {
|
|||||||
|
|
||||||
describe('NotFound', () => {
|
describe('NotFound', () => {
|
||||||
it('is an instance of CustomError', () => {
|
it('is an instance of CustomError', () => {
|
||||||
let notAuthorizedError = new NotFound();
|
const notAuthorizedError = new NotFound();
|
||||||
|
|
||||||
expect(notAuthorizedError).to.be.an.instanceOf(CustomError);
|
expect(notAuthorizedError).to.be.an.instanceOf(CustomError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('it returns an http code of 404', () => {
|
it('it returns an http code of 404', () => {
|
||||||
let notAuthorizedError = new NotFound();
|
const notAuthorizedError = new NotFound();
|
||||||
|
|
||||||
expect(notAuthorizedError.httpCode).to.eql(404);
|
expect(notAuthorizedError.httpCode).to.eql(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns a default message', () => {
|
it('returns a default message', () => {
|
||||||
let notAuthorizedError = new NotFound();
|
const notAuthorizedError = new NotFound();
|
||||||
|
|
||||||
expect(notAuthorizedError.message).to.eql('Not found.');
|
expect(notAuthorizedError.message).to.eql('Not found.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows a custom message', () => {
|
it('allows a custom message', () => {
|
||||||
let notAuthorizedError = new NotFound('Custom Error Message');
|
const notAuthorizedError = new NotFound('Custom Error Message');
|
||||||
|
|
||||||
expect(notAuthorizedError.message).to.eql('Custom Error Message');
|
expect(notAuthorizedError.message).to.eql('Custom Error Message');
|
||||||
});
|
});
|
||||||
@@ -89,25 +89,25 @@ describe('Custom Errors', () => {
|
|||||||
|
|
||||||
describe('BadRequest', () => {
|
describe('BadRequest', () => {
|
||||||
it('is an instance of CustomError', () => {
|
it('is an instance of CustomError', () => {
|
||||||
let badRequestError = new BadRequest();
|
const badRequestError = new BadRequest();
|
||||||
|
|
||||||
expect(badRequestError).to.be.an.instanceOf(CustomError);
|
expect(badRequestError).to.be.an.instanceOf(CustomError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('it returns an http code of 401', () => {
|
it('it returns an http code of 401', () => {
|
||||||
let badRequestError = new BadRequest();
|
const badRequestError = new BadRequest();
|
||||||
|
|
||||||
expect(badRequestError.httpCode).to.eql(400);
|
expect(badRequestError.httpCode).to.eql(400);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns a default message', () => {
|
it('returns a default message', () => {
|
||||||
let badRequestError = new BadRequest();
|
const badRequestError = new BadRequest();
|
||||||
|
|
||||||
expect(badRequestError.message).to.eql('Bad request.');
|
expect(badRequestError.message).to.eql('Bad request.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows a custom message', () => {
|
it('allows a custom message', () => {
|
||||||
let badRequestError = new BadRequest('Custom Error Message');
|
const badRequestError = new BadRequest('Custom Error Message');
|
||||||
|
|
||||||
expect(badRequestError.message).to.eql('Custom Error Message');
|
expect(badRequestError.message).to.eql('Custom Error Message');
|
||||||
});
|
});
|
||||||
@@ -115,25 +115,25 @@ describe('Custom Errors', () => {
|
|||||||
|
|
||||||
describe('InternalServerError', () => {
|
describe('InternalServerError', () => {
|
||||||
it('is an instance of CustomError', () => {
|
it('is an instance of CustomError', () => {
|
||||||
let internalServerError = new InternalServerError();
|
const internalServerError = new InternalServerError();
|
||||||
|
|
||||||
expect(internalServerError).to.be.an.instanceOf(CustomError);
|
expect(internalServerError).to.be.an.instanceOf(CustomError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('it returns an http code of 500', () => {
|
it('it returns an http code of 500', () => {
|
||||||
let internalServerError = new InternalServerError();
|
const internalServerError = new InternalServerError();
|
||||||
|
|
||||||
expect(internalServerError.httpCode).to.eql(500);
|
expect(internalServerError.httpCode).to.eql(500);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns a default message', () => {
|
it('returns a default message', () => {
|
||||||
let internalServerError = new InternalServerError();
|
const internalServerError = new InternalServerError();
|
||||||
|
|
||||||
expect(internalServerError.message).to.eql('An unexpected error occurred.');
|
expect(internalServerError.message).to.eql('An unexpected error occurred.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows a custom message', () => {
|
it('allows a custom message', () => {
|
||||||
let internalServerError = new InternalServerError('Custom Error Message');
|
const internalServerError = new InternalServerError('Custom Error Message');
|
||||||
|
|
||||||
expect(internalServerError.message).to.eql('Custom Error Message');
|
expect(internalServerError.message).to.eql('Custom Error Message');
|
||||||
});
|
});
|
||||||
|
|||||||
60
test/api/unit/libs/highlightMentions.js
Normal file
60
test/api/unit/libs/highlightMentions.js
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import mongoose from 'mongoose';
|
||||||
|
import {
|
||||||
|
highlightMentions,
|
||||||
|
} from '../../../../website/server/libs/highlightMentions';
|
||||||
|
|
||||||
|
describe('highlightMentions', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const mockFind = {
|
||||||
|
select () {
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
lean () {
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
exec () {
|
||||||
|
return Promise.resolve([{
|
||||||
|
auth: { local: { username: 'user' } }, _id: '111',
|
||||||
|
}, { auth: { local: { username: 'user2' } }, _id: '222' }, { auth: { local: { username: 'user3' } }, _id: '333' }, { auth: { local: { username: 'user-dash' } }, _id: '444' }, { auth: { local: { username: 'user_underscore' } }, _id: '555' },
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
sinon.stub(mongoose.Model, 'find').returns(mockFind);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
sinon.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('doesn\'t change text without mentions', async () => {
|
||||||
|
const text = 'some chat text';
|
||||||
|
const result = await highlightMentions(text);
|
||||||
|
expect(result[0]).to.equal(text);
|
||||||
|
});
|
||||||
|
it('highlights existing users', async () => {
|
||||||
|
const text = '@user: message';
|
||||||
|
const result = await highlightMentions(text);
|
||||||
|
expect(result[0]).to.equal('[@user](/profile/111): message');
|
||||||
|
});
|
||||||
|
it('highlights special characters', async () => {
|
||||||
|
const text = '@user-dash: message @user_underscore';
|
||||||
|
const result = await highlightMentions(text);
|
||||||
|
expect(result[0]).to.equal('[@user-dash](/profile/444): message [@user_underscore](/profile/555)');
|
||||||
|
});
|
||||||
|
it('doesn\'t highlight nonexisting users', async () => {
|
||||||
|
const text = '@nouser message';
|
||||||
|
const result = await highlightMentions(text);
|
||||||
|
expect(result[0]).to.equal('@nouser message');
|
||||||
|
});
|
||||||
|
it('highlights multiple existing users', async () => {
|
||||||
|
const text = '@user message (@user2) @user3 @user';
|
||||||
|
const result = await highlightMentions(text);
|
||||||
|
expect(result[0]).to.equal('[@user](/profile/111) message ([@user2](/profile/222)) [@user3](/profile/333) [@user](/profile/111)');
|
||||||
|
});
|
||||||
|
it('doesn\'t highlight more than 5 users', async () => {
|
||||||
|
const text = '@user @user2 @user3 @user4 @user5 @user6';
|
||||||
|
const result = await highlightMentions(text);
|
||||||
|
expect(result[0]).to.equal(text);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -5,11 +5,11 @@ import {
|
|||||||
} from '../../../../website/server/libs/i18n';
|
} from '../../../../website/server/libs/i18n';
|
||||||
|
|
||||||
describe('i18n', () => {
|
describe('i18n', () => {
|
||||||
let listOfLocales = approvedLanguages.sort();
|
const listOfLocales = approvedLanguages.sort();
|
||||||
|
|
||||||
describe('translations', () => {
|
describe('translations', () => {
|
||||||
it('includes a translation object for each locale', () => {
|
it('includes a translation object for each locale', () => {
|
||||||
listOfLocales.forEach((locale) => {
|
listOfLocales.forEach(locale => {
|
||||||
expect(translations[locale]).to.be.an('object');
|
expect(translations[locale]).to.be.an('object');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import winston from 'winston';
|
|||||||
import logger from '../../../../website/server/libs/logger';
|
import logger from '../../../../website/server/libs/logger';
|
||||||
import {
|
import {
|
||||||
NotFound,
|
NotFound,
|
||||||
} from '../../../../website/server/libs//errors';
|
} from '../../../../website/server/libs/errors';
|
||||||
|
|
||||||
describe('logger', () => {
|
describe('logger', () => {
|
||||||
let logSpy;
|
let logSpy;
|
||||||
@@ -34,7 +34,7 @@ describe('logger', () => {
|
|||||||
|
|
||||||
context('error object', () => {
|
context('error object', () => {
|
||||||
it('logs the stack and the err data', () => {
|
it('logs the stack and the err data', () => {
|
||||||
let errInstance = new Error('An error.');
|
const errInstance = new Error('An error.');
|
||||||
logger.error(errInstance, {
|
logger.error(errInstance, {
|
||||||
data: 1,
|
data: 1,
|
||||||
}, 2, 3);
|
}, 2, 3);
|
||||||
@@ -45,13 +45,13 @@ describe('logger', () => {
|
|||||||
errInstance.stack,
|
errInstance.stack,
|
||||||
{ data: 1, fullError: errInstance },
|
{ data: 1, fullError: errInstance },
|
||||||
2,
|
2,
|
||||||
3
|
3,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('logs the stack and the err data with it\'s own fullError property', () => {
|
it('logs the stack and the err data with it\'s own fullError property', () => {
|
||||||
let errInstance = new Error('An error.');
|
const errInstance = new Error('An error.');
|
||||||
let anotherError = new Error('another error');
|
const anotherError = new Error('another error');
|
||||||
|
|
||||||
logger.error(errInstance, {
|
logger.error(errInstance, {
|
||||||
data: 1,
|
data: 1,
|
||||||
@@ -64,12 +64,12 @@ describe('logger', () => {
|
|||||||
errInstance.stack,
|
errInstance.stack,
|
||||||
{ data: 1, fullError: anotherError },
|
{ data: 1, fullError: anotherError },
|
||||||
2,
|
2,
|
||||||
3
|
3,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('logs the error when errorData is null', () => {
|
it('logs the error when errorData is null', () => {
|
||||||
let errInstance = new Error('An error.');
|
const errInstance = new Error('An error.');
|
||||||
|
|
||||||
logger.error(errInstance, null, 2, 3);
|
logger.error(errInstance, null, 2, 3);
|
||||||
|
|
||||||
@@ -79,12 +79,12 @@ describe('logger', () => {
|
|||||||
errInstance.stack,
|
errInstance.stack,
|
||||||
null,
|
null,
|
||||||
2,
|
2,
|
||||||
3
|
3,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('logs the error when errorData is not an object', () => {
|
it('logs the error when errorData is not an object', () => {
|
||||||
let errInstance = new Error('An error.');
|
const errInstance = new Error('An error.');
|
||||||
|
|
||||||
logger.error(errInstance, true, 2, 3);
|
logger.error(errInstance, true, 2, 3);
|
||||||
|
|
||||||
@@ -94,12 +94,12 @@ describe('logger', () => {
|
|||||||
errInstance.stack,
|
errInstance.stack,
|
||||||
true,
|
true,
|
||||||
2,
|
2,
|
||||||
3
|
3,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('logs the error when errorData does not include isHandledError property', () => {
|
it('logs the error when errorData does not include isHandledError property', () => {
|
||||||
let errInstance = new Error('An error.');
|
const errInstance = new Error('An error.');
|
||||||
|
|
||||||
logger.error(errInstance, { httpCode: 400 }, 2, 3);
|
logger.error(errInstance, { httpCode: 400 }, 2, 3);
|
||||||
|
|
||||||
@@ -109,12 +109,12 @@ describe('logger', () => {
|
|||||||
errInstance.stack,
|
errInstance.stack,
|
||||||
{ httpCode: 400, fullError: errInstance },
|
{ httpCode: 400, fullError: errInstance },
|
||||||
2,
|
2,
|
||||||
3
|
3,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('logs the error when errorData includes isHandledError property but is a 500 error', () => {
|
it('logs the error when errorData includes isHandledError property but is a 500 error', () => {
|
||||||
let errInstance = new Error('An error.');
|
const errInstance = new Error('An error.');
|
||||||
|
|
||||||
logger.error(errInstance, {
|
logger.error(errInstance, {
|
||||||
isHandledError: true,
|
isHandledError: true,
|
||||||
@@ -127,12 +127,12 @@ describe('logger', () => {
|
|||||||
errInstance.stack,
|
errInstance.stack,
|
||||||
{ httpCode: 502, isHandledError: true, fullError: errInstance },
|
{ httpCode: 502, isHandledError: true, fullError: errInstance },
|
||||||
2,
|
2,
|
||||||
3
|
3,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('logs a warning when errorData includes isHandledError property and is not a 500 error', () => {
|
it('logs a warning when errorData includes isHandledError property and is not a 500 error', () => {
|
||||||
let errInstance = new Error('An error.');
|
const errInstance = new Error('An error.');
|
||||||
|
|
||||||
logger.error(errInstance, {
|
logger.error(errInstance, {
|
||||||
isHandledError: true,
|
isHandledError: true,
|
||||||
@@ -145,12 +145,12 @@ describe('logger', () => {
|
|||||||
errInstance.stack,
|
errInstance.stack,
|
||||||
{ httpCode: 403, isHandledError: true, fullError: errInstance },
|
{ httpCode: 403, isHandledError: true, fullError: errInstance },
|
||||||
2,
|
2,
|
||||||
3
|
3,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('logs additional data from a CustomError', () => {
|
it('logs additional data from a CustomError', () => {
|
||||||
let errInstance = new NotFound('An error.');
|
const errInstance = new NotFound('An error.');
|
||||||
|
|
||||||
errInstance.customField = 'Some interesting data';
|
errInstance.customField = 'Some interesting data';
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ describe('logger', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
2,
|
2,
|
||||||
3
|
3,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
|
|
||||||
|
import moment from 'moment';
|
||||||
import {
|
import {
|
||||||
encrypt,
|
encrypt,
|
||||||
} from '../../../../website/server/libs/encryption';
|
} from '../../../../website/server/libs/encryption';
|
||||||
import moment from 'moment';
|
|
||||||
import {
|
import {
|
||||||
generateUser,
|
generateUser,
|
||||||
} from '../../../helpers/api-integration/v3';
|
} from '../../../helpers/api-integration/v3';
|
||||||
@@ -20,11 +20,11 @@ import {
|
|||||||
describe('Password Utilities', () => {
|
describe('Password Utilities', () => {
|
||||||
describe('compare', () => {
|
describe('compare', () => {
|
||||||
it('can compare a correct password hashed with SHA1', async () => {
|
it('can compare a correct password hashed with SHA1', async () => {
|
||||||
let textPassword = 'mySecretPassword';
|
const textPassword = 'mySecretPassword';
|
||||||
let salt = sha1MakeSalt();
|
const salt = sha1MakeSalt();
|
||||||
let hashedPassword = sha1EncryptPassword(textPassword, salt);
|
const hashedPassword = sha1EncryptPassword(textPassword, salt);
|
||||||
|
|
||||||
let user = {
|
const user = {
|
||||||
auth: {
|
auth: {
|
||||||
local: {
|
local: {
|
||||||
hashed_password: hashedPassword,
|
hashed_password: hashedPassword,
|
||||||
@@ -34,16 +34,16 @@ describe('Password Utilities', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let isValidPassword = await compare(user, textPassword);
|
const isValidPassword = await compare(user, textPassword);
|
||||||
expect(isValidPassword).to.eql(true);
|
expect(isValidPassword).to.eql(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can compare an invalid password hashed with SHA1', async () => {
|
it('can compare an invalid password hashed with SHA1', async () => {
|
||||||
let textPassword = 'mySecretPassword';
|
const textPassword = 'mySecretPassword';
|
||||||
let salt = sha1MakeSalt();
|
const salt = sha1MakeSalt();
|
||||||
let hashedPassword = sha1EncryptPassword(textPassword, salt);
|
const hashedPassword = sha1EncryptPassword(textPassword, salt);
|
||||||
|
|
||||||
let user = {
|
const user = {
|
||||||
auth: {
|
auth: {
|
||||||
local: {
|
local: {
|
||||||
hashed_password: hashedPassword,
|
hashed_password: hashedPassword,
|
||||||
@@ -53,15 +53,15 @@ describe('Password Utilities', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let isValidPassword = await compare(user, 'wrongPassword');
|
const isValidPassword = await compare(user, 'wrongPassword');
|
||||||
expect(isValidPassword).to.eql(false);
|
expect(isValidPassword).to.eql(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can compare a correct password hashed with bcrypt', async () => {
|
it('can compare a correct password hashed with bcrypt', async () => {
|
||||||
let textPassword = 'mySecretPassword';
|
const textPassword = 'mySecretPassword';
|
||||||
let hashedPassword = await bcryptHash(textPassword);
|
const hashedPassword = await bcryptHash(textPassword);
|
||||||
|
|
||||||
let user = {
|
const user = {
|
||||||
auth: {
|
auth: {
|
||||||
local: {
|
local: {
|
||||||
hashed_password: hashedPassword,
|
hashed_password: hashedPassword,
|
||||||
@@ -70,15 +70,15 @@ describe('Password Utilities', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let isValidPassword = await compare(user, textPassword);
|
const isValidPassword = await compare(user, textPassword);
|
||||||
expect(isValidPassword).to.eql(true);
|
expect(isValidPassword).to.eql(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can compare an invalid password hashed with bcrypt', async () => {
|
it('can compare an invalid password hashed with bcrypt', async () => {
|
||||||
let textPassword = 'mySecretPassword';
|
const textPassword = 'mySecretPassword';
|
||||||
let hashedPassword = await bcryptHash(textPassword);
|
const hashedPassword = await bcryptHash(textPassword);
|
||||||
|
|
||||||
let user = {
|
const user = {
|
||||||
auth: {
|
auth: {
|
||||||
local: {
|
local: {
|
||||||
hashed_password: hashedPassword,
|
hashed_password: hashedPassword,
|
||||||
@@ -87,7 +87,7 @@ describe('Password Utilities', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let isValidPassword = await compare(user, 'wrongPassword');
|
const isValidPassword = await compare(user, 'wrongPassword');
|
||||||
expect(isValidPassword).to.eql(false);
|
expect(isValidPassword).to.eql(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -101,18 +101,18 @@ describe('Password Utilities', () => {
|
|||||||
|
|
||||||
it('throws an error if passwordToCheck is missing', async () => {
|
it('throws an error if passwordToCheck is missing', async () => {
|
||||||
try {
|
try {
|
||||||
await compare({a: true});
|
await compare({ a: true });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.toString()).to.equal('Error: user and passwordToCheck are required parameters.');
|
expect(e.toString()).to.equal('Error: user and passwordToCheck are required parameters.');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('defaults to SHA1 encryption if salt is provided', async () => {
|
it('defaults to SHA1 encryption if salt is provided', async () => {
|
||||||
let textPassword = 'mySecretPassword';
|
const textPassword = 'mySecretPassword';
|
||||||
let salt = sha1MakeSalt();
|
const salt = sha1MakeSalt();
|
||||||
let hashedPassword = sha1EncryptPassword(textPassword, salt);
|
const hashedPassword = sha1EncryptPassword(textPassword, salt);
|
||||||
|
|
||||||
let user = {
|
const user = {
|
||||||
auth: {
|
auth: {
|
||||||
local: {
|
local: {
|
||||||
hashed_password: hashedPassword,
|
hashed_password: hashedPassword,
|
||||||
@@ -122,7 +122,7 @@ describe('Password Utilities', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let isValidPassword = await compare(user, textPassword);
|
const isValidPassword = await compare(user, textPassword);
|
||||||
expect(isValidPassword).to.eql(true);
|
expect(isValidPassword).to.eql(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -141,29 +141,29 @@ describe('Password Utilities', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('returns true if comparing the same password', async () => {
|
it('returns true if comparing the same password', async () => {
|
||||||
let textPassword = 'mySecretPassword';
|
const textPassword = 'mySecretPassword';
|
||||||
let hashedPassword = await bcryptHash(textPassword);
|
const hashedPassword = await bcryptHash(textPassword);
|
||||||
|
|
||||||
let isValidPassword = await bcryptCompare(textPassword, hashedPassword);
|
const isValidPassword = await bcryptCompare(textPassword, hashedPassword);
|
||||||
expect(isValidPassword).to.eql(true);
|
expect(isValidPassword).to.eql(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns true if comparing a different password', async () => {
|
it('returns true if comparing a different password', async () => {
|
||||||
let textPassword = 'mySecretPassword';
|
const textPassword = 'mySecretPassword';
|
||||||
let hashedPassword = await bcryptHash(textPassword);
|
const hashedPassword = await bcryptHash(textPassword);
|
||||||
|
|
||||||
let isValidPassword = await bcryptCompare('anotherPassword', hashedPassword);
|
const isValidPassword = await bcryptCompare('anotherPassword', hashedPassword);
|
||||||
expect(isValidPassword).to.eql(false);
|
expect(isValidPassword).to.eql(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('convertToBcrypt', () => {
|
describe('convertToBcrypt', () => {
|
||||||
it('converts an user password hashed with sha1 to bcrypt', async () => {
|
it('converts an user password hashed with sha1 to bcrypt', async () => {
|
||||||
let textPassword = 'mySecretPassword';
|
const textPassword = 'mySecretPassword';
|
||||||
let salt = sha1MakeSalt();
|
const salt = sha1MakeSalt();
|
||||||
let hashedPassword = sha1EncryptPassword(textPassword, salt);
|
const hashedPassword = sha1EncryptPassword(textPassword, salt);
|
||||||
|
|
||||||
let user = {
|
const user = {
|
||||||
auth: {
|
auth: {
|
||||||
local: {
|
local: {
|
||||||
hashed_password: hashedPassword,
|
hashed_password: hashedPassword,
|
||||||
@@ -178,7 +178,7 @@ describe('Password Utilities', () => {
|
|||||||
expect(user.auth.local.passwordHashMethod).to.equal('bcrypt');
|
expect(user.auth.local.passwordHashMethod).to.equal('bcrypt');
|
||||||
expect(user.auth.local.hashed_password).to.be.a.string;
|
expect(user.auth.local.hashed_password).to.be.a.string;
|
||||||
|
|
||||||
let isValidPassword = await compare(user, textPassword);
|
const isValidPassword = await compare(user, textPassword);
|
||||||
expect(isValidPassword).to.eql(true);
|
expect(isValidPassword).to.eql(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ describe('Password Utilities', () => {
|
|||||||
|
|
||||||
it('throws an error if plainTextPassword is missing', async () => {
|
it('throws an error if plainTextPassword is missing', async () => {
|
||||||
try {
|
try {
|
||||||
await convertToBcrypt({a: true});
|
await convertToBcrypt({ a: true });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.toString()).to.equal('Error: user and plainTextPassword are required parameters.');
|
expect(e.toString()).to.equal('Error: user and plainTextPassword are required parameters.');
|
||||||
}
|
}
|
||||||
@@ -201,18 +201,18 @@ describe('Password Utilities', () => {
|
|||||||
|
|
||||||
describe('validatePasswordResetCodeAndFindUser', () => {
|
describe('validatePasswordResetCodeAndFindUser', () => {
|
||||||
it('returns false if the code is missing', async () => {
|
it('returns false if the code is missing', async () => {
|
||||||
let res = await validatePasswordResetCodeAndFindUser();
|
const res = await validatePasswordResetCodeAndFindUser();
|
||||||
expect(res).to.equal(false);
|
expect(res).to.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false if the code is invalid json', async () => {
|
it('returns false if the code is invalid json', async () => {
|
||||||
let res = await validatePasswordResetCodeAndFindUser('invalid json');
|
const res = await validatePasswordResetCodeAndFindUser('invalid json');
|
||||||
expect(res).to.equal(false);
|
expect(res).to.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false if the code cannot be decrypted', async () => {
|
it('returns false if the code cannot be decrypted', async () => {
|
||||||
let user = await generateUser();
|
const user = await generateUser();
|
||||||
let res = await validatePasswordResetCodeAndFindUser(JSON.stringify({ // not encrypted
|
const res = await validatePasswordResetCodeAndFindUser(JSON.stringify({ // not encrypted
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
expiresAt: new Date(),
|
expiresAt: new Date(),
|
||||||
}));
|
}));
|
||||||
@@ -220,71 +220,71 @@ describe('Password Utilities', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('returns false if the code is expired', async () => {
|
it('returns false if the code is expired', async () => {
|
||||||
let user = await generateUser();
|
const user = await generateUser();
|
||||||
|
|
||||||
let code = encrypt(JSON.stringify({
|
const code = encrypt(JSON.stringify({
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
expiresAt: moment().subtract({minutes: 1}),
|
expiresAt: moment().subtract({ minutes: 1 }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await user.update({
|
await user.update({
|
||||||
'auth.local.passwordResetCode': code,
|
'auth.local.passwordResetCode': code,
|
||||||
});
|
});
|
||||||
|
|
||||||
let res = await validatePasswordResetCodeAndFindUser(code);
|
const res = await validatePasswordResetCodeAndFindUser(code);
|
||||||
expect(res).to.equal(false);
|
expect(res).to.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false if the user does not exist', async () => {
|
it('returns false if the user does not exist', async () => {
|
||||||
let res = await validatePasswordResetCodeAndFindUser(encrypt(JSON.stringify({
|
const res = await validatePasswordResetCodeAndFindUser(encrypt(JSON.stringify({
|
||||||
userId: Date.now().toString(),
|
userId: Date.now().toString(),
|
||||||
expiresAt: moment().add({days: 1}),
|
expiresAt: moment().add({ days: 1 }),
|
||||||
})));
|
})));
|
||||||
expect(res).to.equal(false);
|
expect(res).to.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false if the user has no local auth', async () => {
|
it('returns false if the user has no local auth', async () => {
|
||||||
let user = await generateUser({
|
const user = await generateUser({
|
||||||
auth: {
|
auth: {
|
||||||
facebook: {},
|
facebook: {},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
let res = await validatePasswordResetCodeAndFindUser(encrypt(JSON.stringify({
|
const res = await validatePasswordResetCodeAndFindUser(encrypt(JSON.stringify({
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
expiresAt: moment().add({days: 1}),
|
expiresAt: moment().add({ days: 1 }),
|
||||||
})));
|
})));
|
||||||
expect(res).to.equal(false);
|
expect(res).to.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false if the code doesn\'t match the one saved at user.auth.passwordResetCode', async () => {
|
it('returns false if the code doesn\'t match the one saved at user.auth.passwordResetCode', async () => {
|
||||||
let user = await generateUser();
|
const user = await generateUser();
|
||||||
|
|
||||||
let code = encrypt(JSON.stringify({
|
const code = encrypt(JSON.stringify({
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
expiresAt: moment().add({days: 1}),
|
expiresAt: moment().add({ days: 1 }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await user.update({
|
await user.update({
|
||||||
'auth.local.passwordResetCode': 'invalid',
|
'auth.local.passwordResetCode': 'invalid',
|
||||||
});
|
});
|
||||||
|
|
||||||
let res = await validatePasswordResetCodeAndFindUser(code);
|
const res = await validatePasswordResetCodeAndFindUser(code);
|
||||||
expect(res).to.equal(false);
|
expect(res).to.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the user if the password reset code is valid', async () => {
|
it('returns the user if the password reset code is valid', async () => {
|
||||||
let user = await generateUser();
|
const user = await generateUser();
|
||||||
|
|
||||||
let code = encrypt(JSON.stringify({
|
const code = encrypt(JSON.stringify({
|
||||||
userId: user._id,
|
userId: user._id,
|
||||||
expiresAt: moment().add({days: 1}),
|
expiresAt: moment().add({ days: 1 }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await user.update({
|
await user.update({
|
||||||
'auth.local.passwordResetCode': code,
|
'auth.local.passwordResetCode': code,
|
||||||
});
|
});
|
||||||
|
|
||||||
let res = await validatePasswordResetCodeAndFindUser(code);
|
const res = await validatePasswordResetCodeAndFindUser(code);
|
||||||
expect(res).not.to.equal(false);
|
expect(res).not.to.equal(false);
|
||||||
expect(res._id).to.equal(user._id);
|
expect(res._id).to.equal(user._id);
|
||||||
});
|
});
|
||||||
@@ -293,8 +293,8 @@ describe('Password Utilities', () => {
|
|||||||
describe('bcrypt', () => {
|
describe('bcrypt', () => {
|
||||||
describe('Hash', () => {
|
describe('Hash', () => {
|
||||||
it('returns a hashed string', async () => {
|
it('returns a hashed string', async () => {
|
||||||
let textPassword = 'mySecretPassword';
|
const textPassword = 'mySecretPassword';
|
||||||
let hashedPassword = await bcryptHash(textPassword);
|
const hashedPassword = await bcryptHash(textPassword);
|
||||||
|
|
||||||
expect(hashedPassword).to.be.a.string;
|
expect(hashedPassword).to.be.a.string;
|
||||||
});
|
});
|
||||||
@@ -302,18 +302,18 @@ describe('Password Utilities', () => {
|
|||||||
|
|
||||||
describe('Compare', () => {
|
describe('Compare', () => {
|
||||||
it('returns true if comparing the same password', async () => {
|
it('returns true if comparing the same password', async () => {
|
||||||
let textPassword = 'mySecretPassword';
|
const textPassword = 'mySecretPassword';
|
||||||
let hashedPassword = await bcryptHash(textPassword);
|
const hashedPassword = await bcryptHash(textPassword);
|
||||||
|
|
||||||
let isValidPassword = await bcryptCompare(textPassword, hashedPassword);
|
const isValidPassword = await bcryptCompare(textPassword, hashedPassword);
|
||||||
expect(isValidPassword).to.eql(true);
|
expect(isValidPassword).to.eql(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns true if comparing a different password', async () => {
|
it('returns true if comparing a different password', async () => {
|
||||||
let textPassword = 'mySecretPassword';
|
const textPassword = 'mySecretPassword';
|
||||||
let hashedPassword = await bcryptHash(textPassword);
|
const hashedPassword = await bcryptHash(textPassword);
|
||||||
|
|
||||||
let isValidPassword = await bcryptCompare('anotherPassword', hashedPassword);
|
const isValidPassword = await bcryptCompare('anotherPassword', hashedPassword);
|
||||||
expect(isValidPassword).to.eql(false);
|
expect(isValidPassword).to.eql(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -322,19 +322,19 @@ describe('Password Utilities', () => {
|
|||||||
describe('SHA1', () => {
|
describe('SHA1', () => {
|
||||||
describe('Encrypt', () => {
|
describe('Encrypt', () => {
|
||||||
it('always encrypt the same password to the same value when using the same salt', () => {
|
it('always encrypt the same password to the same value when using the same salt', () => {
|
||||||
let textPassword = 'mySecretPassword';
|
const textPassword = 'mySecretPassword';
|
||||||
let salt = sha1MakeSalt();
|
const salt = sha1MakeSalt();
|
||||||
let encryptedPassword = sha1EncryptPassword(textPassword, salt);
|
const encryptedPassword = sha1EncryptPassword(textPassword, salt);
|
||||||
|
|
||||||
expect(sha1EncryptPassword(textPassword, salt)).to.eql(encryptedPassword);
|
expect(sha1EncryptPassword(textPassword, salt)).to.eql(encryptedPassword);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('never encrypt the same password to the same value when using a different salt', () => {
|
it('never encrypt the same password to the same value when using a different salt', () => {
|
||||||
let textPassword = 'mySecretPassword';
|
const textPassword = 'mySecretPassword';
|
||||||
let aSalt = sha1MakeSalt();
|
const aSalt = sha1MakeSalt();
|
||||||
let anotherSalt = sha1MakeSalt();
|
const anotherSalt = sha1MakeSalt();
|
||||||
let anEncryptedPassword = sha1EncryptPassword(textPassword, aSalt);
|
const anEncryptedPassword = sha1EncryptPassword(textPassword, aSalt);
|
||||||
let anotherEncryptedPassword = sha1EncryptPassword(textPassword, anotherSalt);
|
const anotherEncryptedPassword = sha1EncryptPassword(textPassword, anotherSalt);
|
||||||
|
|
||||||
expect(anEncryptedPassword).not.to.eql(anotherEncryptedPassword);
|
expect(anEncryptedPassword).not.to.eql(anotherEncryptedPassword);
|
||||||
});
|
});
|
||||||
@@ -342,14 +342,14 @@ describe('Password Utilities', () => {
|
|||||||
|
|
||||||
describe('Make Salt', () => {
|
describe('Make Salt', () => {
|
||||||
it('creates a salt with length 10 by default', () => {
|
it('creates a salt with length 10 by default', () => {
|
||||||
let salt = sha1MakeSalt();
|
const salt = sha1MakeSalt();
|
||||||
|
|
||||||
expect(salt.length).to.eql(10);
|
expect(salt.length).to.eql(10);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can create a salt of any length', () => {
|
it('can create a salt of any length', () => {
|
||||||
let length = 24;
|
const length = 24;
|
||||||
let salt = sha1MakeSalt(length);
|
const salt = sha1MakeSalt(length);
|
||||||
|
|
||||||
expect(salt.length).to.eql(length);
|
expect(salt.length).to.eql(length);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,19 +2,20 @@ import moment from 'moment';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
generateGroup,
|
generateGroup,
|
||||||
} from '../../../../../helpers/api-unit.helper.js';
|
} from '../../../../../helpers/api-unit.helper';
|
||||||
import { model as User } from '../../../../../../website/server/models/user';
|
import { model as User } from '../../../../../../website/server/models/user';
|
||||||
import amzLib from '../../../../../../website/server/libs/payments/amazon';
|
import amzLib from '../../../../../../website/server/libs/payments/amazon';
|
||||||
import payments from '../../../../../../website/server/libs/payments/payments';
|
import payments from '../../../../../../website/server/libs/payments/payments';
|
||||||
import common from '../../../../../../website/common';
|
import common from '../../../../../../website/common';
|
||||||
import { createNonLeaderGroupMember } from '../paymentHelpers';
|
import { createNonLeaderGroupMember } from '../paymentHelpers';
|
||||||
|
|
||||||
const i18n = common.i18n;
|
const { i18n } = common;
|
||||||
|
|
||||||
describe('Amazon Payments - Cancel Subscription', () => {
|
describe('Amazon Payments - Cancel Subscription', () => {
|
||||||
const subKey = 'basic_3mo';
|
const subKey = 'basic_3mo';
|
||||||
|
|
||||||
let user, group, headers, billingAgreementId, subscriptionBlock, subscriptionLength;
|
let user; let group; let headers; let billingAgreementId; let subscriptionBlock; let
|
||||||
|
subscriptionLength;
|
||||||
let getBillingAgreementDetailsSpy;
|
let getBillingAgreementDetailsSpy;
|
||||||
let paymentCancelSubscriptionSpy;
|
let paymentCancelSubscriptionSpy;
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
|
|||||||
getBillingAgreementDetailsSpy = sinon.stub(amzLib, 'getBillingAgreementDetails')
|
getBillingAgreementDetailsSpy = sinon.stub(amzLib, 'getBillingAgreementDetails')
|
||||||
.resolves({
|
.resolves({
|
||||||
BillingAgreementDetails: {
|
BillingAgreementDetails: {
|
||||||
BillingAgreementStatus: {State: 'Open'},
|
BillingAgreementStatus: { State: 'Open' },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -81,7 +82,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
|
|||||||
getBillingAgreementDetailsSpy = sinon.stub(amzLib, 'getBillingAgreementDetails');
|
getBillingAgreementDetailsSpy = sinon.stub(amzLib, 'getBillingAgreementDetails');
|
||||||
getBillingAgreementDetailsSpy.resolves({
|
getBillingAgreementDetailsSpy.resolves({
|
||||||
BillingAgreementDetails: {
|
BillingAgreementDetails: {
|
||||||
BillingAgreementStatus: {State: 'Closed'},
|
BillingAgreementStatus: { State: 'Closed' },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -89,7 +90,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
|
|||||||
paymentCancelSubscriptionSpy.resolves({});
|
paymentCancelSubscriptionSpy.resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(() => {
|
||||||
amzLib.getBillingAgreementDetails.restore();
|
amzLib.getBillingAgreementDetails.restore();
|
||||||
payments.cancelSubscription.restore();
|
payments.cancelSubscription.restore();
|
||||||
});
|
});
|
||||||
@@ -97,7 +98,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
|
|||||||
it('should throw an error if we are missing a subscription', async () => {
|
it('should throw an error if we are missing a subscription', async () => {
|
||||||
user.purchased.plan.customerId = undefined;
|
user.purchased.plan.customerId = undefined;
|
||||||
|
|
||||||
await expect(amzLib.cancelSubscription({user}))
|
await expect(amzLib.cancelSubscription({ user }))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -108,7 +109,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
|
|||||||
it('should cancel a user subscription', async () => {
|
it('should cancel a user subscription', async () => {
|
||||||
billingAgreementId = user.purchased.plan.customerId;
|
billingAgreementId = user.purchased.plan.customerId;
|
||||||
|
|
||||||
await amzLib.cancelSubscription({user, headers});
|
await amzLib.cancelSubscription({ user, headers });
|
||||||
|
|
||||||
expectAmazonCancelUserSubscriptionSpy();
|
expectAmazonCancelUserSubscriptionSpy();
|
||||||
expectAmazonStubs();
|
expectAmazonStubs();
|
||||||
@@ -117,10 +118,10 @@ describe('Amazon Payments - Cancel Subscription', () => {
|
|||||||
it('should close a user subscription if amazon not closed', async () => {
|
it('should close a user subscription if amazon not closed', async () => {
|
||||||
amzLib.getBillingAgreementDetails.restore();
|
amzLib.getBillingAgreementDetails.restore();
|
||||||
expectBillingAggreementDetailSpy();
|
expectBillingAggreementDetailSpy();
|
||||||
let closeBillingAgreementSpy = sinon.stub(amzLib, 'closeBillingAgreement').resolves({});
|
const closeBillingAgreementSpy = sinon.stub(amzLib, 'closeBillingAgreement').resolves({});
|
||||||
billingAgreementId = user.purchased.plan.customerId;
|
billingAgreementId = user.purchased.plan.customerId;
|
||||||
|
|
||||||
await amzLib.cancelSubscription({user, headers});
|
await amzLib.cancelSubscription({ user, headers });
|
||||||
|
|
||||||
expectAmazonStubs();
|
expectAmazonStubs();
|
||||||
expect(closeBillingAgreementSpy).to.be.calledOnce;
|
expect(closeBillingAgreementSpy).to.be.calledOnce;
|
||||||
@@ -132,7 +133,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if group is not found', async () => {
|
it('should throw an error if group is not found', async () => {
|
||||||
await expect(amzLib.cancelSubscription({user, groupId: 'fake-id'}))
|
await expect(amzLib.cancelSubscription({ user, groupId: 'fake-id' }))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 404,
|
httpCode: 404,
|
||||||
name: 'NotFound',
|
name: 'NotFound',
|
||||||
@@ -141,9 +142,9 @@ describe('Amazon Payments - Cancel Subscription', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if user is not group leader', async () => {
|
it('should throw an error if user is not group leader', async () => {
|
||||||
let nonLeader = await createNonLeaderGroupMember(group);
|
const nonLeader = await createNonLeaderGroupMember(group);
|
||||||
|
|
||||||
await expect(amzLib.cancelSubscription({user: nonLeader, groupId: group._id}))
|
await expect(amzLib.cancelSubscription({ user: nonLeader, groupId: group._id }))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -154,7 +155,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
|
|||||||
it('should cancel a group subscription', async () => {
|
it('should cancel a group subscription', async () => {
|
||||||
billingAgreementId = group.purchased.plan.customerId;
|
billingAgreementId = group.purchased.plan.customerId;
|
||||||
|
|
||||||
await amzLib.cancelSubscription({user, groupId: group._id, headers});
|
await amzLib.cancelSubscription({ user, groupId: group._id, headers });
|
||||||
|
|
||||||
expectAmazonCancelGroupSubscriptionSpy(group._id);
|
expectAmazonCancelGroupSubscriptionSpy(group._id);
|
||||||
expectAmazonStubs();
|
expectAmazonStubs();
|
||||||
@@ -163,10 +164,10 @@ describe('Amazon Payments - Cancel Subscription', () => {
|
|||||||
it('should close a group subscription if amazon not closed', async () => {
|
it('should close a group subscription if amazon not closed', async () => {
|
||||||
amzLib.getBillingAgreementDetails.restore();
|
amzLib.getBillingAgreementDetails.restore();
|
||||||
expectBillingAggreementDetailSpy();
|
expectBillingAggreementDetailSpy();
|
||||||
let closeBillingAgreementSpy = sinon.stub(amzLib, 'closeBillingAgreement').resolves({});
|
const closeBillingAgreementSpy = sinon.stub(amzLib, 'closeBillingAgreement').resolves({});
|
||||||
billingAgreementId = group.purchased.plan.customerId;
|
billingAgreementId = group.purchased.plan.customerId;
|
||||||
|
|
||||||
await amzLib.cancelSubscription({user, groupId: group._id, headers});
|
await amzLib.cancelSubscription({ user, groupId: group._id, headers });
|
||||||
|
|
||||||
expectAmazonStubs();
|
expectAmazonStubs();
|
||||||
expect(closeBillingAgreementSpy).to.be.calledOnce;
|
expect(closeBillingAgreementSpy).to.be.calledOnce;
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ import amzLib from '../../../../../../website/server/libs/payments/amazon';
|
|||||||
import payments from '../../../../../../website/server/libs/payments/payments';
|
import payments from '../../../../../../website/server/libs/payments/payments';
|
||||||
import common from '../../../../../../website/common';
|
import common from '../../../../../../website/common';
|
||||||
|
|
||||||
const i18n = common.i18n;
|
const { i18n } = common;
|
||||||
|
|
||||||
describe('Amazon Payments - Checkout', () => {
|
describe('Amazon Payments - Checkout', () => {
|
||||||
const subKey = 'basic_3mo';
|
const subKey = 'basic_3mo';
|
||||||
let user, orderReferenceId, headers;
|
let user; let orderReferenceId; let
|
||||||
|
headers;
|
||||||
let setOrderReferenceDetailsSpy;
|
let setOrderReferenceDetailsSpy;
|
||||||
let confirmOrderReferenceSpy;
|
let confirmOrderReferenceSpy;
|
||||||
let authorizeSpy;
|
let authorizeSpy;
|
||||||
@@ -62,7 +63,7 @@ describe('Amazon Payments - Checkout', () => {
|
|||||||
expect(closeOrderReferenceSpy).to.be.calledWith({ AmazonOrderReferenceId: orderReferenceId });
|
expect(closeOrderReferenceSpy).to.be.calledWith({ AmazonOrderReferenceId: orderReferenceId });
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(() => {
|
||||||
user = new User();
|
user = new User();
|
||||||
headers = {};
|
headers = {};
|
||||||
orderReferenceId = 'orderReferenceId';
|
orderReferenceId = 'orderReferenceId';
|
||||||
@@ -88,7 +89,7 @@ describe('Amazon Payments - Checkout', () => {
|
|||||||
sinon.stub(common, 'uuid').returns('uuid-generated');
|
sinon.stub(common, 'uuid').returns('uuid-generated');
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(() => {
|
||||||
amzLib.setOrderReferenceDetails.restore();
|
amzLib.setOrderReferenceDetails.restore();
|
||||||
amzLib.confirmOrderReference.restore();
|
amzLib.confirmOrderReference.restore();
|
||||||
amzLib.authorize.restore();
|
amzLib.authorize.restore();
|
||||||
@@ -101,7 +102,7 @@ describe('Amazon Payments - Checkout', () => {
|
|||||||
function expectBuyGemsStub (paymentMethod, gift) {
|
function expectBuyGemsStub (paymentMethod, gift) {
|
||||||
expect(paymentBuyGemsStub).to.be.calledOnce;
|
expect(paymentBuyGemsStub).to.be.calledOnce;
|
||||||
|
|
||||||
let expectedArgs = {
|
const expectedArgs = {
|
||||||
user,
|
user,
|
||||||
paymentMethod,
|
paymentMethod,
|
||||||
headers,
|
headers,
|
||||||
@@ -112,7 +113,7 @@ describe('Amazon Payments - Checkout', () => {
|
|||||||
|
|
||||||
it('should purchase gems', async () => {
|
it('should purchase gems', async () => {
|
||||||
sinon.stub(user, 'canGetGems').resolves(true);
|
sinon.stub(user, 'canGetGems').resolves(true);
|
||||||
await amzLib.checkout({user, orderReferenceId, headers});
|
await amzLib.checkout({ user, orderReferenceId, headers });
|
||||||
|
|
||||||
expectBuyGemsStub(amzLib.constants.PAYMENT_METHOD);
|
expectBuyGemsStub(amzLib.constants.PAYMENT_METHOD);
|
||||||
expectAmazonStubs();
|
expectAmazonStubs();
|
||||||
@@ -121,9 +122,9 @@ describe('Amazon Payments - Checkout', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should error if gem amount is too low', async () => {
|
it('should error if gem amount is too low', async () => {
|
||||||
let receivingUser = new User();
|
const receivingUser = new User();
|
||||||
receivingUser.save();
|
receivingUser.save();
|
||||||
let gift = {
|
const gift = {
|
||||||
type: 'gems',
|
type: 'gems',
|
||||||
gems: {
|
gems: {
|
||||||
amount: 0,
|
amount: 0,
|
||||||
@@ -131,7 +132,9 @@ describe('Amazon Payments - Checkout', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
await expect(amzLib.checkout({gift, user, orderReferenceId, headers}))
|
await expect(amzLib.checkout({
|
||||||
|
gift, user, orderReferenceId, headers,
|
||||||
|
}))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 400,
|
httpCode: 400,
|
||||||
message: 'Amount must be at least 1.',
|
message: 'Amount must be at least 1.',
|
||||||
@@ -141,18 +144,19 @@ describe('Amazon Payments - Checkout', () => {
|
|||||||
|
|
||||||
it('should error if user cannot get gems gems', async () => {
|
it('should error if user cannot get gems gems', async () => {
|
||||||
sinon.stub(user, 'canGetGems').resolves(false);
|
sinon.stub(user, 'canGetGems').resolves(false);
|
||||||
await expect(amzLib.checkout({user, orderReferenceId, headers})).to.eventually.be.rejected.and.to.eql({
|
await expect(amzLib.checkout({ user, orderReferenceId, headers }))
|
||||||
httpCode: 401,
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
message: i18n.t('groupPolicyCannotGetGems'),
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
message: i18n.t('groupPolicyCannotGetGems'),
|
||||||
});
|
name: 'NotAuthorized',
|
||||||
|
});
|
||||||
user.canGetGems.restore();
|
user.canGetGems.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should gift gems', async () => {
|
it('should gift gems', async () => {
|
||||||
let receivingUser = new User();
|
const receivingUser = new User();
|
||||||
await receivingUser.save();
|
await receivingUser.save();
|
||||||
let gift = {
|
const gift = {
|
||||||
type: 'gems',
|
type: 'gems',
|
||||||
uuid: receivingUser._id,
|
uuid: receivingUser._id,
|
||||||
gems: {
|
gems: {
|
||||||
@@ -160,16 +164,18 @@ describe('Amazon Payments - Checkout', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
amount = 16 / 4;
|
amount = 16 / 4;
|
||||||
await amzLib.checkout({gift, user, orderReferenceId, headers});
|
await amzLib.checkout({
|
||||||
|
gift, user, orderReferenceId, headers,
|
||||||
|
});
|
||||||
|
|
||||||
expectBuyGemsStub(amzLib.constants.PAYMENT_METHOD_GIFT, gift);
|
expectBuyGemsStub(amzLib.constants.PAYMENT_METHOD_GIFT, gift);
|
||||||
expectAmazonStubs();
|
expectAmazonStubs();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should gift a subscription', async () => {
|
it('should gift a subscription', async () => {
|
||||||
let receivingUser = new User();
|
const receivingUser = new User();
|
||||||
receivingUser.save();
|
receivingUser.save();
|
||||||
let gift = {
|
const gift = {
|
||||||
type: 'subscription',
|
type: 'subscription',
|
||||||
subscription: {
|
subscription: {
|
||||||
key: subKey,
|
key: subKey,
|
||||||
@@ -178,7 +184,9 @@ describe('Amazon Payments - Checkout', () => {
|
|||||||
};
|
};
|
||||||
amount = common.content.subscriptionBlocks[subKey].price;
|
amount = common.content.subscriptionBlocks[subKey].price;
|
||||||
|
|
||||||
await amzLib.checkout({user, orderReferenceId, headers, gift});
|
await amzLib.checkout({
|
||||||
|
user, orderReferenceId, headers, gift,
|
||||||
|
});
|
||||||
|
|
||||||
gift.member = receivingUser;
|
gift.member = receivingUser;
|
||||||
expect(paymentCreateSubscritionStub).to.be.calledOnce;
|
expect(paymentCreateSubscritionStub).to.be.calledOnce;
|
||||||
|
|||||||
@@ -2,18 +2,19 @@ import cc from 'coupon-code';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
generateGroup,
|
generateGroup,
|
||||||
} from '../../../../../helpers/api-unit.helper.js';
|
} from '../../../../../helpers/api-unit.helper';
|
||||||
import { model as User } from '../../../../../../website/server/models/user';
|
import { model as User } from '../../../../../../website/server/models/user';
|
||||||
import { model as Coupon } from '../../../../../../website/server/models/coupon';
|
import { model as Coupon } from '../../../../../../website/server/models/coupon';
|
||||||
import amzLib from '../../../../../../website/server/libs/payments/amazon';
|
import amzLib from '../../../../../../website/server/libs/payments/amazon';
|
||||||
import payments from '../../../../../../website/server/libs/payments/payments';
|
import payments from '../../../../../../website/server/libs/payments/payments';
|
||||||
import common from '../../../../../../website/common';
|
import common from '../../../../../../website/common';
|
||||||
|
|
||||||
const i18n = common.i18n;
|
const { i18n } = common;
|
||||||
|
|
||||||
describe('Amazon Payments - Subscribe', () => {
|
describe('Amazon Payments - Subscribe', () => {
|
||||||
const subKey = 'basic_3mo';
|
const subKey = 'basic_3mo';
|
||||||
let user, group, amount, billingAgreementId, sub, coupon, groupId, headers;
|
let user; let group; let amount; let billingAgreementId; let sub; let coupon; let groupId; let
|
||||||
|
headers;
|
||||||
let amazonSetBillingAgreementDetailsSpy;
|
let amazonSetBillingAgreementDetailsSpy;
|
||||||
let amazonConfirmBillingAgreementSpy;
|
let amazonConfirmBillingAgreementSpy;
|
||||||
let amazonAuthorizeOnBillingAgreementSpy;
|
let amazonAuthorizeOnBillingAgreementSpy;
|
||||||
@@ -60,7 +61,7 @@ describe('Amazon Payments - Subscribe', () => {
|
|||||||
sinon.stub(common, 'uuid').returns('uuid-generated');
|
sinon.stub(common, 'uuid').returns('uuid-generated');
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(() => {
|
||||||
amzLib.setBillingAgreementDetails.restore();
|
amzLib.setBillingAgreementDetails.restore();
|
||||||
amzLib.confirmBillingAgreement.restore();
|
amzLib.confirmBillingAgreement.restore();
|
||||||
amzLib.authorizeOnBillingAgreement.restore();
|
amzLib.authorizeOnBillingAgreement.restore();
|
||||||
@@ -168,7 +169,7 @@ describe('Amazon Payments - Subscribe', () => {
|
|||||||
sub.key = 'google_6mo';
|
sub.key = 'google_6mo';
|
||||||
coupon = 'example-coupon';
|
coupon = 'example-coupon';
|
||||||
|
|
||||||
let couponModel = new Coupon();
|
const couponModel = new Coupon();
|
||||||
couponModel.event = 'google_6mo';
|
couponModel.event = 'google_6mo';
|
||||||
await couponModel.save();
|
await couponModel.save();
|
||||||
|
|
||||||
@@ -195,9 +196,9 @@ describe('Amazon Payments - Subscribe', () => {
|
|||||||
sub.key = 'google_6mo';
|
sub.key = 'google_6mo';
|
||||||
coupon = 'example-coupon';
|
coupon = 'example-coupon';
|
||||||
|
|
||||||
let couponModel = new Coupon();
|
const couponModel = new Coupon();
|
||||||
couponModel.event = 'google_6mo';
|
couponModel.event = 'google_6mo';
|
||||||
let updatedCouponModel = await couponModel.save();
|
const updatedCouponModel = await couponModel.save();
|
||||||
|
|
||||||
sinon.stub(cc, 'validate').returns(updatedCouponModel._id);
|
sinon.stub(cc, 'validate').returns(updatedCouponModel._id);
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,17 @@ import uuid from 'uuid';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
generateGroup,
|
generateGroup,
|
||||||
} from '../../../../../helpers/api-unit.helper.js';
|
} from '../../../../../helpers/api-unit.helper';
|
||||||
import { model as User } from '../../../../../../website/server/models/user';
|
import { model as User } from '../../../../../../website/server/models/user';
|
||||||
import { model as Group } from '../../../../../../website/server/models/group';
|
import { model as Group } from '../../../../../../website/server/models/group';
|
||||||
import amzLib from '../../../../../../website/server/libs/payments/amazon';
|
import amzLib from '../../../../../../website/server/libs/payments/amazon';
|
||||||
import payments from '../../../../../../website/server/libs/payments/payments';
|
import payments from '../../../../../../website/server/libs/payments/payments';
|
||||||
|
|
||||||
describe('#upgradeGroupPlan', () => {
|
describe('#upgradeGroupPlan', () => {
|
||||||
let spy, data, user, group, uuidString;
|
let spy; let data; let user; let group; let
|
||||||
|
uuidString;
|
||||||
|
|
||||||
beforeEach(async function () {
|
beforeEach(async () => {
|
||||||
user = new User();
|
user = new User();
|
||||||
user.profile.name = 'sender';
|
user.profile.name = 'sender';
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ describe('#upgradeGroupPlan', () => {
|
|||||||
data.sub.quantity = 3;
|
data.sub.quantity = 3;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(() => {
|
||||||
amzLib.authorizeOnBillingAgreement.restore();
|
amzLib.authorizeOnBillingAgreement.restore();
|
||||||
uuid.v4.restore();
|
uuid.v4.restore();
|
||||||
});
|
});
|
||||||
@@ -55,7 +56,7 @@ describe('#upgradeGroupPlan', () => {
|
|||||||
data.paymentMethod = amzLib.constants.PAYMENT_METHOD;
|
data.paymentMethod = amzLib.constants.PAYMENT_METHOD;
|
||||||
await payments.createSubscription(data);
|
await payments.createSubscription(data);
|
||||||
|
|
||||||
let updatedGroup = await Group.findById(group._id).exec();
|
const updatedGroup = await Group.findById(group._id).exec();
|
||||||
|
|
||||||
updatedGroup.memberCount += 1;
|
updatedGroup.memberCount += 1;
|
||||||
await updatedGroup.save();
|
await updatedGroup.save();
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
import iapModule from '../../../../../website/server/libs/inAppPurchases';
|
import moment from 'moment';
|
||||||
import payments from '../../../../../website/server/libs/payments/payments';
|
import payments from '../../../../../website/server/libs/payments/payments';
|
||||||
import applePayments from '../../../../../website/server/libs/payments/apple';
|
import applePayments from '../../../../../website/server/libs/payments/apple';
|
||||||
import iap from '../../../../../website/server/libs/inAppPurchases';
|
import iap from '../../../../../website/server/libs/inAppPurchases';
|
||||||
import {model as User} from '../../../../../website/server/models/user';
|
import { model as User } from '../../../../../website/server/models/user';
|
||||||
import common from '../../../../../website/common';
|
import common from '../../../../../website/common';
|
||||||
import moment from 'moment';
|
import { mockFindById, restoreFindById } from '../../../../helpers/mongoose.helper';
|
||||||
import {mockFindById, restoreFindById} from '../../../../helpers/mongoose.helper';
|
|
||||||
|
|
||||||
const i18n = common.i18n;
|
const { i18n } = common;
|
||||||
|
|
||||||
describe('Apple Payments', () => {
|
describe('Apple Payments', () => {
|
||||||
let subKey = 'basic_3mo';
|
const subKey = 'basic_3mo';
|
||||||
|
|
||||||
describe('verifyGemPurchase', () => {
|
describe('verifyGemPurchase', () => {
|
||||||
let sku, user, token, receipt, headers;
|
let sku; let user; let token; let receipt; let
|
||||||
let iapSetupStub, iapValidateStub, iapIsValidatedStub, paymentBuyGemsStub, iapGetPurchaseDataStub;
|
headers;
|
||||||
|
let iapSetupStub; let iapValidateStub; let iapIsValidatedStub; let paymentBuyGemsStub; let
|
||||||
|
iapGetPurchaseDataStub;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
token = 'testToken';
|
token = 'testToken';
|
||||||
@@ -24,33 +25,34 @@ describe('Apple Payments', () => {
|
|||||||
receipt = `{"token": "${token}", "productId": "${sku}"}`;
|
receipt = `{"token": "${token}", "productId": "${sku}"}`;
|
||||||
headers = {};
|
headers = {};
|
||||||
|
|
||||||
iapSetupStub = sinon.stub(iapModule, 'setup')
|
iapSetupStub = sinon.stub(iap, 'setup')
|
||||||
.resolves();
|
.resolves();
|
||||||
iapValidateStub = sinon.stub(iapModule, 'validate')
|
iapValidateStub = sinon.stub(iap, 'validate')
|
||||||
.resolves({});
|
.resolves({});
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
|
||||||
.returns(true);
|
.returns(true);
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
|
||||||
.returns([{productId: 'com.habitrpg.ios.Habitica.21gems',
|
.returns([{
|
||||||
transactionId: token,
|
productId: 'com.habitrpg.ios.Habitica.21gems',
|
||||||
|
transactionId: token,
|
||||||
}]);
|
}]);
|
||||||
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').resolves({});
|
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
iapModule.setup.restore();
|
iap.setup.restore();
|
||||||
iapModule.validate.restore();
|
iap.validate.restore();
|
||||||
iapModule.isValidated.restore();
|
iap.isValidated.restore();
|
||||||
iapModule.getPurchaseData.restore();
|
iap.getPurchaseData.restore();
|
||||||
payments.buyGems.restore();
|
payments.buyGems.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if receipt is invalid', async () => {
|
it('should throw an error if receipt is invalid', async () => {
|
||||||
iapModule.isValidated.restore();
|
iap.isValidated.restore();
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
|
||||||
.returns(false);
|
.returns(false);
|
||||||
|
|
||||||
await expect(applePayments.verifyGemPurchase({user, receipt, headers}))
|
await expect(applePayments.verifyGemPurchase({ user, receipt, headers }))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -60,9 +62,9 @@ describe('Apple Payments', () => {
|
|||||||
|
|
||||||
it('should throw an error if getPurchaseData is invalid', async () => {
|
it('should throw an error if getPurchaseData is invalid', async () => {
|
||||||
iapGetPurchaseDataStub.restore();
|
iapGetPurchaseDataStub.restore();
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData').returns([]);
|
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData').returns([]);
|
||||||
|
|
||||||
await expect(applePayments.verifyGemPurchase({user, receipt, headers}))
|
await expect(applePayments.verifyGemPurchase({ user, receipt, headers }))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -72,7 +74,7 @@ describe('Apple Payments', () => {
|
|||||||
|
|
||||||
it('errors if the user cannot purchase gems', async () => {
|
it('errors if the user cannot purchase gems', async () => {
|
||||||
sinon.stub(user, 'canGetGems').resolves(false);
|
sinon.stub(user, 'canGetGems').resolves(false);
|
||||||
await expect(applePayments.verifyGemPurchase({user, receipt, headers}))
|
await expect(applePayments.verifyGemPurchase({ user, receipt, headers }))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -85,12 +87,13 @@ describe('Apple Payments', () => {
|
|||||||
it('errors if amount does not exist', async () => {
|
it('errors if amount does not exist', async () => {
|
||||||
sinon.stub(user, 'canGetGems').resolves(true);
|
sinon.stub(user, 'canGetGems').resolves(true);
|
||||||
iapGetPurchaseDataStub.restore();
|
iapGetPurchaseDataStub.restore();
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
|
||||||
.returns([{productId: 'badProduct',
|
.returns([{
|
||||||
transactionId: token,
|
productId: 'badProduct',
|
||||||
|
transactionId: token,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
await expect(applePayments.verifyGemPurchase({user, receipt, headers}))
|
await expect(applePayments.verifyGemPurchase({ user, receipt, headers }))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -126,13 +129,14 @@ describe('Apple Payments', () => {
|
|||||||
gemsCanPurchase.forEach(gemTest => {
|
gemsCanPurchase.forEach(gemTest => {
|
||||||
it(`purchases ${gemTest.productId} gems`, async () => {
|
it(`purchases ${gemTest.productId} gems`, async () => {
|
||||||
iapGetPurchaseDataStub.restore();
|
iapGetPurchaseDataStub.restore();
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
|
||||||
.returns([{productId: gemTest.productId,
|
.returns([{
|
||||||
transactionId: token,
|
productId: gemTest.productId,
|
||||||
|
transactionId: token,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
sinon.stub(user, 'canGetGems').resolves(true);
|
sinon.stub(user, 'canGetGems').resolves(true);
|
||||||
await applePayments.verifyGemPurchase({user, receipt, headers});
|
await applePayments.verifyGemPurchase({ user, receipt, headers });
|
||||||
|
|
||||||
expect(iapSetupStub).to.be.calledOnce;
|
expect(iapSetupStub).to.be.calledOnce;
|
||||||
expect(iapValidateStub).to.be.calledOnce;
|
expect(iapValidateStub).to.be.calledOnce;
|
||||||
@@ -160,13 +164,16 @@ describe('Apple Payments', () => {
|
|||||||
mockFindById(receivingUser);
|
mockFindById(receivingUser);
|
||||||
|
|
||||||
iapGetPurchaseDataStub.restore();
|
iapGetPurchaseDataStub.restore();
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
|
||||||
.returns([{productId: gemsCanPurchase[0].productId,
|
.returns([{
|
||||||
transactionId: token,
|
productId: gemsCanPurchase[0].productId,
|
||||||
|
transactionId: token,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const gift = {uuid: receivingUser._id};
|
const gift = { uuid: receivingUser._id };
|
||||||
await applePayments.verifyGemPurchase({user, gift, receipt, headers});
|
await applePayments.verifyGemPurchase({
|
||||||
|
user, gift, receipt, headers,
|
||||||
|
});
|
||||||
|
|
||||||
expect(iapSetupStub).to.be.calledOnce;
|
expect(iapSetupStub).to.be.calledOnce;
|
||||||
expect(iapValidateStub).to.be.calledOnce;
|
expect(iapValidateStub).to.be.calledOnce;
|
||||||
@@ -187,8 +194,11 @@ describe('Apple Payments', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('subscribe', () => {
|
describe('subscribe', () => {
|
||||||
let sub, sku, user, token, receipt, headers, nextPaymentProcessing;
|
let sub; let sku; let user; let token; let receipt; let headers; let
|
||||||
let iapSetupStub, iapValidateStub, iapIsValidatedStub, paymentsCreateSubscritionStub, iapGetPurchaseDataStub;
|
nextPaymentProcessing;
|
||||||
|
let iapSetupStub; let iapValidateStub; let iapIsValidatedStub;
|
||||||
|
let paymentsCreateSubscritionStub; let
|
||||||
|
iapGetPurchaseDataStub;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
sub = common.content.subscriptionBlocks[subKey];
|
sub = common.content.subscriptionBlocks[subKey];
|
||||||
@@ -197,25 +207,25 @@ describe('Apple Payments', () => {
|
|||||||
token = 'test-token';
|
token = 'test-token';
|
||||||
headers = {};
|
headers = {};
|
||||||
receipt = `{"token": "${token}"}`;
|
receipt = `{"token": "${token}"}`;
|
||||||
nextPaymentProcessing = moment.utc().add({days: 2});
|
nextPaymentProcessing = moment.utc().add({ days: 2 });
|
||||||
|
|
||||||
iapSetupStub = sinon.stub(iapModule, 'setup')
|
iapSetupStub = sinon.stub(iap, 'setup')
|
||||||
.resolves();
|
.resolves();
|
||||||
iapValidateStub = sinon.stub(iapModule, 'validate')
|
iapValidateStub = sinon.stub(iap, 'validate')
|
||||||
.resolves({});
|
.resolves({});
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
|
||||||
.returns(true);
|
.returns(true);
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
|
||||||
.returns([{
|
.returns([{
|
||||||
expirationDate: moment.utc().subtract({day: 1}).toDate(),
|
expirationDate: moment.utc().subtract({ day: 1 }).toDate(),
|
||||||
productId: sku,
|
productId: sku,
|
||||||
transactionId: token,
|
transactionId: token,
|
||||||
}, {
|
}, {
|
||||||
expirationDate: moment.utc().add({day: 1}).toDate(),
|
expirationDate: moment.utc().add({ day: 1 }).toDate(),
|
||||||
productId: 'wrongsku',
|
productId: 'wrongsku',
|
||||||
transactionId: token,
|
transactionId: token,
|
||||||
}, {
|
}, {
|
||||||
expirationDate: moment.utc().add({day: 1}).toDate(),
|
expirationDate: moment.utc().add({ day: 1 }).toDate(),
|
||||||
productId: sku,
|
productId: sku,
|
||||||
transactionId: token,
|
transactionId: token,
|
||||||
}]);
|
}]);
|
||||||
@@ -223,10 +233,10 @@ describe('Apple Payments', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
iapModule.setup.restore();
|
iap.setup.restore();
|
||||||
iapModule.validate.restore();
|
iap.validate.restore();
|
||||||
iapModule.isValidated.restore();
|
iap.isValidated.restore();
|
||||||
iapModule.getPurchaseData.restore();
|
iap.getPurchaseData.restore();
|
||||||
if (payments.createSubscription.restore) payments.createSubscription.restore();
|
if (payments.createSubscription.restore) payments.createSubscription.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -240,8 +250,8 @@ describe('Apple Payments', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if receipt is invalid', async () => {
|
it('should throw an error if receipt is invalid', async () => {
|
||||||
iapModule.isValidated.restore();
|
iap.isValidated.restore();
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
|
||||||
.returns(false);
|
.returns(false);
|
||||||
|
|
||||||
await expect(applePayments.subscribe(sku, user, receipt, headers, nextPaymentProcessing))
|
await expect(applePayments.subscribe(sku, user, receipt, headers, nextPaymentProcessing))
|
||||||
@@ -272,10 +282,10 @@ describe('Apple Payments', () => {
|
|||||||
];
|
];
|
||||||
subOptions.forEach(option => {
|
subOptions.forEach(option => {
|
||||||
it(`creates a user subscription for ${option.sku}`, async () => {
|
it(`creates a user subscription for ${option.sku}`, async () => {
|
||||||
iapModule.getPurchaseData.restore();
|
iap.getPurchaseData.restore();
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
|
||||||
.returns([{
|
.returns([{
|
||||||
expirationDate: moment.utc().add({day: 1}).toDate(),
|
expirationDate: moment.utc().add({ day: 1 }).toDate(),
|
||||||
productId: option.sku,
|
productId: option.sku,
|
||||||
transactionId: token,
|
transactionId: token,
|
||||||
}]);
|
}]);
|
||||||
@@ -319,8 +329,10 @@ describe('Apple Payments', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('cancelSubscribe ', () => {
|
describe('cancelSubscribe ', () => {
|
||||||
let user, token, receipt, headers, customerId, expirationDate;
|
let user; let token; let receipt; let headers; let customerId; let
|
||||||
let iapSetupStub, iapValidateStub, iapIsValidatedStub, iapGetPurchaseDataStub, paymentCancelSubscriptionSpy;
|
expirationDate;
|
||||||
|
let iapSetupStub; let iapValidateStub; let iapIsValidatedStub; let iapGetPurchaseDataStub; let
|
||||||
|
paymentCancelSubscriptionSpy;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
token = 'test-token';
|
token = 'test-token';
|
||||||
@@ -329,15 +341,15 @@ describe('Apple Payments', () => {
|
|||||||
customerId = 'test-customerId';
|
customerId = 'test-customerId';
|
||||||
expirationDate = moment.utc();
|
expirationDate = moment.utc();
|
||||||
|
|
||||||
iapSetupStub = sinon.stub(iapModule, 'setup')
|
iapSetupStub = sinon.stub(iap, 'setup')
|
||||||
.resolves();
|
.resolves();
|
||||||
iapValidateStub = sinon.stub(iapModule, 'validate')
|
iapValidateStub = sinon.stub(iap, 'validate')
|
||||||
.resolves({
|
.resolves({
|
||||||
expirationDate,
|
expirationDate,
|
||||||
});
|
});
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
|
||||||
.returns([{expirationDate: expirationDate.toDate()}]);
|
.returns([{ expirationDate: expirationDate.toDate() }]);
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
|
||||||
.returns(true);
|
.returns(true);
|
||||||
|
|
||||||
user = new User();
|
user = new User();
|
||||||
@@ -350,11 +362,11 @@ describe('Apple Payments', () => {
|
|||||||
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
|
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(() => {
|
||||||
iapModule.setup.restore();
|
iap.setup.restore();
|
||||||
iapModule.validate.restore();
|
iap.validate.restore();
|
||||||
iapModule.isValidated.restore();
|
iap.isValidated.restore();
|
||||||
iapModule.getPurchaseData.restore();
|
iap.getPurchaseData.restore();
|
||||||
payments.cancelSubscription.restore();
|
payments.cancelSubscription.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -370,9 +382,9 @@ describe('Apple Payments', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if subscription is still valid', async () => {
|
it('should throw an error if subscription is still valid', async () => {
|
||||||
iapModule.getPurchaseData.restore();
|
iap.getPurchaseData.restore();
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
|
||||||
.returns([{expirationDate: expirationDate.add({day: 1}).toDate()}]);
|
.returns([{ expirationDate: expirationDate.add({ day: 1 }).toDate() }]);
|
||||||
|
|
||||||
await expect(applePayments.cancelSubscribe(user, headers))
|
await expect(applePayments.cancelSubscribe(user, headers))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
@@ -383,8 +395,8 @@ describe('Apple Payments', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if receipt is invalid', async () => {
|
it('should throw an error if receipt is invalid', async () => {
|
||||||
iapModule.isValidated.restore();
|
iap.isValidated.restore();
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
|
||||||
.returns(false);
|
.returns(false);
|
||||||
|
|
||||||
await expect(applePayments.cancelSubscribe(user, headers))
|
await expect(applePayments.cancelSubscribe(user, headers))
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
import iapModule from '../../../../../website/server/libs/inAppPurchases';
|
import moment from 'moment';
|
||||||
import payments from '../../../../../website/server/libs/payments/payments';
|
import payments from '../../../../../website/server/libs/payments/payments';
|
||||||
import googlePayments from '../../../../../website/server/libs/payments/google';
|
import googlePayments from '../../../../../website/server/libs/payments/google';
|
||||||
import iap from '../../../../../website/server/libs/inAppPurchases';
|
import iap from '../../../../../website/server/libs/inAppPurchases';
|
||||||
import {model as User} from '../../../../../website/server/models/user';
|
import { model as User } from '../../../../../website/server/models/user';
|
||||||
import common from '../../../../../website/common';
|
import common from '../../../../../website/common';
|
||||||
import moment from 'moment';
|
import { mockFindById, restoreFindById } from '../../../../helpers/mongoose.helper';
|
||||||
import {mockFindById, restoreFindById} from '../../../../helpers/mongoose.helper';
|
|
||||||
|
|
||||||
const i18n = common.i18n;
|
const { i18n } = common;
|
||||||
|
|
||||||
describe('Google Payments', () => {
|
describe('Google Payments', () => {
|
||||||
let subKey = 'basic_3mo';
|
const subKey = 'basic_3mo';
|
||||||
|
|
||||||
describe('verifyGemPurchase', () => {
|
describe('verifyGemPurchase', () => {
|
||||||
let sku, user, token, receipt, signature, headers;
|
let sku; let user; let token; let receipt; let signature; let
|
||||||
let iapSetupStub, iapValidateStub, iapIsValidatedStub, paymentBuyGemsStub;
|
headers;
|
||||||
|
let iapSetupStub; let iapValidateStub; let iapIsValidatedStub; let
|
||||||
|
paymentBuyGemsStub;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
sku = 'com.habitrpg.android.habitica.iap.21gems';
|
sku = 'com.habitrpg.android.habitica.iap.21gems';
|
||||||
@@ -24,28 +25,30 @@ describe('Google Payments', () => {
|
|||||||
signature = '';
|
signature = '';
|
||||||
headers = {};
|
headers = {};
|
||||||
|
|
||||||
iapSetupStub = sinon.stub(iapModule, 'setup')
|
iapSetupStub = sinon.stub(iap, 'setup')
|
||||||
.resolves();
|
.resolves();
|
||||||
iapValidateStub = sinon.stub(iapModule, 'validate')
|
iapValidateStub = sinon.stub(iap, 'validate')
|
||||||
.resolves({});
|
.resolves({});
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
|
||||||
.returns(true);
|
.returns(true);
|
||||||
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').resolves({});
|
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
iapModule.setup.restore();
|
iap.setup.restore();
|
||||||
iapModule.validate.restore();
|
iap.validate.restore();
|
||||||
iapModule.isValidated.restore();
|
iap.isValidated.restore();
|
||||||
payments.buyGems.restore();
|
payments.buyGems.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if receipt is invalid', async () => {
|
it('should throw an error if receipt is invalid', async () => {
|
||||||
iapModule.isValidated.restore();
|
iap.isValidated.restore();
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
|
||||||
.returns(false);
|
.returns(false);
|
||||||
|
|
||||||
await expect(googlePayments.verifyGemPurchase({user, receipt, signature, headers}))
|
await expect(googlePayments.verifyGemPurchase({
|
||||||
|
user, receipt, signature, headers,
|
||||||
|
}))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -56,7 +59,9 @@ describe('Google Payments', () => {
|
|||||||
it('should throw an error if productId is invalid', async () => {
|
it('should throw an error if productId is invalid', async () => {
|
||||||
receipt = `{"token": "${token}", "productId": "invalid"}`;
|
receipt = `{"token": "${token}", "productId": "invalid"}`;
|
||||||
|
|
||||||
await expect(googlePayments.verifyGemPurchase({user, receipt, signature, headers}))
|
await expect(googlePayments.verifyGemPurchase({
|
||||||
|
user, receipt, signature, headers,
|
||||||
|
}))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -67,7 +72,9 @@ describe('Google Payments', () => {
|
|||||||
it('should throw an error if user cannot purchase gems', async () => {
|
it('should throw an error if user cannot purchase gems', async () => {
|
||||||
sinon.stub(user, 'canGetGems').resolves(false);
|
sinon.stub(user, 'canGetGems').resolves(false);
|
||||||
|
|
||||||
await expect(googlePayments.verifyGemPurchase({user, receipt, signature, headers}))
|
await expect(googlePayments.verifyGemPurchase({
|
||||||
|
user, receipt, signature, headers,
|
||||||
|
}))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -79,7 +86,9 @@ describe('Google Payments', () => {
|
|||||||
|
|
||||||
it('purchases gems', async () => {
|
it('purchases gems', async () => {
|
||||||
sinon.stub(user, 'canGetGems').resolves(true);
|
sinon.stub(user, 'canGetGems').resolves(true);
|
||||||
await googlePayments.verifyGemPurchase({user, receipt, signature, headers});
|
await googlePayments.verifyGemPurchase({
|
||||||
|
user, receipt, signature, headers,
|
||||||
|
});
|
||||||
|
|
||||||
expect(iapSetupStub).to.be.calledOnce;
|
expect(iapSetupStub).to.be.calledOnce;
|
||||||
expect(iapValidateStub).to.be.calledOnce;
|
expect(iapValidateStub).to.be.calledOnce;
|
||||||
@@ -107,8 +116,10 @@ describe('Google Payments', () => {
|
|||||||
|
|
||||||
mockFindById(receivingUser);
|
mockFindById(receivingUser);
|
||||||
|
|
||||||
const gift = {uuid: receivingUser._id};
|
const gift = { uuid: receivingUser._id };
|
||||||
await googlePayments.verifyGemPurchase({user, gift, receipt, signature, headers});
|
await googlePayments.verifyGemPurchase({
|
||||||
|
user, gift, receipt, signature, headers,
|
||||||
|
});
|
||||||
|
|
||||||
expect(iapSetupStub).to.be.calledOnce;
|
expect(iapSetupStub).to.be.calledOnce;
|
||||||
expect(iapValidateStub).to.be.calledOnce;
|
expect(iapValidateStub).to.be.calledOnce;
|
||||||
@@ -131,8 +142,10 @@ describe('Google Payments', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('subscribe', () => {
|
describe('subscribe', () => {
|
||||||
let sub, sku, user, token, receipt, signature, headers, nextPaymentProcessing;
|
let sub; let sku; let user; let token; let receipt; let signature; let headers; let
|
||||||
let iapSetupStub, iapValidateStub, iapIsValidatedStub, paymentsCreateSubscritionStub;
|
nextPaymentProcessing;
|
||||||
|
let iapSetupStub; let iapValidateStub; let iapIsValidatedStub; let
|
||||||
|
paymentsCreateSubscritionStub;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
sub = common.content.subscriptionBlocks[subKey];
|
sub = common.content.subscriptionBlocks[subKey];
|
||||||
@@ -142,30 +155,31 @@ describe('Google Payments', () => {
|
|||||||
headers = {};
|
headers = {};
|
||||||
receipt = `{"token": "${token}"}`;
|
receipt = `{"token": "${token}"}`;
|
||||||
signature = '';
|
signature = '';
|
||||||
nextPaymentProcessing = moment.utc().add({days: 2});
|
nextPaymentProcessing = moment.utc().add({ days: 2 });
|
||||||
|
|
||||||
iapSetupStub = sinon.stub(iapModule, 'setup')
|
iapSetupStub = sinon.stub(iap, 'setup')
|
||||||
.resolves();
|
.resolves();
|
||||||
iapValidateStub = sinon.stub(iapModule, 'validate')
|
iapValidateStub = sinon.stub(iap, 'validate')
|
||||||
.resolves({});
|
.resolves({});
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
|
||||||
.returns(true);
|
.returns(true);
|
||||||
paymentsCreateSubscritionStub = sinon.stub(payments, 'createSubscription').resolves({});
|
paymentsCreateSubscritionStub = sinon.stub(payments, 'createSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
iapModule.setup.restore();
|
iap.setup.restore();
|
||||||
iapModule.validate.restore();
|
iap.validate.restore();
|
||||||
iapModule.isValidated.restore();
|
iap.isValidated.restore();
|
||||||
payments.createSubscription.restore();
|
payments.createSubscription.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if receipt is invalid', async () => {
|
it('should throw an error if receipt is invalid', async () => {
|
||||||
iapModule.isValidated.restore();
|
iap.isValidated.restore();
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
|
||||||
.returns(false);
|
.returns(false);
|
||||||
|
|
||||||
await expect(googlePayments.subscribe(sku, user, receipt, signature, headers, nextPaymentProcessing))
|
await expect(googlePayments
|
||||||
|
.subscribe(sku, user, receipt, signature, headers, nextPaymentProcessing))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -176,7 +190,8 @@ describe('Google Payments', () => {
|
|||||||
it('should throw an error if sku is invalid', async () => {
|
it('should throw an error if sku is invalid', async () => {
|
||||||
sku = 'invalid';
|
sku = 'invalid';
|
||||||
|
|
||||||
await expect(googlePayments.subscribe(sku, user, receipt, signature, headers, nextPaymentProcessing))
|
await expect(googlePayments
|
||||||
|
.subscribe(sku, user, receipt, signature, headers, nextPaymentProcessing))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -203,15 +218,17 @@ describe('Google Payments', () => {
|
|||||||
paymentMethod: googlePayments.constants.PAYMENT_METHOD_GOOGLE,
|
paymentMethod: googlePayments.constants.PAYMENT_METHOD_GOOGLE,
|
||||||
sub,
|
sub,
|
||||||
headers,
|
headers,
|
||||||
additionalData: {data: receipt, signature},
|
additionalData: { data: receipt, signature },
|
||||||
nextPaymentProcessing,
|
nextPaymentProcessing,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('cancelSubscribe ', () => {
|
describe('cancelSubscribe ', () => {
|
||||||
let user, token, receipt, signature, headers, customerId, expirationDate;
|
let user; let token; let receipt; let signature; let headers; let customerId; let
|
||||||
let iapSetupStub, iapValidateStub, iapIsValidatedStub, iapGetPurchaseDataStub, paymentCancelSubscriptionSpy;
|
expirationDate;
|
||||||
|
let iapSetupStub; let iapValidateStub; let iapIsValidatedStub; let iapGetPurchaseDataStub; let
|
||||||
|
paymentCancelSubscriptionSpy;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
token = 'test-token';
|
token = 'test-token';
|
||||||
@@ -221,15 +238,15 @@ describe('Google Payments', () => {
|
|||||||
customerId = 'test-customerId';
|
customerId = 'test-customerId';
|
||||||
expirationDate = moment.utc();
|
expirationDate = moment.utc();
|
||||||
|
|
||||||
iapSetupStub = sinon.stub(iapModule, 'setup')
|
iapSetupStub = sinon.stub(iap, 'setup')
|
||||||
.resolves();
|
.resolves();
|
||||||
iapValidateStub = sinon.stub(iapModule, 'validate')
|
iapValidateStub = sinon.stub(iap, 'validate')
|
||||||
.resolves({
|
.resolves({
|
||||||
expirationDate,
|
expirationDate,
|
||||||
});
|
});
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
|
||||||
.returns([{expirationDate: expirationDate.toDate()}]);
|
.returns([{ expirationDate: expirationDate.toDate() }]);
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
|
||||||
.returns(true);
|
.returns(true);
|
||||||
|
|
||||||
user = new User();
|
user = new User();
|
||||||
@@ -237,16 +254,16 @@ describe('Google Payments', () => {
|
|||||||
user.purchased.plan.customerId = customerId;
|
user.purchased.plan.customerId = customerId;
|
||||||
user.purchased.plan.paymentMethod = googlePayments.constants.PAYMENT_METHOD_GOOGLE;
|
user.purchased.plan.paymentMethod = googlePayments.constants.PAYMENT_METHOD_GOOGLE;
|
||||||
user.purchased.plan.planId = subKey;
|
user.purchased.plan.planId = subKey;
|
||||||
user.purchased.plan.additionalData = {data: receipt, signature};
|
user.purchased.plan.additionalData = { data: receipt, signature };
|
||||||
|
|
||||||
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
|
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(() => {
|
||||||
iapModule.setup.restore();
|
iap.setup.restore();
|
||||||
iapModule.validate.restore();
|
iap.validate.restore();
|
||||||
iapModule.isValidated.restore();
|
iap.isValidated.restore();
|
||||||
iapModule.getPurchaseData.restore();
|
iap.getPurchaseData.restore();
|
||||||
payments.cancelSubscription.restore();
|
payments.cancelSubscription.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -262,9 +279,9 @@ describe('Google Payments', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if subscription is still valid', async () => {
|
it('should throw an error if subscription is still valid', async () => {
|
||||||
iapModule.getPurchaseData.restore();
|
iap.getPurchaseData.restore();
|
||||||
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
|
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
|
||||||
.returns([{expirationDate: expirationDate.add({day: 1}).toDate()}]);
|
.returns([{ expirationDate: expirationDate.add({ day: 1 }).toDate() }]);
|
||||||
|
|
||||||
await expect(googlePayments.cancelSubscribe(user, headers))
|
await expect(googlePayments.cancelSubscribe(user, headers))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
@@ -275,8 +292,8 @@ describe('Google Payments', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if receipt is invalid', async () => {
|
it('should throw an error if receipt is invalid', async () => {
|
||||||
iapModule.isValidated.restore();
|
iap.isValidated.restore();
|
||||||
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
|
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
|
||||||
.returns(false);
|
.returns(false);
|
||||||
|
|
||||||
await expect(googlePayments.cancelSubscribe(user, headers))
|
await expect(googlePayments.cancelSubscribe(user, headers))
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
import * as sender from '../../../../../../website/server/libs/email';
|
import * as sender from '../../../../../../website/server/libs/email';
|
||||||
import * as api from '../../../../../../website/server/libs/payments/payments';
|
import api from '../../../../../../website/server/libs/payments/payments';
|
||||||
import { model as User } from '../../../../../../website/server/models/user';
|
import { model as User } from '../../../../../../website/server/models/user';
|
||||||
import { model as Group } from '../../../../../../website/server/models/group';
|
import { model as Group } from '../../../../../../website/server/models/group';
|
||||||
import {
|
import {
|
||||||
generateGroup,
|
generateGroup,
|
||||||
} from '../../../../../helpers/api-unit.helper.js';
|
} from '../../../../../helpers/api-unit.helper';
|
||||||
import i18n from '../../../../../../website/common/script/i18n';
|
import i18n from '../../../../../../website/common/script/i18n';
|
||||||
|
|
||||||
describe('Canceling a subscription for group', () => {
|
describe('Canceling a subscription for group', () => {
|
||||||
let plan, group, user, data;
|
let plan; let group; let user; let
|
||||||
|
data;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
user = new User();
|
user = new User();
|
||||||
@@ -67,9 +68,9 @@ describe('Canceling a subscription for group', () => {
|
|||||||
data.groupId = group._id;
|
data.groupId = group._id;
|
||||||
await api.cancelSubscription(data);
|
await api.cancelSubscription(data);
|
||||||
|
|
||||||
let now = new Date();
|
const now = new Date();
|
||||||
let updatedGroup = await Group.findById(group._id).exec();
|
const updatedGroup = await Group.findById(group._id).exec();
|
||||||
let daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
|
const daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
|
||||||
|
|
||||||
expect(daysTillTermination).to.be.within(29, 30); // 1 month +/- 1 days
|
expect(daysTillTermination).to.be.within(29, 30); // 1 month +/- 1 days
|
||||||
});
|
});
|
||||||
@@ -81,9 +82,9 @@ describe('Canceling a subscription for group', () => {
|
|||||||
|
|
||||||
await api.cancelSubscription(data);
|
await api.cancelSubscription(data);
|
||||||
|
|
||||||
let now = new Date();
|
const now = new Date();
|
||||||
let updatedGroup = await Group.findById(group._id).exec();
|
const updatedGroup = await Group.findById(group._id).exec();
|
||||||
let daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
|
const daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
|
||||||
|
|
||||||
expect(daysTillTermination).to.be.within(89, 90); // 3 months +/- 1 days
|
expect(daysTillTermination).to.be.within(89, 90); // 3 months +/- 1 days
|
||||||
});
|
});
|
||||||
@@ -95,9 +96,9 @@ describe('Canceling a subscription for group', () => {
|
|||||||
|
|
||||||
await api.cancelSubscription(data);
|
await api.cancelSubscription(data);
|
||||||
|
|
||||||
let now = new Date();
|
const now = new Date();
|
||||||
let updatedGroup = await Group.findById(group._id).exec();
|
const updatedGroup = await Group.findById(group._id).exec();
|
||||||
let daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
|
const daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
|
||||||
|
|
||||||
expect(daysTillTermination).to.be.within(38, 39); // should be about 1 month + 1/3 month
|
expect(daysTillTermination).to.be.within(38, 39); // should be about 1 month + 1/3 month
|
||||||
});
|
});
|
||||||
@@ -108,9 +109,9 @@ describe('Canceling a subscription for group', () => {
|
|||||||
|
|
||||||
await api.cancelSubscription(data);
|
await api.cancelSubscription(data);
|
||||||
|
|
||||||
let now = new Date();
|
const now = new Date();
|
||||||
let updatedGroup = await Group.findById(group._id).exec();
|
const updatedGroup = await Group.findById(group._id).exec();
|
||||||
let daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
|
const daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
|
||||||
|
|
||||||
expect(daysTillTermination).to.be.within(13, 15);
|
expect(daysTillTermination).to.be.within(13, 15);
|
||||||
});
|
});
|
||||||
@@ -122,7 +123,7 @@ describe('Canceling a subscription for group', () => {
|
|||||||
|
|
||||||
await api.cancelSubscription(data);
|
await api.cancelSubscription(data);
|
||||||
|
|
||||||
let updatedGroup = await Group.findById(group._id).exec();
|
const updatedGroup = await Group.findById(group._id).exec();
|
||||||
expect(updatedGroup.purchased.plan.extraMonths).to.eql(0);
|
expect(updatedGroup.purchased.plan.extraMonths).to.eql(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -134,12 +135,12 @@ describe('Canceling a subscription for group', () => {
|
|||||||
expect(sender.sendTxn.firstCall.args[0]._id).to.equal(user._id);
|
expect(sender.sendTxn.firstCall.args[0]._id).to.equal(user._id);
|
||||||
expect(sender.sendTxn.firstCall.args[1]).to.equal('group-cancel-subscription');
|
expect(sender.sendTxn.firstCall.args[1]).to.equal('group-cancel-subscription');
|
||||||
expect(sender.sendTxn.firstCall.args[2]).to.eql([
|
expect(sender.sendTxn.firstCall.args[2]).to.eql([
|
||||||
{name: 'GROUP_NAME', content: group.name},
|
{ name: 'GROUP_NAME', content: group.name },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('prevents non group leader from managing subscription', async () => {
|
it('prevents non group leader from managing subscription', async () => {
|
||||||
let groupMember = new User();
|
const groupMember = new User();
|
||||||
data.user = groupMember;
|
data.user = groupMember;
|
||||||
data.groupId = group._id;
|
data.groupId = group._id;
|
||||||
|
|
||||||
@@ -160,7 +161,7 @@ describe('Canceling a subscription for group', () => {
|
|||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedGroup = await Group.findById(group._id).exec();
|
let updatedGroup = await Group.findById(group._id).exec();
|
||||||
let newLeader = new User();
|
const newLeader = new User();
|
||||||
updatedGroup.leader = newLeader._id;
|
updatedGroup.leader = newLeader._id;
|
||||||
await updatedGroup.save();
|
await updatedGroup.save();
|
||||||
|
|
||||||
@@ -192,15 +193,15 @@ describe('Canceling a subscription for group', () => {
|
|||||||
|
|
||||||
await api.cancelSubscription(data);
|
await api.cancelSubscription(data);
|
||||||
|
|
||||||
let now = new Date();
|
const now = new Date();
|
||||||
now.setHours(0, 0, 0, 0);
|
now.setHours(0, 0, 0, 0);
|
||||||
let updatedLeader = await User.findById(user._id).exec();
|
const updatedLeader = await User.findById(user._id).exec();
|
||||||
let daysTillTermination = moment(updatedLeader.purchased.plan.dateTerminated).diff(now, 'days');
|
const daysTillTermination = moment(updatedLeader.purchased.plan.dateTerminated).diff(now, 'days');
|
||||||
expect(daysTillTermination).to.be.within(2, 3); // only a few days
|
expect(daysTillTermination).to.be.within(2, 3); // only a few days
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends an email to members of group', async () => {
|
it('sends an email to members of group', async () => {
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
recipient.guilds.push(group._id);
|
recipient.guilds.push(group._id);
|
||||||
await recipient.save();
|
await recipient.save();
|
||||||
@@ -214,8 +215,8 @@ describe('Canceling a subscription for group', () => {
|
|||||||
expect(sender.sendTxn.thirdCall.args[0]._id).to.equal(recipient._id);
|
expect(sender.sendTxn.thirdCall.args[0]._id).to.equal(recipient._id);
|
||||||
expect(sender.sendTxn.thirdCall.args[1]).to.equal('group-member-cancel');
|
expect(sender.sendTxn.thirdCall.args[1]).to.equal('group-member-cancel');
|
||||||
expect(sender.sendTxn.thirdCall.args[2]).to.eql([
|
expect(sender.sendTxn.thirdCall.args[2]).to.eql([
|
||||||
{name: 'LEADER', content: user.profile.name},
|
{ name: 'LEADER', content: user.profile.name },
|
||||||
{name: 'GROUP_NAME', content: group.name},
|
{ name: 'GROUP_NAME', content: group.name },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -223,7 +224,7 @@ describe('Canceling a subscription for group', () => {
|
|||||||
plan.key = 'basic_earned';
|
plan.key = 'basic_earned';
|
||||||
plan.customerId = api.constants.UNLIMITED_CUSTOMER_ID;
|
plan.customerId = api.constants.UNLIMITED_CUSTOMER_ID;
|
||||||
|
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
recipient.purchased.plan = plan;
|
recipient.purchased.plan = plan;
|
||||||
recipient.guilds.push(group._id);
|
recipient.guilds.push(group._id);
|
||||||
@@ -233,12 +234,12 @@ describe('Canceling a subscription for group', () => {
|
|||||||
|
|
||||||
await api.cancelSubscription(data);
|
await api.cancelSubscription(data);
|
||||||
|
|
||||||
let updatedLeader = await User.findById(user._id).exec();
|
const updatedLeader = await User.findById(user._id).exec();
|
||||||
expect(updatedLeader.purchased.plan.dateTerminated).to.not.exist;
|
expect(updatedLeader.purchased.plan.dateTerminated).to.not.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not cancel a user subscription if they are still in another active group plan', async () => {
|
it('does not cancel a user subscription if they are still in another active group plan', async () => {
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
plan.key = 'basic_earned';
|
plan.key = 'basic_earned';
|
||||||
recipient.purchased.plan = plan;
|
recipient.purchased.plan = plan;
|
||||||
@@ -252,10 +253,10 @@ describe('Canceling a subscription for group', () => {
|
|||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
let updatedUser = await User.findById(recipient._id).exec();
|
||||||
let firstDateCreated = updatedUser.purchased.plan.dateCreated;
|
const firstDateCreated = updatedUser.purchased.plan.dateCreated;
|
||||||
let extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
|
const extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
|
||||||
|
|
||||||
let group2 = generateGroup({
|
const group2 = generateGroup({
|
||||||
name: 'test group2',
|
name: 'test group2',
|
||||||
type: 'guild',
|
type: 'guild',
|
||||||
privacy: 'public',
|
privacy: 'public',
|
||||||
@@ -291,10 +292,10 @@ describe('Canceling a subscription for group', () => {
|
|||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(user._id).exec();
|
let updatedUser = await User.findById(user._id).exec();
|
||||||
let firstDateCreated = updatedUser.purchased.plan.dateCreated;
|
const firstDateCreated = updatedUser.purchased.plan.dateCreated;
|
||||||
let extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
|
const extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
|
||||||
|
|
||||||
let group2 = generateGroup({
|
const group2 = generateGroup({
|
||||||
name: 'test group2',
|
name: 'test group2',
|
||||||
type: 'guild',
|
type: 'guild',
|
||||||
privacy: 'public',
|
privacy: 'public',
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import stripeModule from 'stripe';
|
|||||||
import nconf from 'nconf';
|
import nconf from 'nconf';
|
||||||
|
|
||||||
import * as sender from '../../../../../../website/server/libs/email';
|
import * as sender from '../../../../../../website/server/libs/email';
|
||||||
import * as api from '../../../../../../website/server/libs/payments/payments';
|
import api from '../../../../../../website/server/libs/payments/payments';
|
||||||
import amzLib from '../../../../../../website/server/libs/payments/amazon';
|
import amzLib from '../../../../../../website/server/libs/payments/amazon';
|
||||||
import paypalPayments from '../../../../../../website/server/libs/payments/paypal';
|
import paypalPayments from '../../../../../../website/server/libs/payments/paypal';
|
||||||
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
|
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
|
||||||
@@ -11,7 +11,7 @@ import { model as User } from '../../../../../../website/server/models/user';
|
|||||||
import { model as Group } from '../../../../../../website/server/models/group';
|
import { model as Group } from '../../../../../../website/server/models/group';
|
||||||
import {
|
import {
|
||||||
generateGroup,
|
generateGroup,
|
||||||
} from '../../../../../helpers/api-unit.helper.js';
|
} from '../../../../../helpers/api-unit.helper';
|
||||||
|
|
||||||
describe('Purchasing a group plan for group', () => {
|
describe('Purchasing a group plan for group', () => {
|
||||||
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_GOOGLE = 'Google_subscription';
|
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_GOOGLE = 'Google_subscription';
|
||||||
@@ -19,10 +19,11 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL = 'normal_subscription';
|
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL = 'normal_subscription';
|
||||||
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NONE = 'no_subscription';
|
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NONE = 'no_subscription';
|
||||||
|
|
||||||
let plan, group, user, data;
|
let plan; let group; let user; let
|
||||||
let stripe = stripeModule('test');
|
data;
|
||||||
let groupLeaderName = 'sender';
|
const stripe = stripeModule('test');
|
||||||
let groupName = 'test group';
|
const groupLeaderName = 'sender';
|
||||||
|
const groupName = 'test group';
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
user = new User();
|
user = new User();
|
||||||
@@ -68,14 +69,17 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let subscriptionId = 'subId';
|
const subscriptionId = 'subId';
|
||||||
sinon.stub(stripe.customers, 'del').resolves({});
|
sinon.stub(stripe.customers, 'del').resolves({});
|
||||||
|
|
||||||
let currentPeriodEndTimeStamp = moment().add(3, 'months').unix();
|
const currentPeriodEndTimeStamp = moment().add(3, 'months').unix();
|
||||||
sinon.stub(stripe.customers, 'retrieve')
|
sinon.stub(stripe.customers, 'retrieve')
|
||||||
.resolves({
|
.resolves({
|
||||||
subscriptions: {
|
subscriptions: {
|
||||||
data: [{id: subscriptionId, current_period_end: currentPeriodEndTimeStamp}], // eslint-disable-line camelcase
|
data: [{
|
||||||
|
id: subscriptionId,
|
||||||
|
current_period_end: currentPeriodEndTimeStamp,
|
||||||
|
}], // eslint-disable-line camelcase
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -95,7 +99,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedGroup = await Group.findById(group._id).exec();
|
const updatedGroup = await Group.findById(group._id).exec();
|
||||||
|
|
||||||
expect(updatedGroup.purchased.plan.planId).to.eql('basic_3mo');
|
expect(updatedGroup.purchased.plan.planId).to.eql('basic_3mo');
|
||||||
expect(updatedGroup.purchased.plan.customerId).to.eql('customer-id');
|
expect(updatedGroup.purchased.plan.customerId).to.eql('customer-id');
|
||||||
@@ -126,7 +130,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedGroup = await Group.findById(group._id).exec();
|
const updatedGroup = await Group.findById(group._id).exec();
|
||||||
expect(updatedGroup.purchased.plan.extraMonths).to.within(1.9, 2);
|
expect(updatedGroup.purchased.plan.extraMonths).to.within(1.9, 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -139,7 +143,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedGroup = await Group.findById(group._id).exec();
|
const updatedGroup = await Group.findById(group._id).exec();
|
||||||
expect(updatedGroup.purchased.plan.extraMonths).to.eql(0);
|
expect(updatedGroup.purchased.plan.extraMonths).to.eql(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -150,7 +154,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
data.groupId = group._id;
|
data.groupId = group._id;
|
||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
let updatedLeader = await User.findById(user._id).exec();
|
const updatedLeader = await User.findById(user._id).exec();
|
||||||
|
|
||||||
expect(updatedLeader.purchased.plan.planId).to.eql('group_plan_auto');
|
expect(updatedLeader.purchased.plan.planId).to.eql('group_plan_auto');
|
||||||
expect(updatedLeader.purchased.plan.customerId).to.eql('group-plan');
|
expect(updatedLeader.purchased.plan.customerId).to.eql('group-plan');
|
||||||
@@ -166,7 +170,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('sends an email to member of group who was not a subscriber', async () => {
|
it('sends an email to member of group who was not a subscriber', async () => {
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
recipient.guilds.push(group._id);
|
recipient.guilds.push(group._id);
|
||||||
await recipient.save();
|
await recipient.save();
|
||||||
@@ -179,9 +183,9 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
expect(sender.sendTxn.firstCall.args[0]._id).to.equal(recipient._id);
|
expect(sender.sendTxn.firstCall.args[0]._id).to.equal(recipient._id);
|
||||||
expect(sender.sendTxn.firstCall.args[1]).to.equal('group-member-join');
|
expect(sender.sendTxn.firstCall.args[1]).to.equal('group-member-join');
|
||||||
expect(sender.sendTxn.firstCall.args[2]).to.eql([
|
expect(sender.sendTxn.firstCall.args[2]).to.eql([
|
||||||
{name: 'LEADER', content: user.profile.name},
|
{ name: 'LEADER', content: user.profile.name },
|
||||||
{name: 'GROUP_NAME', content: group.name},
|
{ name: 'GROUP_NAME', content: group.name },
|
||||||
{name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NONE},
|
{ name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NONE },
|
||||||
]);
|
]);
|
||||||
// confirm that the other email sent is appropriate:
|
// confirm that the other email sent is appropriate:
|
||||||
expect(sender.sendTxn.secondCall.args[0]._id).to.equal(group.leader);
|
expect(sender.sendTxn.secondCall.args[0]._id).to.equal(group.leader);
|
||||||
@@ -189,7 +193,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('sends one email to subscribed member of group, stating subscription is cancelled (Stripe)', async () => {
|
it('sends one email to subscribed member of group, stating subscription is cancelled (Stripe)', async () => {
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
plan.key = 'basic_earned';
|
plan.key = 'basic_earned';
|
||||||
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
|
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
|
||||||
@@ -205,9 +209,9 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
expect(sender.sendTxn.firstCall.args[0]._id).to.equal(recipient._id);
|
expect(sender.sendTxn.firstCall.args[0]._id).to.equal(recipient._id);
|
||||||
expect(sender.sendTxn.firstCall.args[1]).to.equal('group-member-join');
|
expect(sender.sendTxn.firstCall.args[1]).to.equal('group-member-join');
|
||||||
expect(sender.sendTxn.firstCall.args[2]).to.eql([
|
expect(sender.sendTxn.firstCall.args[2]).to.eql([
|
||||||
{name: 'LEADER', content: user.profile.name},
|
{ name: 'LEADER', content: user.profile.name },
|
||||||
{name: 'GROUP_NAME', content: group.name},
|
{ name: 'GROUP_NAME', content: group.name },
|
||||||
{name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL},
|
{ name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL },
|
||||||
]);
|
]);
|
||||||
// confirm that the other email sent is not a cancel-subscription email:
|
// confirm that the other email sent is not a cancel-subscription email:
|
||||||
expect(sender.sendTxn.secondCall.args[0]._id).to.equal(group.leader);
|
expect(sender.sendTxn.secondCall.args[0]._id).to.equal(group.leader);
|
||||||
@@ -218,11 +222,11 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
sinon.stub(amzLib, 'getBillingAgreementDetails')
|
sinon.stub(amzLib, 'getBillingAgreementDetails')
|
||||||
.resolves({
|
.resolves({
|
||||||
BillingAgreementDetails: {
|
BillingAgreementDetails: {
|
||||||
BillingAgreementStatus: {State: 'Closed'},
|
BillingAgreementStatus: { State: 'Closed' },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
plan.planId = 'basic_earned';
|
plan.planId = 'basic_earned';
|
||||||
plan.paymentMethod = amzLib.constants.PAYMENT_METHOD;
|
plan.paymentMethod = amzLib.constants.PAYMENT_METHOD;
|
||||||
@@ -238,9 +242,9 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
expect(sender.sendTxn.firstCall.args[0]._id).to.equal(recipient._id);
|
expect(sender.sendTxn.firstCall.args[0]._id).to.equal(recipient._id);
|
||||||
expect(sender.sendTxn.firstCall.args[1]).to.equal('group-member-join');
|
expect(sender.sendTxn.firstCall.args[1]).to.equal('group-member-join');
|
||||||
expect(sender.sendTxn.firstCall.args[2]).to.eql([
|
expect(sender.sendTxn.firstCall.args[2]).to.eql([
|
||||||
{name: 'LEADER', content: user.profile.name},
|
{ name: 'LEADER', content: user.profile.name },
|
||||||
{name: 'GROUP_NAME', content: group.name},
|
{ name: 'GROUP_NAME', content: group.name },
|
||||||
{name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL},
|
{ name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL },
|
||||||
]);
|
]);
|
||||||
// confirm that the other email sent is not a cancel-subscription email:
|
// confirm that the other email sent is not a cancel-subscription email:
|
||||||
expect(sender.sendTxn.secondCall.args[0]._id).to.equal(group.leader);
|
expect(sender.sendTxn.secondCall.args[0]._id).to.equal(group.leader);
|
||||||
@@ -259,7 +263,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
plan.planId = 'basic_earned';
|
plan.planId = 'basic_earned';
|
||||||
plan.paymentMethod = paypalPayments.constants.PAYMENT_METHOD;
|
plan.paymentMethod = paypalPayments.constants.PAYMENT_METHOD;
|
||||||
@@ -275,9 +279,9 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
expect(sender.sendTxn.firstCall.args[0]._id).to.equal(recipient._id);
|
expect(sender.sendTxn.firstCall.args[0]._id).to.equal(recipient._id);
|
||||||
expect(sender.sendTxn.firstCall.args[1]).to.equal('group-member-join');
|
expect(sender.sendTxn.firstCall.args[1]).to.equal('group-member-join');
|
||||||
expect(sender.sendTxn.firstCall.args[2]).to.eql([
|
expect(sender.sendTxn.firstCall.args[2]).to.eql([
|
||||||
{name: 'LEADER', content: user.profile.name},
|
{ name: 'LEADER', content: user.profile.name },
|
||||||
{name: 'GROUP_NAME', content: group.name},
|
{ name: 'GROUP_NAME', content: group.name },
|
||||||
{name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL},
|
{ name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL },
|
||||||
]);
|
]);
|
||||||
// confirm that the other email sent is not a cancel-subscription email:
|
// confirm that the other email sent is not a cancel-subscription email:
|
||||||
expect(sender.sendTxn.secondCall.args[0]._id).to.equal(group.leader);
|
expect(sender.sendTxn.secondCall.args[0]._id).to.equal(group.leader);
|
||||||
@@ -292,7 +296,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
plan.customerId = 'random';
|
plan.customerId = 'random';
|
||||||
plan.paymentMethod = api.constants.GOOGLE_PAYMENT_METHOD;
|
plan.paymentMethod = api.constants.GOOGLE_PAYMENT_METHOD;
|
||||||
|
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
recipient.purchased.plan = plan;
|
recipient.purchased.plan = plan;
|
||||||
recipient.guilds.push(group._id);
|
recipient.guilds.push(group._id);
|
||||||
@@ -310,9 +314,9 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
expect(sender.sendTxn.args[1][0]._id).to.equal(recipient._id);
|
expect(sender.sendTxn.args[1][0]._id).to.equal(recipient._id);
|
||||||
expect(sender.sendTxn.args[1][1]).to.equal('group-member-join');
|
expect(sender.sendTxn.args[1][1]).to.equal('group-member-join');
|
||||||
expect(sender.sendTxn.args[1][2]).to.eql([
|
expect(sender.sendTxn.args[1][2]).to.eql([
|
||||||
{name: 'LEADER', content: groupLeaderName},
|
{ name: 'LEADER', content: groupLeaderName },
|
||||||
{name: 'GROUP_NAME', content: groupName},
|
{ name: 'GROUP_NAME', content: groupName },
|
||||||
{name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_GOOGLE},
|
{ name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_GOOGLE },
|
||||||
]);
|
]);
|
||||||
expect(sender.sendTxn.args[2][0]._id).to.equal(group.leader);
|
expect(sender.sendTxn.args[2][0]._id).to.equal(group.leader);
|
||||||
expect(sender.sendTxn.args[2][1]).to.equal('group-member-join');
|
expect(sender.sendTxn.args[2][1]).to.equal('group-member-join');
|
||||||
@@ -325,7 +329,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
plan.customerId = 'random';
|
plan.customerId = 'random';
|
||||||
plan.paymentMethod = api.constants.IOS_PAYMENT_METHOD;
|
plan.paymentMethod = api.constants.IOS_PAYMENT_METHOD;
|
||||||
|
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
recipient.purchased.plan = plan;
|
recipient.purchased.plan = plan;
|
||||||
recipient.guilds.push(group._id);
|
recipient.guilds.push(group._id);
|
||||||
@@ -343,9 +347,9 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
expect(sender.sendTxn.args[1][0]._id).to.equal(recipient._id);
|
expect(sender.sendTxn.args[1][0]._id).to.equal(recipient._id);
|
||||||
expect(sender.sendTxn.args[1][1]).to.equal('group-member-join');
|
expect(sender.sendTxn.args[1][1]).to.equal('group-member-join');
|
||||||
expect(sender.sendTxn.args[1][2]).to.eql([
|
expect(sender.sendTxn.args[1][2]).to.eql([
|
||||||
{name: 'LEADER', content: groupLeaderName},
|
{ name: 'LEADER', content: groupLeaderName },
|
||||||
{name: 'GROUP_NAME', content: groupName},
|
{ name: 'GROUP_NAME', content: groupName },
|
||||||
{name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_IOS},
|
{ name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_IOS },
|
||||||
]);
|
]);
|
||||||
expect(sender.sendTxn.args[2][0]._id).to.equal(group.leader);
|
expect(sender.sendTxn.args[2][0]._id).to.equal(group.leader);
|
||||||
expect(sender.sendTxn.args[2][1]).to.equal('group-member-join');
|
expect(sender.sendTxn.args[2][1]).to.equal('group-member-join');
|
||||||
@@ -354,7 +358,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('adds months to members with existing gift subscription', async () => {
|
it('adds months to members with existing gift subscription', async () => {
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
recipient.purchased.plan = plan;
|
recipient.purchased.plan = plan;
|
||||||
recipient.guilds.push(group._id);
|
recipient.guilds.push(group._id);
|
||||||
@@ -378,7 +382,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
const updatedUser = await User.findById(recipient._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.purchased.plan.planId).to.eql('group_plan_auto');
|
expect(updatedUser.purchased.plan.planId).to.eql('group_plan_auto');
|
||||||
expect(updatedUser.purchased.plan.customerId).to.eql('group-plan');
|
expect(updatedUser.purchased.plan.customerId).to.eql('group-plan');
|
||||||
@@ -392,7 +396,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('adds months to members with existing multi-month gift subscription', async () => {
|
it('adds months to members with existing multi-month gift subscription', async () => {
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
recipient.purchased.plan = plan;
|
recipient.purchased.plan = plan;
|
||||||
recipient.guilds.push(group._id);
|
recipient.guilds.push(group._id);
|
||||||
@@ -414,7 +418,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
const updatedUser = await User.findById(recipient._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.purchased.plan.planId).to.eql('group_plan_auto');
|
expect(updatedUser.purchased.plan.planId).to.eql('group_plan_auto');
|
||||||
expect(updatedUser.purchased.plan.customerId).to.eql('group-plan');
|
expect(updatedUser.purchased.plan.customerId).to.eql('group-plan');
|
||||||
@@ -428,7 +432,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('adds months to members with existing recurring subscription (Stripe)', async () => {
|
it('adds months to members with existing recurring subscription (Stripe)', async () => {
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
plan.key = 'basic_earned';
|
plan.key = 'basic_earned';
|
||||||
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
|
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
|
||||||
@@ -450,11 +454,11 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
sinon.stub(amzLib, 'getBillingAgreementDetails')
|
sinon.stub(amzLib, 'getBillingAgreementDetails')
|
||||||
.resolves({
|
.resolves({
|
||||||
BillingAgreementDetails: {
|
BillingAgreementDetails: {
|
||||||
BillingAgreementStatus: {State: 'Closed'},
|
BillingAgreementStatus: { State: 'Closed' },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
plan.planId = 'basic_earned';
|
plan.planId = 'basic_earned';
|
||||||
plan.paymentMethod = amzLib.constants.PAYMENT_METHOD;
|
plan.paymentMethod = amzLib.constants.PAYMENT_METHOD;
|
||||||
@@ -470,7 +474,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
const updatedUser = await User.findById(recipient._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.purchased.plan.extraMonths).to.within(3, 5);
|
expect(updatedUser.purchased.plan.extraMonths).to.within(3, 5);
|
||||||
});
|
});
|
||||||
@@ -485,7 +489,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
plan.planId = 'basic_earned';
|
plan.planId = 'basic_earned';
|
||||||
plan.paymentMethod = paypalPayments.constants.PAYMENT_METHOD;
|
plan.paymentMethod = paypalPayments.constants.PAYMENT_METHOD;
|
||||||
@@ -500,7 +504,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
const updatedUser = await User.findById(recipient._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.purchased.plan.extraMonths).to.within(2, 3);
|
expect(updatedUser.purchased.plan.extraMonths).to.within(2, 3);
|
||||||
paypalPayments.paypalBillingAgreementGet.restore();
|
paypalPayments.paypalBillingAgreementGet.restore();
|
||||||
@@ -511,7 +515,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
it('adds months to members with existing recurring subscription (iOS)');
|
it('adds months to members with existing recurring subscription (iOS)');
|
||||||
|
|
||||||
it('adds months to members who already cancelled but not yet terminated recurring subscription', async () => {
|
it('adds months to members who already cancelled but not yet terminated recurring subscription', async () => {
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
plan.key = 'basic_earned';
|
plan.key = 'basic_earned';
|
||||||
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
|
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
|
||||||
@@ -527,13 +531,13 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
const updatedUser = await User.findById(recipient._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.purchased.plan.extraMonths).to.within(2, 3);
|
expect(updatedUser.purchased.plan.extraMonths).to.within(2, 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('adds months to members who already cancelled but not yet terminated group plan subscription', async () => {
|
it('adds months to members who already cancelled but not yet terminated group plan subscription', async () => {
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
plan.key = 'basic_earned';
|
plan.key = 'basic_earned';
|
||||||
plan.paymentMethod = api.constants.GROUP_PLAN_PAYMENT_METHOD;
|
plan.paymentMethod = api.constants.GROUP_PLAN_PAYMENT_METHOD;
|
||||||
@@ -550,12 +554,12 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
const updatedUser = await User.findById(recipient._id).exec();
|
||||||
expect(updatedUser.purchased.plan.extraMonths).to.within(3, 4);
|
expect(updatedUser.purchased.plan.extraMonths).to.within(3, 4);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('resets date terminated if user has old subscription', async () => {
|
it('resets date terminated if user has old subscription', async () => {
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
plan.key = 'basic_earned';
|
plan.key = 'basic_earned';
|
||||||
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
|
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
|
||||||
@@ -570,13 +574,13 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
const updatedUser = await User.findById(recipient._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.purchased.plan.dateTerminated).to.not.exist;
|
expect(updatedUser.purchased.plan.dateTerminated).to.not.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('adds months to members with existing recurring subscription and includes existing extraMonths', async () => {
|
it('adds months to members with existing recurring subscription and includes existing extraMonths', async () => {
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
plan.key = 'basic_earned';
|
plan.key = 'basic_earned';
|
||||||
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
|
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
|
||||||
@@ -591,13 +595,13 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
const updatedUser = await User.findById(recipient._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.purchased.plan.extraMonths).to.within(7, 9);
|
expect(updatedUser.purchased.plan.extraMonths).to.within(7, 9);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('adds months to members with existing recurring subscription and ignores existing negative extraMonths', async () => {
|
it('adds months to members with existing recurring subscription and ignores existing negative extraMonths', async () => {
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
plan.key = 'basic_earned';
|
plan.key = 'basic_earned';
|
||||||
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
|
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
|
||||||
@@ -612,23 +616,23 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
const updatedUser = await User.findById(recipient._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.purchased.plan.extraMonths).to.within(2, 3);
|
expect(updatedUser.purchased.plan.extraMonths).to.within(2, 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not override gemsBought, mysteryItems, dateCreated, and consective fields', async () => {
|
it('does not override gemsBought, mysteryItems, dateCreated, and consective fields', async () => {
|
||||||
let planCreatedDate = moment().toDate();
|
const planCreatedDate = moment().toDate();
|
||||||
let mysteryItem = {title: 'item'};
|
const mysteryItem = { title: 'item' };
|
||||||
let mysteryItems = [mysteryItem];
|
const mysteryItems = [mysteryItem];
|
||||||
let consecutive = {
|
const consecutive = {
|
||||||
trinkets: 3,
|
trinkets: 3,
|
||||||
gemCapExtra: 20,
|
gemCapExtra: 20,
|
||||||
offset: 1,
|
offset: 1,
|
||||||
count: 13,
|
count: 13,
|
||||||
};
|
};
|
||||||
|
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
|
|
||||||
plan.key = 'basic_earned';
|
plan.key = 'basic_earned';
|
||||||
@@ -647,7 +651,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
const updatedUser = await User.findById(recipient._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.purchased.plan.gemsBought).to.equal(3);
|
expect(updatedUser.purchased.plan.gemsBought).to.equal(3);
|
||||||
expect(updatedUser.purchased.plan.mysteryItems[0]).to.eql(mysteryItem);
|
expect(updatedUser.purchased.plan.mysteryItems[0]).to.eql(mysteryItem);
|
||||||
@@ -659,7 +663,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('does not modify a user with a group subscription when they join another group', async () => {
|
it('does not modify a user with a group subscription when they join another group', async () => {
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
plan.key = 'basic_earned';
|
plan.key = 'basic_earned';
|
||||||
recipient.purchased.plan = plan;
|
recipient.purchased.plan = plan;
|
||||||
@@ -673,10 +677,10 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
let updatedUser = await User.findById(recipient._id).exec();
|
||||||
let firstDateCreated = updatedUser.purchased.plan.dateCreated;
|
const firstDateCreated = updatedUser.purchased.plan.dateCreated;
|
||||||
let extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
|
const extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
|
||||||
|
|
||||||
let group2 = generateGroup({
|
const group2 = generateGroup({
|
||||||
name: 'test group2',
|
name: 'test group2',
|
||||||
type: 'guild',
|
type: 'guild',
|
||||||
privacy: 'public',
|
privacy: 'public',
|
||||||
@@ -703,7 +707,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('does not remove a user who is in two groups plans and leaves one', async () => {
|
it('does not remove a user who is in two groups plans and leaves one', async () => {
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
plan.key = 'basic_earned';
|
plan.key = 'basic_earned';
|
||||||
recipient.purchased.plan = plan;
|
recipient.purchased.plan = plan;
|
||||||
@@ -717,10 +721,10 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
let updatedUser = await User.findById(recipient._id).exec();
|
||||||
let firstDateCreated = updatedUser.purchased.plan.dateCreated;
|
const firstDateCreated = updatedUser.purchased.plan.dateCreated;
|
||||||
let extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
|
const extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
|
||||||
|
|
||||||
let group2 = generateGroup({
|
const group2 = generateGroup({
|
||||||
name: 'test group2',
|
name: 'test group2',
|
||||||
type: 'guild',
|
type: 'guild',
|
||||||
privacy: 'public',
|
privacy: 'public',
|
||||||
@@ -733,7 +737,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedGroup = await Group.findById(group._id).exec();
|
const updatedGroup = await Group.findById(group._id).exec();
|
||||||
await updatedGroup.leave(recipient);
|
await updatedGroup.leave(recipient);
|
||||||
|
|
||||||
updatedUser = await User.findById(recipient._id).exec();
|
updatedUser = await User.findById(recipient._id).exec();
|
||||||
@@ -753,7 +757,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
plan.key = 'basic_earned';
|
plan.key = 'basic_earned';
|
||||||
plan.customerId = api.constants.UNLIMITED_CUSTOMER_ID;
|
plan.customerId = api.constants.UNLIMITED_CUSTOMER_ID;
|
||||||
|
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
recipient.purchased.plan = plan;
|
recipient.purchased.plan = plan;
|
||||||
recipient.guilds.push(group._id);
|
recipient.guilds.push(group._id);
|
||||||
@@ -765,7 +769,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
const updatedUser = await User.findById(recipient._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.purchased.plan.planId).to.eql('basic_3mo');
|
expect(updatedUser.purchased.plan.planId).to.eql('basic_3mo');
|
||||||
expect(updatedUser.purchased.plan.customerId).to.eql(api.constants.UNLIMITED_CUSTOMER_ID);
|
expect(updatedUser.purchased.plan.customerId).to.eql(api.constants.UNLIMITED_CUSTOMER_ID);
|
||||||
@@ -782,7 +786,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
plan.customerId = 'random';
|
plan.customerId = 'random';
|
||||||
plan.paymentMethod = api.constants.GOOGLE_PAYMENT_METHOD;
|
plan.paymentMethod = api.constants.GOOGLE_PAYMENT_METHOD;
|
||||||
|
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
recipient.purchased.plan = plan;
|
recipient.purchased.plan = plan;
|
||||||
recipient.guilds.push(group._id);
|
recipient.guilds.push(group._id);
|
||||||
@@ -794,7 +798,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
const updatedUser = await User.findById(recipient._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.purchased.plan.planId).to.eql('basic_3mo');
|
expect(updatedUser.purchased.plan.planId).to.eql('basic_3mo');
|
||||||
expect(updatedUser.purchased.plan.customerId).to.eql('random');
|
expect(updatedUser.purchased.plan.customerId).to.eql('random');
|
||||||
@@ -811,7 +815,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
plan.customerId = 'random';
|
plan.customerId = 'random';
|
||||||
plan.paymentMethod = api.constants.IOS_PAYMENT_METHOD;
|
plan.paymentMethod = api.constants.IOS_PAYMENT_METHOD;
|
||||||
|
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
recipient.purchased.plan = plan;
|
recipient.purchased.plan = plan;
|
||||||
recipient.guilds.push(group._id);
|
recipient.guilds.push(group._id);
|
||||||
@@ -823,7 +827,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
const updatedUser = await User.findById(recipient._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.purchased.plan.planId).to.eql('basic_3mo');
|
expect(updatedUser.purchased.plan.planId).to.eql('basic_3mo');
|
||||||
expect(updatedUser.purchased.plan.customerId).to.eql('random');
|
expect(updatedUser.purchased.plan.customerId).to.eql('random');
|
||||||
@@ -841,7 +845,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
plan.customerId = api.constants.GROUP_PLAN_CUSTOMER_ID;
|
plan.customerId = api.constants.GROUP_PLAN_CUSTOMER_ID;
|
||||||
plan.dateTerminated = moment().add(1, 'months');
|
plan.dateTerminated = moment().add(1, 'months');
|
||||||
|
|
||||||
let recipient = new User();
|
const recipient = new User();
|
||||||
recipient.profile.name = 'recipient';
|
recipient.profile.name = 'recipient';
|
||||||
recipient.purchased.plan = plan;
|
recipient.purchased.plan = plan;
|
||||||
recipient.guilds.push(group._id);
|
recipient.guilds.push(group._id);
|
||||||
@@ -853,7 +857,7 @@ describe('Purchasing a group plan for group', () => {
|
|||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
let updatedUser = await User.findById(recipient._id).exec();
|
const updatedUser = await User.findById(recipient._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.purchased.plan.planId).to.eql('group_plan_auto');
|
expect(updatedUser.purchased.plan.planId).to.eql('group_plan_auto');
|
||||||
expect(updatedUser.purchased.plan.customerId).to.eql(api.constants.GROUP_PLAN_CUSTOMER_ID);
|
expect(updatedUser.purchased.plan.customerId).to.eql(api.constants.GROUP_PLAN_CUSTOMER_ID);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { model as User } from '../../../../../website/server/models/user';
|
import { model as User } from '../../../../../website/server/models/user';
|
||||||
|
|
||||||
export async function createNonLeaderGroupMember (group) {
|
export async function createNonLeaderGroupMember (group) { // eslint-disable-line import/prefer-default-export, max-len
|
||||||
let nonLeader = new User();
|
const nonLeader = new User();
|
||||||
nonLeader.guilds.push(group._id);
|
nonLeader.guilds.push(group._id);
|
||||||
return await nonLeader.save();
|
return nonLeader.save();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
import * as sender from '../../../../../website/server/libs/email';
|
import * as sender from '../../../../../website/server/libs/email';
|
||||||
import * as api from '../../../../../website/server/libs/payments/payments';
|
import api from '../../../../../website/server/libs/payments/payments';
|
||||||
import analytics from '../../../../../website/server/libs/analyticsService';
|
import * as analytics from '../../../../../website/server/libs/analyticsService';
|
||||||
import notifications from '../../../../../website/server/libs/pushNotifications';
|
import * as notifications from '../../../../../website/server/libs/pushNotifications';
|
||||||
import { model as User } from '../../../../../website/server/models/user';
|
import { model as User } from '../../../../../website/server/models/user';
|
||||||
import { translate as t } from '../../../../helpers/api-integration/v3';
|
import { translate as t } from '../../../../helpers/api-integration/v3';
|
||||||
import {
|
import {
|
||||||
generateGroup,
|
generateGroup,
|
||||||
} from '../../../../helpers/api-unit.helper.js';
|
} from '../../../../helpers/api-unit.helper';
|
||||||
|
|
||||||
describe('payments/index', () => {
|
describe('payments/index', () => {
|
||||||
let user, group, data, plan;
|
let user; let group; let data; let
|
||||||
|
plan;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
user = new User();
|
user = new User();
|
||||||
@@ -102,7 +103,7 @@ describe('payments/index', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('does not set negative extraMonths if plan has past dateTerminated date', async () => {
|
it('does not set negative extraMonths if plan has past dateTerminated date', async () => {
|
||||||
let dateTerminated = moment().subtract(2, 'months').toDate();
|
const dateTerminated = moment().subtract(2, 'months').toDate();
|
||||||
recipient.purchased.plan.dateTerminated = dateTerminated;
|
recipient.purchased.plan.dateTerminated = dateTerminated;
|
||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
@@ -120,7 +121,7 @@ describe('payments/index', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('adds to date terminated for an existing plan with a future terminated date', async () => {
|
it('adds to date terminated for an existing plan with a future terminated date', async () => {
|
||||||
let dateTerminated = moment().add(1, 'months').toDate();
|
const dateTerminated = moment().add(1, 'months').toDate();
|
||||||
recipient.purchased.plan = plan;
|
recipient.purchased.plan = plan;
|
||||||
recipient.purchased.plan.dateTerminated = dateTerminated;
|
recipient.purchased.plan.dateTerminated = dateTerminated;
|
||||||
|
|
||||||
@@ -130,7 +131,7 @@ describe('payments/index', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('replaces date terminated for an account with a past terminated date', async () => {
|
it('replaces date terminated for an account with a past terminated date', async () => {
|
||||||
let dateTerminated = moment().subtract(1, 'months').toDate();
|
const dateTerminated = moment().subtract(1, 'months').toDate();
|
||||||
recipient.purchased.plan.dateTerminated = dateTerminated;
|
recipient.purchased.plan.dateTerminated = dateTerminated;
|
||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
@@ -208,18 +209,21 @@ describe('payments/index', () => {
|
|||||||
|
|
||||||
it('sends a private message about the gift', async () => {
|
it('sends a private message about the gift', async () => {
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
let msg = '\`Hello recipient, sender has sent you 3 months of subscription!\`';
|
const msg = '`Hello recipient, sender has sent you 3 months of subscription!`';
|
||||||
|
|
||||||
expect(user.sendMessage).to.be.calledOnce;
|
expect(user.sendMessage).to.be.calledOnce;
|
||||||
expect(user.sendMessage).to.be.calledWith(recipient, { receiverMsg: msg, senderMsg: msg, save: false });
|
expect(user.sendMessage).to.be.calledWith(
|
||||||
|
recipient,
|
||||||
|
{ receiverMsg: msg, senderMsg: msg, save: false },
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends an email about the gift', async () => {
|
it('sends an email about the gift', async () => {
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
|
|
||||||
expect(sender.sendTxn).to.be.calledWith(recipient, 'gifted-subscription', [
|
expect(sender.sendTxn).to.be.calledWith(recipient, 'gifted-subscription', [
|
||||||
{name: 'GIFTER', content: 'sender'},
|
{ name: 'GIFTER', content: 'sender' },
|
||||||
{name: 'X_MONTHS_SUBSCRIPTION', content: 3},
|
{ name: 'X_MONTHS_SUBSCRIPTION', content: 3 },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -416,8 +420,8 @@ describe('payments/index', () => {
|
|||||||
|
|
||||||
context('Mystery Items', () => {
|
context('Mystery Items', () => {
|
||||||
it('awards mystery items when within the timeframe for a mystery item', async () => {
|
it('awards mystery items when within the timeframe for a mystery item', async () => {
|
||||||
let mayMysteryItemTimeframe = 1464725113000; // May 31st 2016
|
const mayMysteryItemTimeframe = 1464725113000; // May 31st 2016
|
||||||
let fakeClock = sinon.useFakeTimers(mayMysteryItemTimeframe);
|
const fakeClock = sinon.useFakeTimers(mayMysteryItemTimeframe);
|
||||||
|
|
||||||
data = { paymentMethod: 'PaymentMethod', user, sub: { key: 'basic_3mo' } };
|
data = { paymentMethod: 'PaymentMethod', user, sub: { key: 'basic_3mo' } };
|
||||||
|
|
||||||
@@ -437,7 +441,7 @@ describe('payments/index', () => {
|
|||||||
|
|
||||||
it('does not awards mystery items when not within the timeframe for a mystery item', async () => {
|
it('does not awards mystery items when not within the timeframe for a mystery item', async () => {
|
||||||
const noMysteryItemTimeframe = 1462183920000; // May 2nd 2016
|
const noMysteryItemTimeframe = 1462183920000; // May 2nd 2016
|
||||||
let fakeClock = sinon.useFakeTimers(noMysteryItemTimeframe);
|
const fakeClock = sinon.useFakeTimers(noMysteryItemTimeframe);
|
||||||
data = { paymentMethod: 'PaymentMethod', user, sub: { key: 'basic_3mo' } };
|
data = { paymentMethod: 'PaymentMethod', user, sub: { key: 'basic_3mo' } };
|
||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
@@ -449,7 +453,7 @@ describe('payments/index', () => {
|
|||||||
|
|
||||||
it('does not add a notification for mystery items if none was awarded', async () => {
|
it('does not add a notification for mystery items if none was awarded', async () => {
|
||||||
const noMysteryItemTimeframe = 1462183920000; // May 2nd 2016
|
const noMysteryItemTimeframe = 1462183920000; // May 2nd 2016
|
||||||
let fakeClock = sinon.useFakeTimers(noMysteryItemTimeframe);
|
const fakeClock = sinon.useFakeTimers(noMysteryItemTimeframe);
|
||||||
data = { paymentMethod: 'PaymentMethod', user, sub: { key: 'basic_3mo' } };
|
data = { paymentMethod: 'PaymentMethod', user, sub: { key: 'basic_3mo' } };
|
||||||
|
|
||||||
await api.createSubscription(data);
|
await api.createSubscription(data);
|
||||||
@@ -461,9 +465,9 @@ describe('payments/index', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('does not award mystery item when user already owns the item', async () => {
|
it('does not award mystery item when user already owns the item', async () => {
|
||||||
let mayMysteryItemTimeframe = 1464725113000; // May 31st 2016
|
const mayMysteryItemTimeframe = 1464725113000; // May 31st 2016
|
||||||
let fakeClock = sinon.useFakeTimers(mayMysteryItemTimeframe);
|
const fakeClock = sinon.useFakeTimers(mayMysteryItemTimeframe);
|
||||||
let mayMysteryItem = 'armor_mystery_201605';
|
const mayMysteryItem = 'armor_mystery_201605';
|
||||||
user.items.gear.owned[mayMysteryItem] = true;
|
user.items.gear.owned[mayMysteryItem] = true;
|
||||||
|
|
||||||
data = { paymentMethod: 'PaymentMethod', user, sub: { key: 'basic_3mo' } };
|
data = { paymentMethod: 'PaymentMethod', user, sub: { key: 'basic_3mo' } };
|
||||||
@@ -477,9 +481,9 @@ describe('payments/index', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('does not award mystery item when user already has the item in the mystery box', async () => {
|
it('does not award mystery item when user already has the item in the mystery box', async () => {
|
||||||
let mayMysteryItemTimeframe = 1464725113000; // May 31st 2016
|
const mayMysteryItemTimeframe = 1464725113000; // May 31st 2016
|
||||||
let fakeClock = sinon.useFakeTimers(mayMysteryItemTimeframe);
|
const fakeClock = sinon.useFakeTimers(mayMysteryItemTimeframe);
|
||||||
let mayMysteryItem = 'armor_mystery_201605';
|
const mayMysteryItem = 'armor_mystery_201605';
|
||||||
user.purchased.plan.mysteryItems = [mayMysteryItem];
|
user.purchased.plan.mysteryItems = [mayMysteryItem];
|
||||||
|
|
||||||
sandbox.spy(user.purchased.plan.mysteryItems, 'push');
|
sandbox.spy(user.purchased.plan.mysteryItems, 'push');
|
||||||
@@ -504,8 +508,8 @@ describe('payments/index', () => {
|
|||||||
it('adds a month termination date by default', async () => {
|
it('adds a month termination date by default', async () => {
|
||||||
await api.cancelSubscription(data);
|
await api.cancelSubscription(data);
|
||||||
|
|
||||||
let now = new Date();
|
const now = new Date();
|
||||||
let daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
|
const daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
|
||||||
|
|
||||||
expect(daysTillTermination).to.be.within(29, 30); // 1 month +/- 1 days
|
expect(daysTillTermination).to.be.within(29, 30); // 1 month +/- 1 days
|
||||||
});
|
});
|
||||||
@@ -515,8 +519,8 @@ describe('payments/index', () => {
|
|||||||
|
|
||||||
await api.cancelSubscription(data);
|
await api.cancelSubscription(data);
|
||||||
|
|
||||||
let now = new Date();
|
const now = new Date();
|
||||||
let daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
|
const daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
|
||||||
|
|
||||||
expect(daysTillTermination).to.be.within(89, 90); // 3 months +/- 1 days
|
expect(daysTillTermination).to.be.within(89, 90); // 3 months +/- 1 days
|
||||||
});
|
});
|
||||||
@@ -526,8 +530,8 @@ describe('payments/index', () => {
|
|||||||
|
|
||||||
await api.cancelSubscription(data);
|
await api.cancelSubscription(data);
|
||||||
|
|
||||||
let now = new Date();
|
const now = new Date();
|
||||||
let daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
|
const daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
|
||||||
|
|
||||||
expect(daysTillTermination).to.be.within(38, 39); // should be about 1 month + 1/3 month
|
expect(daysTillTermination).to.be.within(38, 39); // should be about 1 month + 1/3 month
|
||||||
});
|
});
|
||||||
@@ -537,8 +541,8 @@ describe('payments/index', () => {
|
|||||||
|
|
||||||
await api.cancelSubscription(data);
|
await api.cancelSubscription(data);
|
||||||
|
|
||||||
let now = new Date();
|
const now = new Date();
|
||||||
let daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
|
const daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
|
||||||
|
|
||||||
expect(daysTillTermination).to.be.within(13, 15);
|
expect(daysTillTermination).to.be.within(13, 15);
|
||||||
});
|
});
|
||||||
@@ -549,8 +553,8 @@ describe('payments/index', () => {
|
|||||||
|
|
||||||
await api.cancelSubscription(data);
|
await api.cancelSubscription(data);
|
||||||
|
|
||||||
let now = new Date();
|
const now = new Date();
|
||||||
let daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
|
const daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
|
||||||
|
|
||||||
expect(daysTillTermination).to.be.within(13, 15);
|
expect(daysTillTermination).to.be.within(13, 15);
|
||||||
});
|
});
|
||||||
@@ -641,9 +645,10 @@ describe('payments/index', () => {
|
|||||||
|
|
||||||
it('sends a message from purchaser to recipient', async () => {
|
it('sends a message from purchaser to recipient', async () => {
|
||||||
await api.buyGems(data);
|
await api.buyGems(data);
|
||||||
let msg = '\`Hello recipient, sender has sent you 4 gems!\`';
|
const msg = '`Hello recipient, sender has sent you 4 gems!`';
|
||||||
|
|
||||||
expect(user.sendMessage).to.be.calledWith(recipient, { receiverMsg: msg, senderMsg: msg, save: false });
|
expect(user.sendMessage).to.be
|
||||||
|
.calledWith(recipient, { receiverMsg: msg, senderMsg: msg, save: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends a message from purchaser to recipient wtih custom message', async () => {
|
it('sends a message from purchaser to recipient wtih custom message', async () => {
|
||||||
@@ -652,7 +657,8 @@ describe('payments/index', () => {
|
|||||||
await api.buyGems(data);
|
await api.buyGems(data);
|
||||||
|
|
||||||
const msg = `\`Hello recipient, sender has sent you 4 gems!\` ${data.gift.message}`;
|
const msg = `\`Hello recipient, sender has sent you 4 gems!\` ${data.gift.message}`;
|
||||||
expect(user.sendMessage).to.be.calledWith(recipient, { receiverMsg: msg, senderMsg: msg, save: false });
|
expect(user.sendMessage).to.be
|
||||||
|
.calledWith(recipient, { receiverMsg: msg, senderMsg: msg, save: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends a push notification if user did not gift to self', async () => {
|
it('sends a push notification if user did not gift to self', async () => {
|
||||||
@@ -671,8 +677,8 @@ describe('payments/index', () => {
|
|||||||
});
|
});
|
||||||
await api.buyGems(data);
|
await api.buyGems(data);
|
||||||
|
|
||||||
let [recipientsMessageContent, sendersMessageContent] = ['en', 'en'].map((lang) => {
|
const [recipientsMessageContent, sendersMessageContent] = ['en', 'en'].map(lang => {
|
||||||
let messageContent = t('giftedGemsFull', {
|
const messageContent = t('giftedGemsFull', {
|
||||||
username: recipient.profile.name,
|
username: recipient.profile.name,
|
||||||
sender: user.profile.name,
|
sender: user.profile.name,
|
||||||
gemAmount: data.gift.gems.amount,
|
gemAmount: data.gift.gems.amount,
|
||||||
@@ -681,7 +687,10 @@ describe('payments/index', () => {
|
|||||||
return `\`${messageContent}\``;
|
return `\`${messageContent}\``;
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(user.sendMessage).to.be.calledWith(recipient, { receiverMsg: recipientsMessageContent, senderMsg: sendersMessageContent, save: false });
|
expect(user.sendMessage).to.be.calledWith(
|
||||||
|
recipient,
|
||||||
|
{ receiverMsg: recipientsMessageContent, senderMsg: sendersMessageContent, save: false },
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -693,7 +702,7 @@ describe('payments/index', () => {
|
|||||||
|
|
||||||
await api.addSubToGroupUser(user, group);
|
await api.addSubToGroupUser(user, group);
|
||||||
|
|
||||||
let updatedUser = await User.findById(user._id).exec();
|
const updatedUser = await User.findById(user._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.purchased.plan.planId).to.eql('group_plan_auto');
|
expect(updatedUser.purchased.plan.planId).to.eql('group_plan_auto');
|
||||||
expect(updatedUser.purchased.plan.customerId).to.eql('group-plan');
|
expect(updatedUser.purchased.plan.customerId).to.eql('group-plan');
|
||||||
@@ -709,17 +718,17 @@ describe('payments/index', () => {
|
|||||||
it('awards the Royal Purple Jackalope pet', async () => {
|
it('awards the Royal Purple Jackalope pet', async () => {
|
||||||
await api.addSubToGroupUser(user, group);
|
await api.addSubToGroupUser(user, group);
|
||||||
|
|
||||||
let updatedUser = await User.findById(user._id).exec();
|
const updatedUser = await User.findById(user._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.items.pets['Jackalope-RoyalPurple']).to.eql(5);
|
expect(updatedUser.items.pets['Jackalope-RoyalPurple']).to.eql(5);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('saves previously unused Mystery Items and Hourglasses for an expired subscription', async () => {
|
it('saves previously unused Mystery Items and Hourglasses for an expired subscription', async () => {
|
||||||
let planExpirationDate = new Date();
|
const planExpirationDate = new Date();
|
||||||
planExpirationDate.setDate(planExpirationDate.getDate() - 2);
|
planExpirationDate.setDate(planExpirationDate.getDate() - 2);
|
||||||
let mysteryItem = 'item';
|
const mysteryItem = 'item';
|
||||||
let mysteryItems = [mysteryItem];
|
const mysteryItems = [mysteryItem];
|
||||||
let consecutive = {
|
const consecutive = {
|
||||||
trinkets: 3,
|
trinkets: 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -735,7 +744,7 @@ describe('payments/index', () => {
|
|||||||
await user.save();
|
await user.save();
|
||||||
await api.addSubToGroupUser(user, group);
|
await api.addSubToGroupUser(user, group);
|
||||||
|
|
||||||
let updatedUser = await User.findById(user._id).exec();
|
const updatedUser = await User.findById(user._id).exec();
|
||||||
|
|
||||||
expect(updatedUser.purchased.plan.mysteryItems[0]).to.eql(mysteryItem);
|
expect(updatedUser.purchased.plan.mysteryItems[0]).to.eql(mysteryItem);
|
||||||
expect(updatedUser.purchased.plan.consecutive.trinkets).to.equal(consecutive.trinkets);
|
expect(updatedUser.purchased.plan.consecutive.trinkets).to.equal(consecutive.trinkets);
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import { model as User } from '../../../../../../website/server/models/user';
|
|||||||
|
|
||||||
describe('checkout success', () => {
|
describe('checkout success', () => {
|
||||||
const subKey = 'basic_3mo';
|
const subKey = 'basic_3mo';
|
||||||
let user, gift, customerId, paymentId;
|
let user; let gift; let customerId; let
|
||||||
let paypalPaymentExecuteStub, paymentBuyGemsStub, paymentsCreateSubscritionStub;
|
paymentId;
|
||||||
|
let paypalPaymentExecuteStub; let paymentBuyGemsStub; let
|
||||||
|
paymentsCreateSubscritionStub;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
user = new User();
|
user = new User();
|
||||||
@@ -25,7 +27,9 @@ describe('checkout success', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('purchases gems', async () => {
|
it('purchases gems', async () => {
|
||||||
await paypalPayments.checkoutSuccess({user, gift, paymentId, customerId});
|
await paypalPayments.checkoutSuccess({
|
||||||
|
user, gift, paymentId, customerId,
|
||||||
|
});
|
||||||
|
|
||||||
expect(paypalPaymentExecuteStub).to.be.calledOnce;
|
expect(paypalPaymentExecuteStub).to.be.calledOnce;
|
||||||
expect(paypalPaymentExecuteStub).to.be.calledWith(paymentId, { payer_id: customerId });
|
expect(paypalPaymentExecuteStub).to.be.calledWith(paymentId, { payer_id: customerId });
|
||||||
@@ -38,7 +42,7 @@ describe('checkout success', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('gifts gems', async () => {
|
it('gifts gems', async () => {
|
||||||
let receivingUser = new User();
|
const receivingUser = new User();
|
||||||
await receivingUser.save();
|
await receivingUser.save();
|
||||||
gift = {
|
gift = {
|
||||||
type: 'gems',
|
type: 'gems',
|
||||||
@@ -48,7 +52,9 @@ describe('checkout success', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
await paypalPayments.checkoutSuccess({user, gift, paymentId, customerId});
|
await paypalPayments.checkoutSuccess({
|
||||||
|
user, gift, paymentId, customerId,
|
||||||
|
});
|
||||||
|
|
||||||
expect(paypalPaymentExecuteStub).to.be.calledOnce;
|
expect(paypalPaymentExecuteStub).to.be.calledOnce;
|
||||||
expect(paypalPaymentExecuteStub).to.be.calledWith(paymentId, { payer_id: customerId });
|
expect(paypalPaymentExecuteStub).to.be.calledWith(paymentId, { payer_id: customerId });
|
||||||
@@ -62,7 +68,7 @@ describe('checkout success', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('gifts subscription', async () => {
|
it('gifts subscription', async () => {
|
||||||
let receivingUser = new User();
|
const receivingUser = new User();
|
||||||
await receivingUser.save();
|
await receivingUser.save();
|
||||||
gift = {
|
gift = {
|
||||||
type: 'subscription',
|
type: 'subscription',
|
||||||
@@ -72,7 +78,9 @@ describe('checkout success', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
await paypalPayments.checkoutSuccess({user, gift, paymentId, customerId});
|
await paypalPayments.checkoutSuccess({
|
||||||
|
user, gift, paymentId, customerId,
|
||||||
|
});
|
||||||
|
|
||||||
expect(paypalPaymentExecuteStub).to.be.calledOnce;
|
expect(paypalPaymentExecuteStub).to.be.calledOnce;
|
||||||
expect(paypalPaymentExecuteStub).to.be.calledWith(paymentId, { payer_id: customerId });
|
expect(paypalPaymentExecuteStub).to.be.calledWith(paymentId, { payer_id: customerId });
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { model as User } from '../../../../../../website/server/models/user';
|
|||||||
import common from '../../../../../../website/common';
|
import common from '../../../../../../website/common';
|
||||||
|
|
||||||
const BASE_URL = nconf.get('BASE_URL');
|
const BASE_URL = nconf.get('BASE_URL');
|
||||||
const i18n = common.i18n;
|
const { i18n } = common;
|
||||||
|
|
||||||
describe('checkout', () => {
|
describe('checkout', () => {
|
||||||
const subKey = 'basic_3mo';
|
const subKey = 'basic_3mo';
|
||||||
@@ -53,7 +53,7 @@ describe('checkout', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('creates a link for gem purchases', async () => {
|
it('creates a link for gem purchases', async () => {
|
||||||
let link = await paypalPayments.checkout({user: new User()});
|
const link = await paypalPayments.checkout({ user: new User() });
|
||||||
|
|
||||||
expect(paypalPaymentCreateStub).to.be.calledOnce;
|
expect(paypalPaymentCreateStub).to.be.calledOnce;
|
||||||
expect(paypalPaymentCreateStub).to.be.calledWith(getPaypalCreateOptions('Habitica Gems', 5.00));
|
expect(paypalPaymentCreateStub).to.be.calledWith(getPaypalCreateOptions('Habitica Gems', 5.00));
|
||||||
@@ -61,9 +61,9 @@ describe('checkout', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should error if gem amount is too low', async () => {
|
it('should error if gem amount is too low', async () => {
|
||||||
let receivingUser = new User();
|
const receivingUser = new User();
|
||||||
receivingUser.save();
|
receivingUser.save();
|
||||||
let gift = {
|
const gift = {
|
||||||
type: 'gems',
|
type: 'gems',
|
||||||
gems: {
|
gems: {
|
||||||
amount: 0,
|
amount: 0,
|
||||||
@@ -71,7 +71,7 @@ describe('checkout', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
await expect(paypalPayments.checkout({gift}))
|
await expect(paypalPayments.checkout({ gift }))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 400,
|
httpCode: 400,
|
||||||
message: 'Amount must be at least 1.',
|
message: 'Amount must be at least 1.',
|
||||||
@@ -80,10 +80,10 @@ describe('checkout', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should error if the user cannot get gems', async () => {
|
it('should error if the user cannot get gems', async () => {
|
||||||
let user = new User();
|
const user = new User();
|
||||||
sinon.stub(user, 'canGetGems').resolves(false);
|
sinon.stub(user, 'canGetGems').resolves(false);
|
||||||
|
|
||||||
await expect(paypalPayments.checkout({user})).to.eventually.be.rejected.and.to.eql({
|
await expect(paypalPayments.checkout({ user })).to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
message: i18n.t('groupPolicyCannotGetGems'),
|
message: i18n.t('groupPolicyCannotGetGems'),
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -91,9 +91,9 @@ describe('checkout', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('creates a link for gifting gems', async () => {
|
it('creates a link for gifting gems', async () => {
|
||||||
let receivingUser = new User();
|
const receivingUser = new User();
|
||||||
await receivingUser.save();
|
await receivingUser.save();
|
||||||
let gift = {
|
const gift = {
|
||||||
type: 'gems',
|
type: 'gems',
|
||||||
uuid: receivingUser._id,
|
uuid: receivingUser._id,
|
||||||
gems: {
|
gems: {
|
||||||
@@ -101,7 +101,7 @@ describe('checkout', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let link = await paypalPayments.checkout({gift});
|
const link = await paypalPayments.checkout({ gift });
|
||||||
|
|
||||||
expect(paypalPaymentCreateStub).to.be.calledOnce;
|
expect(paypalPaymentCreateStub).to.be.calledOnce;
|
||||||
expect(paypalPaymentCreateStub).to.be.calledWith(getPaypalCreateOptions('Habitica Gems (Gift)', '4.00'));
|
expect(paypalPaymentCreateStub).to.be.calledWith(getPaypalCreateOptions('Habitica Gems (Gift)', '4.00'));
|
||||||
@@ -109,9 +109,9 @@ describe('checkout', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('creates a link for gifting a subscription', async () => {
|
it('creates a link for gifting a subscription', async () => {
|
||||||
let receivingUser = new User();
|
const receivingUser = new User();
|
||||||
receivingUser.save();
|
receivingUser.save();
|
||||||
let gift = {
|
const gift = {
|
||||||
type: 'subscription',
|
type: 'subscription',
|
||||||
subscription: {
|
subscription: {
|
||||||
key: subKey,
|
key: subKey,
|
||||||
@@ -119,7 +119,7 @@ describe('checkout', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let link = await paypalPayments.checkout({gift});
|
const link = await paypalPayments.checkout({ gift });
|
||||||
|
|
||||||
expect(paypalPaymentCreateStub).to.be.calledOnce;
|
expect(paypalPaymentCreateStub).to.be.calledOnce;
|
||||||
expect(paypalPaymentCreateStub).to.be.calledWith(getPaypalCreateOptions('mo. Habitica Subscription (Gift)', '15.00'));
|
expect(paypalPaymentCreateStub).to.be.calledWith(getPaypalCreateOptions('mo. Habitica Subscription (Gift)', '15.00'));
|
||||||
|
|||||||
@@ -3,13 +3,15 @@ import paypalPayments from '../../../../../../website/server/libs/payments/paypa
|
|||||||
import payments from '../../../../../../website/server/libs/payments/payments';
|
import payments from '../../../../../../website/server/libs/payments/payments';
|
||||||
import {
|
import {
|
||||||
generateGroup,
|
generateGroup,
|
||||||
} from '../../../../../helpers/api-unit.helper.js';
|
} from '../../../../../helpers/api-unit.helper';
|
||||||
import { model as User } from '../../../../../../website/server/models/user';
|
import { model as User } from '../../../../../../website/server/models/user';
|
||||||
|
|
||||||
describe('ipn', () => {
|
describe('ipn', () => {
|
||||||
const subKey = 'basic_3mo';
|
const subKey = 'basic_3mo';
|
||||||
let user, group, txn_type, userPaymentId, groupPaymentId;
|
let user; let group; let txn_type; let userPaymentId; let
|
||||||
let ipnVerifyAsyncStub, paymentCancelSubscriptionSpy;
|
groupPaymentId;
|
||||||
|
let ipnVerifyAsyncStub; let
|
||||||
|
paymentCancelSubscriptionSpy;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
txn_type = 'recurring_payment_profile_cancel';
|
txn_type = 'recurring_payment_profile_cancel';
|
||||||
@@ -38,16 +40,16 @@ describe('ipn', () => {
|
|||||||
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
|
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(() => {
|
||||||
paypalPayments.ipnVerifyAsync.restore();
|
paypalPayments.ipnVerifyAsync.restore();
|
||||||
payments.cancelSubscription.restore();
|
payments.cancelSubscription.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should cancel a user subscription', async () => {
|
it('should cancel a user subscription', async () => {
|
||||||
await paypalPayments.ipn({txn_type, recurring_payment_id: userPaymentId});
|
await paypalPayments.ipn({ txn_type, recurring_payment_id: userPaymentId });
|
||||||
|
|
||||||
expect(ipnVerifyAsyncStub).to.be.calledOnce;
|
expect(ipnVerifyAsyncStub).to.be.calledOnce;
|
||||||
expect(ipnVerifyAsyncStub).to.be.calledWith({txn_type, recurring_payment_id: userPaymentId});
|
expect(ipnVerifyAsyncStub).to.be.calledWith({ txn_type, recurring_payment_id: userPaymentId });
|
||||||
|
|
||||||
expect(paymentCancelSubscriptionSpy).to.be.calledOnce;
|
expect(paymentCancelSubscriptionSpy).to.be.calledOnce;
|
||||||
expect(paymentCancelSubscriptionSpy.args[0][0].user._id).to.eql(user._id);
|
expect(paymentCancelSubscriptionSpy.args[0][0].user._id).to.eql(user._id);
|
||||||
@@ -55,10 +57,10 @@ describe('ipn', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should cancel a group subscription', async () => {
|
it('should cancel a group subscription', async () => {
|
||||||
await paypalPayments.ipn({txn_type, recurring_payment_id: groupPaymentId});
|
await paypalPayments.ipn({ txn_type, recurring_payment_id: groupPaymentId });
|
||||||
|
|
||||||
expect(ipnVerifyAsyncStub).to.be.calledOnce;
|
expect(ipnVerifyAsyncStub).to.be.calledOnce;
|
||||||
expect(ipnVerifyAsyncStub).to.be.calledWith({txn_type, recurring_payment_id: groupPaymentId});
|
expect(ipnVerifyAsyncStub).to.be.calledWith({ txn_type, recurring_payment_id: groupPaymentId });
|
||||||
|
|
||||||
expect(paymentCancelSubscriptionSpy).to.be.calledOnce;
|
expect(paymentCancelSubscriptionSpy).to.be.calledOnce;
|
||||||
expect(paymentCancelSubscriptionSpy).to.be.calledWith({ groupId: group._id, paymentMethod: 'Paypal' });
|
expect(paymentCancelSubscriptionSpy).to.be.calledWith({ groupId: group._id, paymentMethod: 'Paypal' });
|
||||||
|
|||||||
@@ -3,17 +3,19 @@ import paypalPayments from '../../../../../../website/server/libs/payments/paypa
|
|||||||
import payments from '../../../../../../website/server/libs/payments/payments';
|
import payments from '../../../../../../website/server/libs/payments/payments';
|
||||||
import {
|
import {
|
||||||
generateGroup,
|
generateGroup,
|
||||||
} from '../../../../../helpers/api-unit.helper.js';
|
} from '../../../../../helpers/api-unit.helper';
|
||||||
import { model as User } from '../../../../../../website/server/models/user';
|
import { model as User } from '../../../../../../website/server/models/user';
|
||||||
import common from '../../../../../../website/common';
|
import common from '../../../../../../website/common';
|
||||||
import { createNonLeaderGroupMember } from '../paymentHelpers';
|
import { createNonLeaderGroupMember } from '../paymentHelpers';
|
||||||
|
|
||||||
const i18n = common.i18n;
|
const { i18n } = common;
|
||||||
|
|
||||||
describe('subscribeCancel', () => {
|
describe('subscribeCancel', () => {
|
||||||
const subKey = 'basic_3mo';
|
const subKey = 'basic_3mo';
|
||||||
let user, group, groupId, customerId, groupCustomerId, nextBillingDate;
|
let user; let group; let groupId; let customerId; let groupCustomerId; let
|
||||||
let paymentCancelSubscriptionSpy, paypalBillingAgreementCancelStub, paypalBillingAgreementGetStub;
|
nextBillingDate;
|
||||||
|
let paymentCancelSubscriptionSpy; let paypalBillingAgreementCancelStub; let
|
||||||
|
paypalBillingAgreementGetStub;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
customerId = 'customer-id';
|
customerId = 'customer-id';
|
||||||
@@ -49,7 +51,7 @@ describe('subscribeCancel', () => {
|
|||||||
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
|
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(() => {
|
||||||
paypalPayments.paypalBillingAgreementGet.restore();
|
paypalPayments.paypalBillingAgreementGet.restore();
|
||||||
paypalPayments.paypalBillingAgreementCancel.restore();
|
paypalPayments.paypalBillingAgreementCancel.restore();
|
||||||
payments.cancelSubscription.restore();
|
payments.cancelSubscription.restore();
|
||||||
@@ -58,7 +60,7 @@ describe('subscribeCancel', () => {
|
|||||||
it('should throw an error if we are missing a subscription', async () => {
|
it('should throw an error if we are missing a subscription', async () => {
|
||||||
user.purchased.plan.customerId = undefined;
|
user.purchased.plan.customerId = undefined;
|
||||||
|
|
||||||
await expect(paypalPayments.subscribeCancel({user}))
|
await expect(paypalPayments.subscribeCancel({ user }))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -67,7 +69,7 @@ describe('subscribeCancel', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if group is not found', async () => {
|
it('should throw an error if group is not found', async () => {
|
||||||
await expect(paypalPayments.subscribeCancel({user, groupId: 'fake-id'}))
|
await expect(paypalPayments.subscribeCancel({ user, groupId: 'fake-id' }))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 404,
|
httpCode: 404,
|
||||||
name: 'NotFound',
|
name: 'NotFound',
|
||||||
@@ -76,9 +78,9 @@ describe('subscribeCancel', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if user is not group leader', async () => {
|
it('should throw an error if user is not group leader', async () => {
|
||||||
let nonLeader = await createNonLeaderGroupMember(group);
|
const nonLeader = await createNonLeaderGroupMember(group);
|
||||||
|
|
||||||
await expect(paypalPayments.subscribeCancel({user: nonLeader, groupId: group._id}))
|
await expect(paypalPayments.subscribeCancel({ user: nonLeader, groupId: group._id }))
|
||||||
.to.eventually.be.rejected.and.to.eql({
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
httpCode: 401,
|
httpCode: 401,
|
||||||
name: 'NotAuthorized',
|
name: 'NotAuthorized',
|
||||||
@@ -87,7 +89,7 @@ describe('subscribeCancel', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should cancel a user subscription', async () => {
|
it('should cancel a user subscription', async () => {
|
||||||
await paypalPayments.subscribeCancel({user});
|
await paypalPayments.subscribeCancel({ user });
|
||||||
|
|
||||||
expect(paypalBillingAgreementGetStub).to.be.calledOnce;
|
expect(paypalBillingAgreementGetStub).to.be.calledOnce;
|
||||||
expect(paypalBillingAgreementGetStub).to.be.calledWith(customerId);
|
expect(paypalBillingAgreementGetStub).to.be.calledWith(customerId);
|
||||||
@@ -105,7 +107,7 @@ describe('subscribeCancel', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should cancel a group subscription', async () => {
|
it('should cancel a group subscription', async () => {
|
||||||
await paypalPayments.subscribeCancel({user, groupId: group._id});
|
await paypalPayments.subscribeCancel({ user, groupId: group._id });
|
||||||
|
|
||||||
expect(paypalBillingAgreementGetStub).to.be.calledOnce;
|
expect(paypalBillingAgreementGetStub).to.be.calledOnce;
|
||||||
expect(paypalBillingAgreementGetStub).to.be.calledWith(groupCustomerId);
|
expect(paypalBillingAgreementGetStub).to.be.calledWith(groupCustomerId);
|
||||||
|
|||||||
@@ -3,14 +3,16 @@ import paypalPayments from '../../../../../../website/server/libs/payments/paypa
|
|||||||
import payments from '../../../../../../website/server/libs/payments/payments';
|
import payments from '../../../../../../website/server/libs/payments/payments';
|
||||||
import {
|
import {
|
||||||
generateGroup,
|
generateGroup,
|
||||||
} from '../../../../../helpers/api-unit.helper.js';
|
} from '../../../../../helpers/api-unit.helper';
|
||||||
import { model as User } from '../../../../../../website/server/models/user';
|
import { model as User } from '../../../../../../website/server/models/user';
|
||||||
import common from '../../../../../../website/common';
|
import common from '../../../../../../website/common';
|
||||||
|
|
||||||
describe('subscribeSuccess', () => {
|
describe('subscribeSuccess', () => {
|
||||||
const subKey = 'basic_3mo';
|
const subKey = 'basic_3mo';
|
||||||
let user, group, block, groupId, token, headers, customerId;
|
let user; let group; let block; let groupId; let token; let headers; let
|
||||||
let paypalBillingAgreementExecuteStub, paymentsCreateSubscritionStub;
|
customerId;
|
||||||
|
let paypalBillingAgreementExecuteStub; let
|
||||||
|
paymentsCreateSubscritionStub;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
user = new User();
|
user = new User();
|
||||||
@@ -40,7 +42,9 @@ describe('subscribeSuccess', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('creates a user subscription', async () => {
|
it('creates a user subscription', async () => {
|
||||||
await paypalPayments.subscribeSuccess({user, block, groupId, token, headers});
|
await paypalPayments.subscribeSuccess({
|
||||||
|
user, block, groupId, token, headers,
|
||||||
|
});
|
||||||
|
|
||||||
expect(paypalBillingAgreementExecuteStub).to.be.calledOnce;
|
expect(paypalBillingAgreementExecuteStub).to.be.calledOnce;
|
||||||
expect(paypalBillingAgreementExecuteStub).to.be.calledWith(token, {});
|
expect(paypalBillingAgreementExecuteStub).to.be.calledWith(token, {});
|
||||||
@@ -59,7 +63,9 @@ describe('subscribeSuccess', () => {
|
|||||||
it('create a group subscription', async () => {
|
it('create a group subscription', async () => {
|
||||||
groupId = group._id;
|
groupId = group._id;
|
||||||
|
|
||||||
await paypalPayments.subscribeSuccess({user, block, groupId, token, headers});
|
await paypalPayments.subscribeSuccess({
|
||||||
|
user, block, groupId, token, headers,
|
||||||
|
});
|
||||||
|
|
||||||
expect(paypalBillingAgreementExecuteStub).to.be.calledOnce;
|
expect(paypalBillingAgreementExecuteStub).to.be.calledOnce;
|
||||||
expect(paypalBillingAgreementExecuteStub).to.be.calledWith(token, {});
|
expect(paypalBillingAgreementExecuteStub).to.be.calledWith(token, {});
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user