Merge branch 'develop' into release
|
|
@ -14,7 +14,7 @@ files:
|
|||
owner: root
|
||||
group: users
|
||||
content: |
|
||||
$(ls -td /opt/elasticbeanstalk/node-install/node-* | head -1)/bin/npm install -g npm@4
|
||||
$(ls -td /opt/elasticbeanstalk/node-install/node-* | head -1)/bin/npm install -g npm@5
|
||||
container_commands:
|
||||
01_makeBabel:
|
||||
command: "touch /tmp/.babel.json"
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ addons:
|
|||
- g++-4.8
|
||||
before_install:
|
||||
- $CXX --version
|
||||
- npm install -g npm@4
|
||||
- npm install -g npm@5
|
||||
- if [ $REQUIRES_SERVER ]; then sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10; echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list; sudo apt-get update; sudo apt-get install mongodb-org-server; fi
|
||||
install:
|
||||
- npm install &> npm.install.log || (cat npm.install.log; false)
|
||||
|
|
@ -34,6 +34,5 @@ env:
|
|||
- TEST="test:sanity"
|
||||
- TEST="test:content" COVERAGE=true
|
||||
- TEST="test:common" COVERAGE=true
|
||||
- TEST="test:karma" COVERAGE=true
|
||||
- TEST="client:unit" COVERAGE=true
|
||||
- TEST="apidoc"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
FROM node:boron
|
||||
|
||||
# Upgrade NPM to v5 (Yarn is needed because of this bug https://github.com/npm/npm/issues/16807)
|
||||
# The used solution is suggested here https://github.com/npm/npm/issues/16807#issuecomment-313591975
|
||||
RUN yarn global add npm@5
|
||||
# Install global packages
|
||||
RUN npm install -g gulp grunt-cli bower mocha
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
FROM node:boron
|
||||
|
||||
# Upgrade NPM to v5 (Yarn is needed because of this bug https://github.com/npm/npm/issues/16807)
|
||||
# The used solution is suggested here https://github.com/npm/npm/issues/16807#issuecomment-313591975
|
||||
RUN yarn global add npm@5
|
||||
# Install global packages
|
||||
RUN npm install -g gulp grunt-cli bower mocha
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import gulp from 'gulp';
|
||||
import runSequence from 'run-sequence';
|
||||
import babel from 'gulp-babel';
|
||||
import webpackProductionBuild from '../webpack/build';
|
||||
require('gulp-grunt')(gulp);
|
||||
|
||||
gulp.task('build', () => {
|
||||
|
|
@ -25,6 +26,14 @@ gulp.task('build:common', () => {
|
|||
|
||||
gulp.task('build:server', ['build:src', 'build:common']);
|
||||
|
||||
// Client Production Build
|
||||
gulp.task('build:client', ['bootstrap'], (done) => {
|
||||
webpackProductionBuild((err, output) => {
|
||||
if (err) return done(err);
|
||||
console.log(output);
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('build:dev', ['browserify', 'prepare:staticNewStuff'], (done) => {
|
||||
gulp.start('grunt-build:dev', done);
|
||||
});
|
||||
|
|
@ -33,7 +42,12 @@ gulp.task('build:dev:watch', ['build:dev'], () => {
|
|||
gulp.watch(['website/client-old/**/*.styl', 'website/common/script/*']);
|
||||
});
|
||||
|
||||
gulp.task('build:prod', ['browserify', 'build:server', 'prepare:staticNewStuff'], (done) => {
|
||||
gulp.task('build:prod', [
|
||||
'browserify',
|
||||
'build:server',
|
||||
'prepare:staticNewStuff',
|
||||
'build:client',
|
||||
], (done) => {
|
||||
runSequence(
|
||||
'grunt-build:prod',
|
||||
'apidoc',
|
||||
|
|
|
|||
97
migrations/20170928_redesign_guilds.js
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
var migrationName = '20170928_redesign_guilds.js';
|
||||
|
||||
/*
|
||||
* Copy Guild Leader messages to end of Guild descriptions
|
||||
* Copy Guild logos to beginning of Guild descriptions
|
||||
*/
|
||||
|
||||
var monk = require('monk');
|
||||
var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
var dbGroups = monk(connectionString).get('groups', { castIds: false });
|
||||
|
||||
function processGroups(lastId) {
|
||||
// specify a query to limit the affected groups (empty for all groups):
|
||||
var query = {
|
||||
};
|
||||
|
||||
var fields = {
|
||||
'description': 1,
|
||||
'logo': 1,
|
||||
'leaderMessage': 1,
|
||||
}
|
||||
|
||||
if (lastId) {
|
||||
query._id = {
|
||||
$gt: lastId
|
||||
}
|
||||
}
|
||||
|
||||
return dbGroups.find(query, {
|
||||
fields: fields,
|
||||
sort: {_id: 1},
|
||||
limit: 250,
|
||||
})
|
||||
.then(updateGroups)
|
||||
.catch(function (err) {
|
||||
console.log(err);
|
||||
return exiting(1, 'ERROR! ' + err);
|
||||
});
|
||||
}
|
||||
|
||||
var progressCount = 1000;
|
||||
var count = 0;
|
||||
|
||||
function updateGroups (groups) {
|
||||
if (!groups || groups.length === 0) {
|
||||
console.warn('All appropriate groups found and modified.');
|
||||
displayData();
|
||||
return;
|
||||
}
|
||||
|
||||
var groupPromises = groups.map(updateGroup);
|
||||
var lastGroup = groups[groups.length - 1];
|
||||
|
||||
return Promise.all(groupPromises)
|
||||
.then(function () {
|
||||
processGroups(lastGroup._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updateGroup (group) {
|
||||
count++;
|
||||
|
||||
var description = group.description;
|
||||
|
||||
if (group.logo) {
|
||||
description = '\n\n \n\n' + description;
|
||||
}
|
||||
|
||||
if (group.leaderMessage) {
|
||||
description = description + '\n\n \n\n' + group.leaderMessage;
|
||||
}
|
||||
|
||||
var set = {
|
||||
description: description,
|
||||
};
|
||||
|
||||
if (count % progressCount == 0) console.warn(count + ' ' + group._id);
|
||||
|
||||
return dbGroups.update({_id: group._id}, {$set:set});
|
||||
}
|
||||
|
||||
function displayData() {
|
||||
console.warn('\n' + count + ' groups processed\n');
|
||||
return exiting(0);
|
||||
}
|
||||
|
||||
function exiting(code, msg) {
|
||||
code = code || 0; // 0 = success
|
||||
if (code && !msg) { msg = 'ERROR!'; }
|
||||
if (msg) {
|
||||
if (code) { console.error(msg); }
|
||||
else { console.log( msg); }
|
||||
}
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
module.exports = processGroups;
|
||||
127
migrations/20170928_redesign_launch.js
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
var updateStore = require('../website/common/script/libs/updateStore');
|
||||
var getItemInfo = require('../website/common/script/libs/getItemInfo');
|
||||
|
||||
var migrationName = '20170928_redesign_launch.js';
|
||||
var authorName = 'paglias'; // in case script author needs to know when their ...
|
||||
var authorUuid = 'ed4c688c-6652-4a92-9d03-a5a79844174a'; //... own data is done
|
||||
|
||||
/*
|
||||
* Migrate existing in app rewards lists to pinned items
|
||||
* Award Veteran Pets
|
||||
*/
|
||||
|
||||
var monk = require('monk');
|
||||
var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
var dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||
|
||||
function processUsers(lastId) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
var query = {
|
||||
'migration': {$ne:migrationName},
|
||||
'auth.timestamps.loggedin': {$gt: new Date('2017-09-21')},
|
||||
};
|
||||
|
||||
var fields = {
|
||||
'items.pets': 1,
|
||||
'items.gear': 1,
|
||||
'stats.class': 1,
|
||||
}
|
||||
|
||||
if (lastId) {
|
||||
query._id = {
|
||||
$gt: lastId
|
||||
}
|
||||
}
|
||||
|
||||
return dbUsers.find(query, {
|
||||
fields: fields,
|
||||
sort: {_id: 1},
|
||||
limit: 250,
|
||||
})
|
||||
.then(updateUsers)
|
||||
.catch(function (err) {
|
||||
console.log(err);
|
||||
return exiting(1, 'ERROR! ' + err);
|
||||
});
|
||||
}
|
||||
|
||||
var progressCount = 1000;
|
||||
var count = 0;
|
||||
|
||||
function updateUsers (users) {
|
||||
if (!users || users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
displayData();
|
||||
return;
|
||||
}
|
||||
|
||||
var userPromises = users.map(updateUser);
|
||||
var lastUser = users[users.length - 1];
|
||||
|
||||
return Promise.all(userPromises)
|
||||
.then(function () {
|
||||
processUsers(lastUser._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count++;
|
||||
|
||||
var set = {'migration': migrationName};
|
||||
|
||||
var oldRewardsList = updateStore(user);
|
||||
var newPinnedItems = [
|
||||
{
|
||||
type: 'armoire',
|
||||
path: 'armoire',
|
||||
},
|
||||
{
|
||||
type: 'potion',
|
||||
path: 'potion',
|
||||
},
|
||||
];
|
||||
|
||||
oldRewardsList.forEach(item => {
|
||||
var type = 'marketGear';
|
||||
|
||||
var itemInfo = getItemInfo(user, 'marketGear', item);
|
||||
newPinnedItems.push({
|
||||
type,
|
||||
path: itemInfo.path,
|
||||
})
|
||||
});
|
||||
|
||||
set.pinnedItems = newPinnedItems;
|
||||
|
||||
if (user.items.pets['Lion-Veteran']) {
|
||||
set['items.pets.Bear-Veteran'] = 5;
|
||||
} else if (user.items.pets['Tiger-Veteran']) {
|
||||
set['items.pets.Lion-Veteran'] = 5;
|
||||
} else if (user.items.pets['Wolf-Veteran']) {
|
||||
set['items.pets.Tiger-Veteran'] = 5;
|
||||
} else {
|
||||
set['items.pets.Wolf-Veteran'] = 5;
|
||||
}
|
||||
|
||||
if (count % progressCount == 0) console.warn(count + ' ' + user._id);
|
||||
if (user._id == authorUuid) console.warn(authorName + ' processed');
|
||||
|
||||
return dbUsers.update({_id: user._id}, {$set:set});
|
||||
}
|
||||
|
||||
function displayData() {
|
||||
console.warn('\n' + count + ' users processed\n');
|
||||
return exiting(0);
|
||||
}
|
||||
|
||||
function exiting(code, msg) {
|
||||
code = code || 0; // 0 = success
|
||||
if (code && !msg) { msg = 'ERROR!'; }
|
||||
if (msg) {
|
||||
if (code) { console.error(msg); }
|
||||
else { console.log( msg); }
|
||||
}
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
module.exports = processUsers;
|
||||
98
migrations/s3-upload.js
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
let Bluebird = require('bluebird');
|
||||
let request = require('superagent');
|
||||
let last = require('lodash/last');
|
||||
let AWS = require('aws-sdk');
|
||||
|
||||
let config = require('../config');
|
||||
const S3_DIRECTORY = 'mobileApp/images'; //config.S3.SPRITES_DIRECTORY;
|
||||
|
||||
AWS.config.update({
|
||||
accessKeyId: config.S3.accessKeyId,
|
||||
secretAccessKey: config.S3.secretAccessKey,
|
||||
// region: config.get('S3_REGION'),
|
||||
});
|
||||
|
||||
let BUCKET_NAME = config.S3.bucket;
|
||||
let s3 = new AWS.S3();
|
||||
|
||||
// Adapted from http://stackoverflow.com/a/22210077/2601552
|
||||
function uploadFile (buffer, fileName) {
|
||||
return new Promise((resolve, reject) => {
|
||||
s3.putObject({
|
||||
Body: buffer,
|
||||
Key: fileName,
|
||||
Bucket: BUCKET_NAME,
|
||||
}, (error) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
// console.info(`${fileName} uploaded to ${BUCKET_NAME} succesfully.`);
|
||||
resolve(fileName);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getFileName (file) {
|
||||
let piecesOfPath = file.split('/');
|
||||
let name = last(piecesOfPath);
|
||||
let fullName = S3_DIRECTORY + name;
|
||||
|
||||
return fullName;
|
||||
}
|
||||
|
||||
function getFileFromUrl (url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.get(url).end((err, res) => {
|
||||
if (err) return reject(err);
|
||||
let file = res.body;
|
||||
resolve(file);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let commit = '78f94e365c72cc58f66857d5941105638db7d35c';
|
||||
commit = 'df0dbaba636c9ce424cc7040f7bd7fc1aa311015';
|
||||
let gihuburl = `https://api.github.com/repos/HabitRPG/habitica/commits/${commit}`
|
||||
|
||||
|
||||
let currentIndex = 0;
|
||||
|
||||
function uploadToS3(start, end, filesUrls) {
|
||||
let urls = filesUrls.slice(start, end);
|
||||
|
||||
if (urls.length === 0) {
|
||||
console.log("done");
|
||||
return;
|
||||
}
|
||||
|
||||
let promises = urls.map(fullUrl => {
|
||||
return getFileFromUrl(fullUrl)
|
||||
.then((buffer) => {
|
||||
return uploadFile(buffer, getFileName(fullUrl));
|
||||
});
|
||||
});
|
||||
console.log(promises.length)
|
||||
|
||||
return Bluebird.all(promises)
|
||||
.then(() => {
|
||||
currentIndex += 50;
|
||||
uploadToS3(currentIndex, currentIndex + 50, filesUrls);
|
||||
})
|
||||
.catch(e => {
|
||||
console.log(e);
|
||||
});
|
||||
}
|
||||
|
||||
request.get(gihuburl)
|
||||
.end((err, res) => {
|
||||
console.log(err);
|
||||
let files = res.body.files;
|
||||
|
||||
let filesUrls = [''];
|
||||
filesUrls = files.map(file => {
|
||||
return file.raw_url;
|
||||
})
|
||||
|
||||
uploadToS3(currentIndex, currentIndex + 50, filesUrls);
|
||||
});
|
||||
13885
npm-shrinkwrap.json
generated
21115
package-lock.json
generated
Normal file
25
package.json
|
|
@ -30,14 +30,15 @@
|
|||
"bcrypt": "^1.0.2",
|
||||
"bluebird": "^3.3.5",
|
||||
"body-parser": "^1.15.0",
|
||||
"bootstrap": "^4.0.0-alpha.6",
|
||||
"bootstrap-vue": "^0.18.0",
|
||||
"bootstrap": "4.0.0-alpha.6",
|
||||
"bootstrap-vue": "^1.0.0-beta.6",
|
||||
"bower": "~1.3.12",
|
||||
"browserify": "~12.0.1",
|
||||
"compression": "^1.6.1",
|
||||
"connect-ratelimit": "0.0.7",
|
||||
"cookie-session": "^1.2.0",
|
||||
"coupon-code": "^0.4.5",
|
||||
"cross-env": "^4.0.0",
|
||||
"css-loader": "^0.28.0",
|
||||
"csv-stringify": "^1.0.2",
|
||||
"cwait": "~1.0.1",
|
||||
|
|
@ -59,7 +60,7 @@
|
|||
"grunt-contrib-stylus": "~0.20.0",
|
||||
"grunt-contrib-uglify": "~0.6.0",
|
||||
"grunt-contrib-watch": "~0.6.1",
|
||||
"grunt-hashres": "habitrpg/grunt-hashres#v0.4.2",
|
||||
"grunt-hashres": "git://github.com/habitrpg/grunt-hashres#dc85db6d3002e29e1b7c5ee186b80d708d2f0e0b",
|
||||
"gulp": "^3.9.0",
|
||||
"gulp-babel": "^6.1.2",
|
||||
"gulp-grunt": "^0.5.2",
|
||||
|
|
@ -75,13 +76,13 @@
|
|||
"in-app-purchase": "^1.1.6",
|
||||
"intro.js": "^2.6.0",
|
||||
"jade": "~1.11.0",
|
||||
"jquery": "^3.1.1",
|
||||
"jquery": ">=3.0.0",
|
||||
"js2xmlparser": "~1.0.0",
|
||||
"lodash": "^4.17.4",
|
||||
"merge-stream": "^1.0.0",
|
||||
"method-override": "^2.3.5",
|
||||
"moment": "^2.13.0",
|
||||
"moment-recur": "habitrpg/moment-recur#v1.0.6",
|
||||
"moment-recur": "git://github.com/habitrpg/moment-recur#f147ef27bbc26ca67638385f3db4a44084c76626",
|
||||
"mongoose": "~4.8.6",
|
||||
"mongoose-id-autoinc": "~2013.7.14-4",
|
||||
"morgan": "^1.7.0",
|
||||
|
|
@ -98,11 +99,12 @@
|
|||
"passport-google-oauth20": "1.0.0",
|
||||
"paypal-ipn": "3.0.0",
|
||||
"paypal-rest-sdk": "^1.2.1",
|
||||
"popper.js": "^1.11.0",
|
||||
"postcss-easy-import": "^2.0.0",
|
||||
"pretty-data": "^0.40.0",
|
||||
"ps-tree": "^1.0.0",
|
||||
"pug": "^2.0.0-beta.12",
|
||||
"push-notify": "habitrpg/push-notify#v1.2.0",
|
||||
"push-notify": "git://github.com/habitrpg/push-notify#6bc2b5fdb1bdc9649b9ec1964d79ca50187fc8a9",
|
||||
"pusher": "^1.3.0",
|
||||
"request": "~2.74.0",
|
||||
"rimraf": "^2.4.3",
|
||||
|
|
@ -111,6 +113,7 @@
|
|||
"sass-loader": "^6.0.2",
|
||||
"serve-favicon": "^2.3.0",
|
||||
"shelljs": "^0.7.6",
|
||||
"sortablejs": "^1.6.1",
|
||||
"stripe": "^4.2.0",
|
||||
"superagent": "^3.4.3",
|
||||
"svg-inline-loader": "^0.7.1",
|
||||
|
|
@ -126,11 +129,10 @@
|
|||
"vue": "^2.1.0",
|
||||
"vue-loader": "^11.0.0",
|
||||
"vue-mugen-scroll": "^0.2.1",
|
||||
"vue-notification": "^1.3.2",
|
||||
"vue-router": "^2.0.0-rc.5",
|
||||
"vue-style-loader": "^3.0.0",
|
||||
"vue-template-compiler": "^2.1.10",
|
||||
"vuejs-datepicker": "^0.9.4",
|
||||
"vuejs-datepicker": "git://github.com/habitrpg/vuejs-datepicker#45e607a7bccf4e3e089761b3b7b33e3f2c5dc21f",
|
||||
"webpack": "^2.2.1",
|
||||
"webpack-merge": "^4.0.0",
|
||||
"winston": "^2.1.0",
|
||||
|
|
@ -140,7 +142,7 @@
|
|||
"private": true,
|
||||
"engines": {
|
||||
"node": "^6.9.1",
|
||||
"npm": "^4.0.2"
|
||||
"npm": "^5.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint --ext .js,.vue .",
|
||||
|
|
@ -162,13 +164,13 @@
|
|||
"coverage": "COVERAGE=true mocha --require register-handlers.js --reporter html-cov > coverage.html; open coverage.html",
|
||||
"sprites": "gulp sprites:compile",
|
||||
"client:dev": "gulp bootstrap && node webpack/dev-server.js",
|
||||
"client:build": "gulp bootstrap && node webpack/build.js",
|
||||
"client:build": "gulp build:client",
|
||||
"client:unit": "cross-env NODE_ENV=test karma start test/client/unit/karma.conf.js --single-run",
|
||||
"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 run:dev",
|
||||
"postinstall": "bower --config.interactive=false install -f && gulp build && npm run client:build",
|
||||
"postinstall": "gulp build",
|
||||
"apidoc": "gulp apidoc"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -179,7 +181,6 @@
|
|||
"chromedriver": "^2.27.2",
|
||||
"connect-history-api-fallback": "^1.1.0",
|
||||
"coveralls": "^2.11.2",
|
||||
"cross-env": "^4.0.0",
|
||||
"cross-spawn": "^5.0.1",
|
||||
"csv": "~0.3.6",
|
||||
"deep-diff": "~0.1.4",
|
||||
|
|
|
|||
|
|
@ -48,8 +48,10 @@ describe('GET /challenges/:challengeId', () => {
|
|||
});
|
||||
expect(chal.group).to.eql({
|
||||
_id: group._id,
|
||||
categories: [],
|
||||
id: group.id,
|
||||
name: group.name,
|
||||
summary: group.name,
|
||||
type: group.type,
|
||||
privacy: group.privacy,
|
||||
leader: groupLeader.id,
|
||||
|
|
@ -100,8 +102,10 @@ describe('GET /challenges/:challengeId', () => {
|
|||
});
|
||||
expect(chal.group).to.eql({
|
||||
_id: group._id,
|
||||
categories: [],
|
||||
id: group.id,
|
||||
name: group.name,
|
||||
summary: group.name,
|
||||
type: group.type,
|
||||
privacy: group.privacy,
|
||||
leader: groupLeader.id,
|
||||
|
|
@ -153,7 +157,9 @@ describe('GET /challenges/:challengeId', () => {
|
|||
expect(chal.group).to.eql({
|
||||
_id: group._id,
|
||||
id: group.id,
|
||||
categories: [],
|
||||
name: group.name,
|
||||
summary: group.name,
|
||||
type: group.type,
|
||||
privacy: group.privacy,
|
||||
leader: groupLeader.id,
|
||||
|
|
|
|||
|
|
@ -41,10 +41,12 @@ describe('GET challenges/user', () => {
|
|||
});
|
||||
expect(foundChallenge.group).to.eql({
|
||||
_id: publicGuild._id,
|
||||
categories: [],
|
||||
id: publicGuild._id,
|
||||
type: publicGuild.type,
|
||||
privacy: publicGuild.privacy,
|
||||
name: publicGuild.name,
|
||||
summary: publicGuild.name,
|
||||
leader: publicGuild.leader._id,
|
||||
});
|
||||
});
|
||||
|
|
@ -61,10 +63,12 @@ describe('GET challenges/user', () => {
|
|||
});
|
||||
expect(foundChallenge1.group).to.eql({
|
||||
_id: publicGuild._id,
|
||||
categories: [],
|
||||
id: publicGuild._id,
|
||||
type: publicGuild.type,
|
||||
privacy: publicGuild.privacy,
|
||||
name: publicGuild.name,
|
||||
summary: publicGuild.name,
|
||||
leader: publicGuild.leader._id,
|
||||
});
|
||||
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
||||
|
|
@ -76,10 +80,12 @@ describe('GET challenges/user', () => {
|
|||
});
|
||||
expect(foundChallenge2.group).to.eql({
|
||||
_id: publicGuild._id,
|
||||
categories: [],
|
||||
id: publicGuild._id,
|
||||
type: publicGuild.type,
|
||||
privacy: publicGuild.privacy,
|
||||
name: publicGuild.name,
|
||||
summary: publicGuild.name,
|
||||
leader: publicGuild.leader._id,
|
||||
});
|
||||
});
|
||||
|
|
@ -96,10 +102,12 @@ describe('GET challenges/user', () => {
|
|||
});
|
||||
expect(foundChallenge1.group).to.eql({
|
||||
_id: publicGuild._id,
|
||||
categories: [],
|
||||
id: publicGuild._id,
|
||||
type: publicGuild.type,
|
||||
privacy: publicGuild.privacy,
|
||||
name: publicGuild.name,
|
||||
summary: publicGuild.name,
|
||||
leader: publicGuild.leader._id,
|
||||
});
|
||||
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
||||
|
|
@ -111,14 +119,26 @@ describe('GET challenges/user', () => {
|
|||
});
|
||||
expect(foundChallenge2.group).to.eql({
|
||||
_id: publicGuild._id,
|
||||
categories: [],
|
||||
id: publicGuild._id,
|
||||
type: publicGuild.type,
|
||||
privacy: publicGuild.privacy,
|
||||
name: publicGuild.name,
|
||||
summary: publicGuild.name,
|
||||
leader: publicGuild.leader._id,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return not return challenges in user groups if we send member true param', async () => {
|
||||
let challenges = await member.get(`/challenges/user?member=${true}`);
|
||||
|
||||
let foundChallenge1 = _.find(challenges, { _id: challenge._id });
|
||||
expect(foundChallenge1).to.not.exist;
|
||||
|
||||
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
||||
expect(foundChallenge2).to.not.exist;
|
||||
});
|
||||
|
||||
it('should return newest challenges first', async () => {
|
||||
let challenges = await user.get('/challenges/user');
|
||||
|
||||
|
|
@ -137,6 +157,7 @@ describe('GET challenges/user', () => {
|
|||
let { group, groupLeader } = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
name: 'TestPrivateGuild',
|
||||
summary: 'summary for TestPrivateGuild',
|
||||
type: 'guild',
|
||||
privacy: 'private',
|
||||
},
|
||||
|
|
@ -158,6 +179,7 @@ describe('GET challenges/user', () => {
|
|||
let { group, groupLeader } = await createAndPopulateGroup({
|
||||
groupDetails: {
|
||||
name: 'TestGuild',
|
||||
summary: 'summary for TestGuild',
|
||||
type: 'guild',
|
||||
privacy: 'public',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ describe('POST /chat', () => {
|
|||
color: 'danger',
|
||||
author_name: `${user.profile.name} - ${user.auth.local.email} - ${user._id}`,
|
||||
title: 'Slur in Test Guild',
|
||||
title_link: `${BASE_URL}/#/options/groups/guilds/${groupWithChat.id}`,
|
||||
title_link: `${BASE_URL}/groups/guild/${groupWithChat.id}`,
|
||||
text: testSlurMessage,
|
||||
// footer: sandbox.match(/<.*?groupId=group-id&chatId=chat-id\|Flag this message>/),
|
||||
mrkdwn_in: [
|
||||
|
|
|
|||
32
test/api/v3/integration/groups/GET-group-plans.test.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import {
|
||||
generateUser,
|
||||
generateGroup,
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
|
||||
describe('GET /group-plans', () => {
|
||||
let user;
|
||||
let groupPlan;
|
||||
|
||||
before(async () => {
|
||||
user = await generateUser({balance: 4});
|
||||
groupPlan = await generateGroup(user,
|
||||
{
|
||||
name: 'public guild - is member',
|
||||
type: 'guild',
|
||||
privacy: 'public',
|
||||
},
|
||||
{
|
||||
purchased: {
|
||||
plan: {
|
||||
customerId: 'existings',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('returns group plans for the user', async () => {
|
||||
let groupPlans = await user.get('/group-plans');
|
||||
|
||||
expect(groupPlans[0]._id).to.eql(groupPlan._id);
|
||||
});
|
||||
});
|
||||
|
|
@ -6,7 +6,7 @@ import superagent from 'superagent';
|
|||
import nconf from 'nconf';
|
||||
|
||||
const API_TEST_SERVER_PORT = nconf.get('PORT');
|
||||
describe('GET /qr-code/user/:memberId', () => {
|
||||
xdescribe('GET /qr-code/user/:memberId', () => {
|
||||
let user;
|
||||
|
||||
before(async () => {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ describe('GET /tasks/user', () => {
|
|||
it('returns all user\'s tasks', async () => {
|
||||
let createdTasks = await user.post('/tasks/user', [{text: 'test habit', type: 'habit'}, {text: 'test todo', type: 'todo'}]);
|
||||
let tasks = await user.get('/tasks/user');
|
||||
expect(tasks.length).to.equal(createdTasks.length + 1); // + 1 because 1 is a default task
|
||||
expect(tasks.length).to.equal(createdTasks.length + 1); // Plus one for generated todo
|
||||
});
|
||||
|
||||
it('returns only a type of user\'s tasks if req.query.type is specified', async () => {
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ describe('POST /tasks/unlink-all/:challengeId', () => {
|
|||
// Have the leader delete the challenge and unlink the tasks
|
||||
await user.del(`/challenges/${challenge._id}`);
|
||||
await user.post(`/tasks/unlink-all/${challenge._id}?keep=keep-all`);
|
||||
// Get the second task for the second user
|
||||
// Get the task for the second user
|
||||
const [, anotherUserTask] = await anotherUser.get('/tasks/user');
|
||||
// Expect the second user to still have the task, but unlinked
|
||||
expect(anotherUserTask.challenge).to.eql({
|
||||
|
|
@ -106,4 +106,4 @@ describe('POST /tasks/unlink-all/:challengeId', () => {
|
|||
winner: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ describe('POST /tasks/user', () => {
|
|||
expect(task.updatedAt).not.to.equal('tomorrow');
|
||||
expect(task.challenge).not.to.equal('no');
|
||||
expect(task.completed).to.equal(false);
|
||||
expect(task.streak).not.to.equal('never');
|
||||
expect(task.dateCompleted).not.to.equal('never');
|
||||
expect(task.value).not.to.equal(324);
|
||||
expect(task.yesterDaily).to.equal(true);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -86,6 +86,12 @@ describe('DELETE /user', () => {
|
|||
});
|
||||
|
||||
it('deletes the user\'s tasks', async () => {
|
||||
await user.post('/tasks/user', {
|
||||
text: 'test habit',
|
||||
type: 'habit',
|
||||
});
|
||||
await user.sync();
|
||||
|
||||
// gets the user's tasks ids
|
||||
let ids = [];
|
||||
each(user.tasksOrder, (idsForOrder) => {
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ describe('GET /user/anonymized', () => {
|
|||
});
|
||||
// tasks
|
||||
expect(tasks2).to.exist;
|
||||
expect(tasks2.length).to.eql(5); // +1 because generateUser() assigns one todo
|
||||
expect(tasks2.length).to.eql(5);
|
||||
expect(tasks2[0].checklist).to.exist;
|
||||
_.forEach(tasks2, (task) => {
|
||||
expect(task.text).to.eql('task text');
|
||||
|
|
|
|||
|
|
@ -10,43 +10,31 @@ import nconf from 'nconf';
|
|||
|
||||
const API_TEST_SERVER_PORT = nconf.get('PORT');
|
||||
|
||||
describe('GET /user/auth/local/reset-password-set-new-one', () => {
|
||||
// @TODO skipped because on travis the client isn't available and the redirect fails
|
||||
xdescribe('GET /user/auth/local/reset-password-set-new-one', () => {
|
||||
let endpoint = `http://localhost:${API_TEST_SERVER_PORT}/static/user/auth/local/reset-password-set-new-one`;
|
||||
|
||||
// Tests to validate the validatePasswordResetCodeAndFindUser function
|
||||
|
||||
it('renders an error page if the code is missing', async () => {
|
||||
try {
|
||||
await superagent.get(endpoint);
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
const res = await superagent.get(endpoint);
|
||||
expect(res.req.path.indexOf('hasError=true') !== -1).to.equal(true);
|
||||
});
|
||||
|
||||
it('renders an error page if the code is invalid json', async () => {
|
||||
try {
|
||||
await superagent.get(`${endpoint}?code=invalid`);
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
const res = await superagent.get(`${endpoint}?code=invalid`);
|
||||
expect(res.req.path.indexOf('hasError=true') !== -1).to.equal(true);
|
||||
});
|
||||
|
||||
it('renders an error page if the code cannot be decrypted', async () => {
|
||||
let user = await generateUser();
|
||||
|
||||
try {
|
||||
let code = JSON.stringify({ // not encrypted
|
||||
userId: user._id,
|
||||
expiresAt: new Date(),
|
||||
});
|
||||
await superagent.get(`${endpoint}?code=${code}`);
|
||||
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
let code = JSON.stringify({ // not encrypted
|
||||
userId: user._id,
|
||||
expiresAt: new Date(),
|
||||
});
|
||||
const res = await superagent.get(`${endpoint}?code=${code}`);
|
||||
expect(res.req.path.indexOf('hasError=true') !== -1).to.equal(true);
|
||||
});
|
||||
|
||||
it('renders an error page if the code is expired', async () => {
|
||||
|
|
@ -60,12 +48,8 @@ describe('GET /user/auth/local/reset-password-set-new-one', () => {
|
|||
'auth.local.passwordResetCode': code,
|
||||
});
|
||||
|
||||
try {
|
||||
await superagent.get(`${endpoint}?code=${code}`);
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
const res = await superagent.get(`${endpoint}?code=${code}`);
|
||||
expect(res.req.path.indexOf('hasError=true') !== -1).to.equal(true);
|
||||
});
|
||||
|
||||
it('renders an error page if the user does not exist', async () => {
|
||||
|
|
@ -74,12 +58,8 @@ describe('GET /user/auth/local/reset-password-set-new-one', () => {
|
|||
expiresAt: moment().add({days: 1}),
|
||||
}));
|
||||
|
||||
try {
|
||||
await superagent.get(`${endpoint}?code=${code}`);
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
const res = await superagent.get(`${endpoint}?code=${code}`);
|
||||
expect(res.req.path.indexOf('hasError=true') !== -1).to.equal(true);
|
||||
});
|
||||
|
||||
it('renders an error page if the user has no local auth', async () => {
|
||||
|
|
@ -93,12 +73,8 @@ describe('GET /user/auth/local/reset-password-set-new-one', () => {
|
|||
auth: 'not an object with valid fields',
|
||||
});
|
||||
|
||||
try {
|
||||
await superagent.get(`${endpoint}?code=${code}`);
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
const res = await superagent.get(`${endpoint}?code=${code}`);
|
||||
expect(res.req.path.indexOf('hasError=true') !== -1).to.equal(true);
|
||||
});
|
||||
|
||||
it('renders an error page if the code doesn\'t match the one saved at user.auth.passwordResetCode', async () => {
|
||||
|
|
@ -112,12 +88,8 @@ describe('GET /user/auth/local/reset-password-set-new-one', () => {
|
|||
'auth.local.passwordResetCode': 'invalid',
|
||||
});
|
||||
|
||||
try {
|
||||
await superagent.get(`${endpoint}?code=${code}`);
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
const res = await superagent.get(`${endpoint}?code=${code}`);
|
||||
expect(res.req.path.indexOf('hasError=true') !== -1).to.equal(true);
|
||||
});
|
||||
|
||||
//
|
||||
|
|
@ -134,7 +106,8 @@ describe('GET /user/auth/local/reset-password-set-new-one', () => {
|
|||
});
|
||||
|
||||
let res = await superagent.get(`${endpoint}?code=${code}`);
|
||||
expect(res.status).to.equal(200);
|
||||
expect(res.req.path.indexOf('hasError=false') !== -1).to.equal(true);
|
||||
expect(res.req.path.indexOf('code=') !== -1).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -10,49 +10,46 @@ import {
|
|||
import moment from 'moment';
|
||||
import {
|
||||
generateUser,
|
||||
requester,
|
||||
translate as t,
|
||||
} from '../../../../../helpers/api-integration/v3';
|
||||
import superagent from 'superagent';
|
||||
import nconf from 'nconf';
|
||||
|
||||
const API_TEST_SERVER_PORT = nconf.get('PORT');
|
||||
|
||||
describe('POST /user/auth/local/reset-password-set-new-one', () => {
|
||||
let endpoint = `http://localhost:${API_TEST_SERVER_PORT}/static/user/auth/local/reset-password-set-new-one`;
|
||||
describe('POST /user/auth/reset-password-set-new-one', () => {
|
||||
const endpoint = '/user/auth/reset-password-set-new-one';
|
||||
const api = requester();
|
||||
|
||||
// Tests to validate the validatePasswordResetCodeAndFindUser function
|
||||
|
||||
it('renders an error page if the code is missing', async () => {
|
||||
try {
|
||||
await superagent.post(endpoint);
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
await expect(api.post(endpoint)).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('invalidPasswordResetCode'),
|
||||
});
|
||||
});
|
||||
|
||||
it('renders an error page if the code is invalid json', async () => {
|
||||
try {
|
||||
await superagent.post(`${endpoint}?code=invalid`);
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
await expect(api.post(`${endpoint}?code=invalid`)).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('invalidPasswordResetCode'),
|
||||
});
|
||||
});
|
||||
|
||||
it('renders an error page if the code cannot be decrypted', async () => {
|
||||
let user = await generateUser();
|
||||
|
||||
try {
|
||||
let code = JSON.stringify({ // not encrypted
|
||||
userId: user._id,
|
||||
expiresAt: new Date(),
|
||||
});
|
||||
await superagent.post(`${endpoint}?code=${code}`);
|
||||
let code = JSON.stringify({ // not encrypted
|
||||
userId: user._id,
|
||||
expiresAt: new Date(),
|
||||
});
|
||||
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
await expect(api.post(`${endpoint}`, {
|
||||
code,
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('invalidPasswordResetCode'),
|
||||
});
|
||||
});
|
||||
|
||||
it('renders an error page if the code is expired', async () => {
|
||||
|
|
@ -66,12 +63,13 @@ describe('POST /user/auth/local/reset-password-set-new-one', () => {
|
|||
'auth.local.passwordResetCode': code,
|
||||
});
|
||||
|
||||
try {
|
||||
await superagent.post(`${endpoint}?code=${code}`);
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
await expect(api.post(`${endpoint}`, {
|
||||
code,
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('invalidPasswordResetCode'),
|
||||
});
|
||||
});
|
||||
|
||||
it('renders an error page if the user does not exist', async () => {
|
||||
|
|
@ -80,12 +78,13 @@ describe('POST /user/auth/local/reset-password-set-new-one', () => {
|
|||
expiresAt: moment().add({days: 1}),
|
||||
}));
|
||||
|
||||
try {
|
||||
await superagent.post(`${endpoint}?code=${code}`);
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
await expect(api.post(`${endpoint}`, {
|
||||
code,
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('invalidPasswordResetCode'),
|
||||
});
|
||||
});
|
||||
|
||||
it('renders an error page if the user has no local auth', async () => {
|
||||
|
|
@ -99,12 +98,13 @@ describe('POST /user/auth/local/reset-password-set-new-one', () => {
|
|||
auth: 'not an object with valid fields',
|
||||
});
|
||||
|
||||
try {
|
||||
await superagent.post(`${endpoint}?code=${code}`);
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
await expect(api.post(`${endpoint}`, {
|
||||
code,
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('invalidPasswordResetCode'),
|
||||
});
|
||||
});
|
||||
|
||||
it('renders an error page if the code doesn\'t match the one saved at user.auth.passwordResetCode', async () => {
|
||||
|
|
@ -118,12 +118,13 @@ describe('POST /user/auth/local/reset-password-set-new-one', () => {
|
|||
'auth.local.passwordResetCode': 'invalid',
|
||||
});
|
||||
|
||||
try {
|
||||
await superagent.post(`${endpoint}?code=${code}`);
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
await expect(api.post(`${endpoint}`, {
|
||||
code,
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('invalidPasswordResetCode'),
|
||||
});
|
||||
});
|
||||
|
||||
//
|
||||
|
|
@ -139,12 +140,13 @@ describe('POST /user/auth/local/reset-password-set-new-one', () => {
|
|||
'auth.local.passwordResetCode': code,
|
||||
});
|
||||
|
||||
try {
|
||||
await superagent.post(`${endpoint}?code=${code}`);
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
await expect(api.post(`${endpoint}`, {
|
||||
code,
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: t('invalidReqParams'),
|
||||
});
|
||||
});
|
||||
|
||||
it('renders the error page if the password confirmation is missing', async () => {
|
||||
|
|
@ -158,14 +160,14 @@ describe('POST /user/auth/local/reset-password-set-new-one', () => {
|
|||
'auth.local.passwordResetCode': code,
|
||||
});
|
||||
|
||||
try {
|
||||
await superagent
|
||||
.post(`${endpoint}?code=${code}`)
|
||||
.send({newPassword: 'my new password'});
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
await expect(api.post(`${endpoint}`, {
|
||||
newPassword: 'my new password',
|
||||
code,
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: t('invalidReqParams'),
|
||||
});
|
||||
});
|
||||
|
||||
it('renders the error page if the password confirmation does not match', async () => {
|
||||
|
|
@ -179,17 +181,15 @@ describe('POST /user/auth/local/reset-password-set-new-one', () => {
|
|||
'auth.local.passwordResetCode': code,
|
||||
});
|
||||
|
||||
try {
|
||||
await superagent
|
||||
.post(`${endpoint}?code=${code}`)
|
||||
.send({
|
||||
newPassword: 'my new password',
|
||||
confirmPassword: 'not matching',
|
||||
});
|
||||
throw new Error('Request should fail.');
|
||||
} catch (err) {
|
||||
expect(err.status).to.equal(401);
|
||||
}
|
||||
await expect(api.post(`${endpoint}`, {
|
||||
newPassword: 'my new password',
|
||||
confirmPassword: 'not matching',
|
||||
code,
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: t('passwordConfirmationMatch'),
|
||||
});
|
||||
});
|
||||
|
||||
it('renders the success page and save the user', async () => {
|
||||
|
|
@ -203,14 +203,13 @@ describe('POST /user/auth/local/reset-password-set-new-one', () => {
|
|||
'auth.local.passwordResetCode': code,
|
||||
});
|
||||
|
||||
let res = await superagent
|
||||
.post(`${endpoint}?code=${code}`)
|
||||
.send({
|
||||
newPassword: 'my new password',
|
||||
confirmPassword: 'my new password',
|
||||
});
|
||||
let res = await api.post(`${endpoint}`, {
|
||||
newPassword: 'my new password',
|
||||
confirmPassword: 'my new password',
|
||||
code,
|
||||
});
|
||||
|
||||
expect(res.status).to.equal(200);
|
||||
expect(res.message).to.equal(t('passwordChangeSuccess'));
|
||||
|
||||
await user.sync();
|
||||
expect(user.auth.local.passwordResetCode).to.equal(undefined);
|
||||
|
|
@ -246,14 +245,13 @@ describe('POST /user/auth/local/reset-password-set-new-one', () => {
|
|||
'auth.local.passwordResetCode': code,
|
||||
});
|
||||
|
||||
let res = await superagent
|
||||
.post(`${endpoint}?code=${code}`)
|
||||
.send({
|
||||
newPassword: 'my new password',
|
||||
confirmPassword: 'my new password',
|
||||
});
|
||||
let res = await api.post(`${endpoint}`, {
|
||||
newPassword: 'my new password',
|
||||
confirmPassword: 'my new password',
|
||||
code,
|
||||
});
|
||||
|
||||
expect(res.status).to.equal(200);
|
||||
expect(res.message).to.equal(t('passwordChangeSuccess'));
|
||||
|
||||
await user.sync();
|
||||
expect(user.auth.local.passwordResetCode).to.equal(undefined);
|
||||
|
|
|
|||
|
|
@ -59,13 +59,8 @@ describe('POST /user/auth/local/register', () => {
|
|||
let tags = await requests.get('/tags');
|
||||
|
||||
expect(habits).to.have.a.lengthOf(0);
|
||||
|
||||
expect(dailys).to.have.a.lengthOf(0);
|
||||
|
||||
expect(todos).to.have.a.lengthOf(1);
|
||||
expect(todos[0].text).to.eql(t('defaultTodo1Text'));
|
||||
expect(todos[0].notes).to.eql(t('defaultTodoNotes'));
|
||||
|
||||
expect(rewards).to.have.a.lengthOf(0);
|
||||
|
||||
expect(tags).to.have.a.lengthOf(7);
|
||||
|
|
@ -78,7 +73,7 @@ describe('POST /user/auth/local/register', () => {
|
|||
expect(tags[6].name).to.eql(t('defaultTag7'));
|
||||
});
|
||||
|
||||
it('for Web', async () => {
|
||||
xit('for Web', async () => {
|
||||
api = requester(
|
||||
null,
|
||||
{'x-client': 'habitica-web'},
|
||||
|
|
@ -623,10 +618,10 @@ describe('POST /user/auth/local/register', () => {
|
|||
confirmPassword: password,
|
||||
});
|
||||
|
||||
expect(user.tasksOrder.todos).to.not.be.empty;
|
||||
expect(user.tasksOrder.todos).to.be.empty;
|
||||
expect(user.tasksOrder.dailys).to.be.empty;
|
||||
expect(user.tasksOrder.habits).to.not.be.empty;
|
||||
expect(user.tasksOrder.rewards).to.not.be.empty;
|
||||
expect(user.tasksOrder.habits).to.be.empty;
|
||||
expect(user.tasksOrder.rewards).to.be.empty;
|
||||
});
|
||||
|
||||
it('populates user with default tags', async () => {
|
||||
|
|
@ -653,23 +648,8 @@ describe('POST /user/auth/local/register', () => {
|
|||
let habits = await requests.get('/tasks/user?type=habits');
|
||||
let todos = await requests.get('/tasks/user?type=todos');
|
||||
|
||||
function findTag (tagName) {
|
||||
let tag = user.tags.find((userTag) => {
|
||||
return userTag.name === t(tagName);
|
||||
});
|
||||
return tag.id;
|
||||
}
|
||||
|
||||
expect(habits[0].tags).to.have.a.lengthOf(3);
|
||||
expect(habits[0].tags).to.include.members(['defaultTag1', 'defaultTag4', 'defaultTag6'].map(findTag));
|
||||
|
||||
expect(habits[1].tags).to.have.a.lengthOf(1);
|
||||
expect(habits[1].tags).to.include.members(['defaultTag3'].map(findTag));
|
||||
|
||||
expect(habits[2].tags).to.have.a.lengthOf(2);
|
||||
expect(habits[2].tags).to.include.members(['defaultTag2', 'defaultTag3'].map(findTag));
|
||||
|
||||
expect(todos[0].tags).to.have.a.lengthOf(0);
|
||||
expect(habits).to.have.a.lengthOf(0);
|
||||
expect(todos).to.have.a.lengthOf(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -142,12 +142,12 @@ describe('emails', () => {
|
|||
describe('getGroupUrl', () => {
|
||||
it('returns correct url if group is the tavern', () => {
|
||||
let getGroupUrl = require(pathToEmailLib).getGroupUrl;
|
||||
expect(getGroupUrl({_id: TAVERN_ID, type: 'guild'})).to.eql('/#/options/groups/tavern');
|
||||
expect(getGroupUrl({_id: TAVERN_ID, type: 'guild'})).to.eql('/groups/tavern');
|
||||
});
|
||||
|
||||
it('returns correct url if group is a guild', () => {
|
||||
let getGroupUrl = require(pathToEmailLib).getGroupUrl;
|
||||
expect(getGroupUrl({_id: 'random _id', type: 'guild'})).to.eql('/#/options/groups/guilds/random _id');
|
||||
expect(getGroupUrl({_id: 'random _id', type: 'guild'})).to.eql('/groups/guild/random _id');
|
||||
});
|
||||
|
||||
it('returns correct url if group is a party', () => {
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ describe('slack', () => {
|
|||
expect(IncomingWebhook.prototype.send).to.be.calledWithMatch({
|
||||
attachments: [sandbox.match({
|
||||
title: 'Flag in Some group',
|
||||
title_link: sandbox.match(/.*\/#\/options\/groups\/guilds\/group-id/),
|
||||
title_link: sandbox.match(/.*\/groups\/guild\/group-id/),
|
||||
})],
|
||||
});
|
||||
});
|
||||
|
|
@ -86,7 +86,7 @@ describe('slack', () => {
|
|||
expect(IncomingWebhook.prototype.send).to.be.calledWithMatch({
|
||||
attachments: [sandbox.match({
|
||||
title: 'Flag in Tavern',
|
||||
title_link: sandbox.match(/.*\/#\/options\/groups\/tavern/),
|
||||
title_link: sandbox.match(/.*\/groups\/tavern/),
|
||||
})],
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ describe('response middleware', () => {
|
|||
success: true,
|
||||
data: {field: 1},
|
||||
notifications: [],
|
||||
userV: res.locals.user._v,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -49,6 +50,7 @@ describe('response middleware', () => {
|
|||
data: {field: 1},
|
||||
message: 'hello',
|
||||
notifications: [],
|
||||
userV: res.locals.user._v,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -64,12 +66,12 @@ describe('response middleware', () => {
|
|||
success: false,
|
||||
data: {field: 1},
|
||||
notifications: [],
|
||||
userV: res.locals.user._v,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns userV if a user is authenticated req.query.userV is passed', () => {
|
||||
it('returns userV if a user is authenticated', () => {
|
||||
responseMiddleware(req, res, next);
|
||||
req.query.userV = 3;
|
||||
res.respond(200, {field: 1});
|
||||
|
||||
expect(res.json).to.be.calledOnce;
|
||||
|
|
@ -101,6 +103,7 @@ describe('response middleware', () => {
|
|||
data: {},
|
||||
},
|
||||
],
|
||||
userV: res.locals.user._v,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ describe('Notification Controller', function() {
|
|||
});
|
||||
|
||||
describe('User challenge won notification watch', function() {
|
||||
it('opens challenge won modal when a challenge-won notification is recieved', function() {
|
||||
it('opens challenge won modal when a challenge-won notification is received', function() {
|
||||
rootScope.$digest();
|
||||
rootScope.userNotifications.push({type: 'WON_CHALLENGE'});
|
||||
rootScope.$digest();
|
||||
|
|
@ -109,7 +109,7 @@ describe('Notification Controller', function() {
|
|||
expect(achievement.displayAchievement).to.be.calledWith('wonChallenge');
|
||||
});
|
||||
|
||||
it('does not open challenge won modal if no new challenge-won notification is recieved', function() {
|
||||
it('does not open challenge won modal if no new challenge-won notification is received', function() {
|
||||
rootScope.$digest();
|
||||
rootScope.$digest();
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ describe('Notification Controller', function() {
|
|||
});
|
||||
|
||||
describe('User streak achievement notification watch', function() {
|
||||
it('opens streak achievement modal when a streak-achievement notification is recieved', function() {
|
||||
it('opens streak achievement modal when a streak-achievement notification is received', function() {
|
||||
rootScope.$digest();
|
||||
rootScope.userNotifications.push({type: 'STREAK_ACHIEVEMENT'});
|
||||
rootScope.$digest();
|
||||
|
|
@ -127,7 +127,7 @@ describe('Notification Controller', function() {
|
|||
expect(achievement.displayAchievement).to.be.calledWith('streak', {size: 'md'});
|
||||
});
|
||||
|
||||
it('does not open streak achievement modal if no new streak-achievement notification is recieved', function() {
|
||||
it('does not open streak achievement modal if no new streak-achievement notification is received', function() {
|
||||
rootScope.$digest();
|
||||
rootScope.$digest();
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ describe('Notification Controller', function() {
|
|||
});
|
||||
|
||||
describe('User ultimate gear set achievement notification watch', function() {
|
||||
it('opens ultimate gear set achievement modal when an ultimate-gear-achievement notification is recieved', function() {
|
||||
it('opens ultimate gear set achievement modal when an ultimate-gear-achievement notification is received', function() {
|
||||
rootScope.$digest();
|
||||
rootScope.userNotifications.push({type: 'ULTIMATE_GEAR_ACHIEVEMENT'});
|
||||
rootScope.$digest();
|
||||
|
|
@ -145,7 +145,7 @@ describe('Notification Controller', function() {
|
|||
expect(achievement.displayAchievement).to.be.calledWith('ultimateGear', {size: 'md'});
|
||||
});
|
||||
|
||||
it('does not open ultimate gear set achievement modal if no new ultimate-gear-achievement notification is recieved', function() {
|
||||
it('does not open ultimate gear set achievement modal if no new ultimate-gear-achievement notification is received', function() {
|
||||
rootScope.$digest();
|
||||
rootScope.$digest();
|
||||
|
||||
|
|
@ -154,7 +154,7 @@ describe('Notification Controller', function() {
|
|||
});
|
||||
|
||||
describe('User rebirth achievement notification watch', function() {
|
||||
it('opens rebirth achievement modal when a rebirth-achievement notification is recieved', function() {
|
||||
it('opens rebirth achievement modal when a rebirth-achievement notification is received', function() {
|
||||
rootScope.$digest();
|
||||
rootScope.userNotifications.push({type: 'REBIRTH_ACHIEVEMENT'});
|
||||
rootScope.$digest();
|
||||
|
|
@ -163,7 +163,7 @@ describe('Notification Controller', function() {
|
|||
expect(achievement.displayAchievement).to.be.calledWith('rebirth');
|
||||
});
|
||||
|
||||
it('does not open rebirth achievement modal if no new rebirth-achievement notification is recieved', function() {
|
||||
it('does not open rebirth achievement modal if no new rebirth-achievement notification is received', function() {
|
||||
rootScope.$digest();
|
||||
rootScope.$digest();
|
||||
|
||||
|
|
@ -172,7 +172,7 @@ describe('Notification Controller', function() {
|
|||
});
|
||||
|
||||
describe('User contributor achievement notification watch', function() {
|
||||
it('opens contributor achievement modal when a new-contributor-level notification is recieved', function() {
|
||||
it('opens contributor achievement modal when a new-contributor-level notification is received', function() {
|
||||
rootScope.$digest();
|
||||
rootScope.userNotifications.push({type: 'NEW_CONTRIBUTOR_LEVEL'});
|
||||
rootScope.$digest();
|
||||
|
|
@ -181,7 +181,7 @@ describe('Notification Controller', function() {
|
|||
expect(achievement.displayAchievement).to.be.calledWith('contributor', {size: 'md'});
|
||||
});
|
||||
|
||||
it('does not open contributor achievement modal if no new new-contributor-level notification is recieved', function() {
|
||||
it('does not open contributor achievement modal if no new new-contributor-level notification is received', function() {
|
||||
rootScope.$digest();
|
||||
rootScope.$digest();
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,13 @@ import Vue from 'vue';
|
|||
|
||||
describe('i18n plugin', () => {
|
||||
before(() => {
|
||||
Vue.use(i18n);
|
||||
Vue.use(i18n, {
|
||||
i18nData: {
|
||||
strings: {
|
||||
reportBug: 'Report a Bug',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('adds $t to Vue.prototype', () => {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ describe('user actions', () => {
|
|||
const user = {_id: 2};
|
||||
sandbox.stub(axios, 'get').withArgs('/api/v3/user').returns(Promise.resolve({data: {data: user}}));
|
||||
|
||||
await store.dispatch('user:fetch', true);
|
||||
await store.dispatch('user:fetch', {forceLoad: true});
|
||||
|
||||
expect(store.state.user.data).to.equal(user);
|
||||
expect(store.state.user.loadingStatus).to.equal('LOADED');
|
||||
|
|
|
|||
|
|
@ -68,23 +68,6 @@ describe('shared.ops.buyArmoire', () => {
|
|||
done();
|
||||
}
|
||||
});
|
||||
|
||||
it('does not open without Ultimate Gear achievement', (done) => {
|
||||
user.achievements.ultimateGearSets = {healer: false, wizard: false, rogue: false, warrior: false};
|
||||
|
||||
try {
|
||||
buyArmoire(user);
|
||||
} catch (err) {
|
||||
expect(err).to.be.an.instanceof(NotAuthorized);
|
||||
expect(err.message).to.equal(i18n.t('cannotBuyItem'));
|
||||
expect(user.items.gear.owned).to.eql({
|
||||
weapon_warrior_0: true,
|
||||
});
|
||||
expect(user.items.food).to.be.empty;
|
||||
expect(user.stats.exp).to.eql(0);
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
context('non-gear awards', () => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
// https://github.com/shelljs/shelljs
|
||||
require('shelljs/global');
|
||||
env.NODE_ENV = 'production';
|
||||
|
||||
const path = require('path');
|
||||
const config = require('./config');
|
||||
|
|
@ -10,28 +9,39 @@ const ora = require('ora');
|
|||
const webpack = require('webpack');
|
||||
const webpackConfig = require('./webpack.prod.conf');
|
||||
|
||||
console.log( // eslint-disable-line no-console
|
||||
' Tip:\n' +
|
||||
' Built files are meant to be served over an HTTP server.\n' +
|
||||
' Opening index.html over file:// won\'t work.\n'
|
||||
);
|
||||
module.exports = function webpackProductionBuild (callback) {
|
||||
env.NODE_ENV = 'production';
|
||||
|
||||
const spinner = ora('building for production...');
|
||||
spinner.start();
|
||||
console.log( // eslint-disable-line no-console
|
||||
' Tip:\n' +
|
||||
' Built files are meant to be served over an HTTP server.\n' +
|
||||
' Opening index.html over file:// won\'t work.\n'
|
||||
);
|
||||
|
||||
const assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory);
|
||||
rm('-rf', assetsPath);
|
||||
mkdir('-p', assetsPath);
|
||||
cp('-R', config.build.staticAssetsDirectory, assetsPath);
|
||||
const spinner = ora('building for production...');
|
||||
spinner.start();
|
||||
|
||||
webpack(webpackConfig, (err, stats) => {
|
||||
spinner.stop();
|
||||
if (err) throw err;
|
||||
process.stdout.write(`${stats.toString({
|
||||
colors: true,
|
||||
modules: false,
|
||||
children: false,
|
||||
chunks: false,
|
||||
chunkModules: false,
|
||||
})}\n`);
|
||||
});
|
||||
const assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory);
|
||||
rm('-rf', assetsPath);
|
||||
mkdir('-p', assetsPath);
|
||||
cp('-R', config.build.staticAssetsDirectory, assetsPath);
|
||||
|
||||
webpack(webpackConfig, (err, stats) => {
|
||||
spinner.stop();
|
||||
|
||||
const output = `${stats.toString({
|
||||
colors: true,
|
||||
modules: false,
|
||||
children: false,
|
||||
chunks: false,
|
||||
chunkModules: false,
|
||||
})}\n`;
|
||||
|
||||
if (callback) {
|
||||
return err ? callback(err) : callback(null, output);
|
||||
} else {
|
||||
if (err) throw err;
|
||||
process.stdout.write(output);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ module.exports = {
|
|||
index: path.resolve(__dirname, '../../dist-client/index.html'),
|
||||
assetsRoot: path.resolve(__dirname, '../../dist-client'),
|
||||
assetsSubDirectory: 'static',
|
||||
assetsPublicPath: '/new-app/',
|
||||
assetsPublicPath: '/',
|
||||
staticAssetsDirectory,
|
||||
productionSourceMap: true,
|
||||
// Gzip off by default as many popular static hosts such as
|
||||
|
|
@ -21,7 +21,7 @@ module.exports = {
|
|||
productionGzipExtensions: ['js', 'css'],
|
||||
// Run the build command with an extra argument to
|
||||
// View the bundle analyzer report after build finishes:
|
||||
// `npm run build --report`
|
||||
// `npm run client:build --report`
|
||||
// Set to `true` or `false` to always turn it on or off
|
||||
bundleAnalyzerReport: process.env.npm_config_report, // eslint-disable-line no-process-env
|
||||
},
|
||||
|
|
@ -50,6 +50,10 @@ module.exports = {
|
|||
target: 'http://localhost:3000',
|
||||
changeOrigin: true,
|
||||
},
|
||||
'/logout': {
|
||||
target: 'http://localhost:3000',
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
// CSS Sourcemaps off by default because relative paths are "buggy"
|
||||
// with this option, according to the CSS-Loader README
|
||||
|
|
|
|||
|
|
@ -1,3 +1,49 @@
|
|||
module.exports = {
|
||||
const nconf = require('nconf');
|
||||
const { join, resolve } = require('path');
|
||||
|
||||
const PATH_TO_CONFIG = join(resolve(__dirname, '../../config.json'));
|
||||
let configFile = PATH_TO_CONFIG;
|
||||
|
||||
nconf
|
||||
.argv()
|
||||
.env()
|
||||
.file('user', configFile);
|
||||
|
||||
nconf.set('IS_PROD', nconf.get('NODE_ENV') === 'production');
|
||||
nconf.set('IS_DEV', nconf.get('NODE_ENV') === 'development');
|
||||
nconf.set('IS_TEST', nconf.get('NODE_ENV') === 'test');
|
||||
|
||||
// @TODO: Check if we can import from client. Items like admin emails can be imported
|
||||
// and that should be prefered
|
||||
|
||||
// To avoid stringifying more data then we need,
|
||||
// items from `env` used on the client will have to be specified in this array
|
||||
// @TODO: Do we need? const CLIENT_VARS = ['language', 'isStaticPage', 'availableLanguages', 'translations',
|
||||
// 'FACEBOOK_KEY', 'GOOGLE_CLIENT_ID', 'NODE_ENV', 'BASE_URL', 'GA_ID',
|
||||
// 'AMAZON_PAYMENTS', 'STRIPE_PUB_KEY', 'AMPLITUDE_KEY',
|
||||
// 'worldDmg', 'mods', 'IS_MOBILE', 'PUSHER:KEY', 'PUSHER:ENABLED'];
|
||||
|
||||
const AMAZON_SELLER_ID = nconf.get('AMAZON_PAYMENTS:SELLER_ID') || nconf.get('AMAZON_PAYMENTS_SELLER_ID');
|
||||
const AMAZON_CLIENT_ID = nconf.get('AMAZON_PAYMENTS:CLIENT_ID') || nconf.get('AMAZON_PAYMENTS_CLIENT_ID');
|
||||
|
||||
let env = {
|
||||
NODE_ENV: '"production"',
|
||||
// clientVars: CLIENT_VARS,
|
||||
AMAZON_PAYMENTS: {
|
||||
SELLER_ID: `"${AMAZON_SELLER_ID}"`,
|
||||
CLIENT_ID: `"${AMAZON_CLIENT_ID}"`,
|
||||
},
|
||||
EMAILS: {
|
||||
COMMUNITY_MANAGER_EMAIL: `"${nconf.get('EMAILS:COMMUNITY_MANAGER_EMAIL')}"`,
|
||||
TECH_ASSISTANCE_EMAIL: `"${nconf.get('EMAILS:TECH_ASSISTANCE_EMAIL')}"`,
|
||||
PRESS_ENQUIRY_EMAIL: `"${nconf.get('EMAILS:PRESS_ENQUIRY_EMAIL')}"`,
|
||||
},
|
||||
};
|
||||
|
||||
'NODE_ENV BASE_URL GA_ID STRIPE_PUB_KEY FACEBOOK_KEY GOOGLE_CLIENT_ID AMPLITUDE_KEY PUSHER:KEY PUSHER:ENABLED'
|
||||
.split(' ')
|
||||
.forEach(key => {
|
||||
env[key] = `"${nconf.get(key)}"`;
|
||||
});
|
||||
|
||||
module.exports = env;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
const path = require('path');
|
||||
const config = require('./config');
|
||||
const utils = require('./utils');
|
||||
const projectRoot = path.resolve(__dirname, '../');
|
||||
const webpack = require('webpack');
|
||||
const projectRoot = path.resolve(__dirname, '../');
|
||||
const autoprefixer = require('autoprefixer');
|
||||
const postcssEasyImport = require('postcss-easy-import');
|
||||
const IS_PROD = process.env.NODE_ENV === 'production';
|
||||
|
|
@ -36,7 +36,6 @@ const baseConfig = {
|
|||
path.join(projectRoot, 'node_modules'),
|
||||
],
|
||||
alias: {
|
||||
jquery: 'jquery/src/jquery',
|
||||
website: path.resolve(projectRoot, 'website'),
|
||||
common: path.resolve(projectRoot, 'website/common'),
|
||||
client: path.resolve(projectRoot, 'website/client'),
|
||||
|
|
@ -45,10 +44,7 @@ const baseConfig = {
|
|||
},
|
||||
},
|
||||
plugins: [
|
||||
new webpack.ProvidePlugin({
|
||||
$: 'jquery',
|
||||
jQuery: 'jquery',
|
||||
}),
|
||||
new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/(NOT_EXISTING)$/),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
|
|
|
|||
|
|
@ -1102,55 +1102,55 @@
|
|||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_bamboo_forest {
|
||||
.icon_background_back_of_giant_beast {
|
||||
background-image: url(/static/sprites/spritesmith-main-0.png);
|
||||
background-position: -846px -1480px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_beach {
|
||||
.icon_background_bamboo_forest {
|
||||
background-image: url(/static/sprites/spritesmith-main-0.png);
|
||||
background-position: -846px -1549px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_beehive {
|
||||
.icon_background_beach {
|
||||
background-image: url(/static/sprites/spritesmith-main-0.png);
|
||||
background-position: -1605px -1480px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_bell_tower {
|
||||
.icon_background_beehive {
|
||||
background-image: url(/static/sprites/spritesmith-main-0.png);
|
||||
background-position: -1536px -1480px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_blacksmithy {
|
||||
.icon_background_bell_tower {
|
||||
background-image: url(/static/sprites/spritesmith-main-0.png);
|
||||
background-position: -1467px -1480px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_blizzard {
|
||||
.icon_background_beside_well {
|
||||
background-image: url(/static/sprites/spritesmith-main-0.png);
|
||||
background-position: -1398px -1480px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_blue {
|
||||
.icon_background_blacksmithy {
|
||||
background-image: url(/static/sprites/spritesmith-main-0.png);
|
||||
background-position: -1329px -1480px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_bug_covered_log {
|
||||
.icon_background_blizzard {
|
||||
background-image: url(/static/sprites/spritesmith-main-0.png);
|
||||
background-position: -1260px -1480px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.icon_background_buried_treasure {
|
||||
.icon_background_blue {
|
||||
background-image: url(/static/sprites/spritesmith-main-0.png);
|
||||
background-position: -1191px -1480px;
|
||||
width: 68px;
|
||||
|
|
|
|||
BIN
website/assets/sprites/dist/spritesmith-main-0.png
vendored
|
Before Width: | Height: | Size: 557 KiB After Width: | Height: | Size: 556 KiB |
6450
website/assets/sprites/dist/spritesmith-main-1.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-1.png
vendored
|
Before Width: | Height: | Size: 268 KiB After Width: | Height: | Size: 285 KiB |
3110
website/assets/sprites/dist/spritesmith-main-10.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-10.png
vendored
|
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 279 KiB |
2626
website/assets/sprites/dist/spritesmith-main-11.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-11.png
vendored
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 156 KiB |
1950
website/assets/sprites/dist/spritesmith-main-12.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-12.png
vendored
|
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 152 KiB |
2546
website/assets/sprites/dist/spritesmith-main-13.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-13.png
vendored
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 143 KiB |
2606
website/assets/sprites/dist/spritesmith-main-14.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-14.png
vendored
|
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 150 KiB |
2976
website/assets/sprites/dist/spritesmith-main-15.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-15.png
vendored
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 145 KiB |
3544
website/assets/sprites/dist/spritesmith-main-16.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-16.png
vendored
|
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 155 KiB |
2836
website/assets/sprites/dist/spritesmith-main-17.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-17.png
vendored
|
Before Width: | Height: | Size: 174 KiB After Width: | Height: | Size: 173 KiB |
2560
website/assets/sprites/dist/spritesmith-main-18.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-18.png
vendored
|
Before Width: | Height: | Size: 169 KiB After Width: | Height: | Size: 160 KiB |
1860
website/assets/sprites/dist/spritesmith-main-19.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-19.png
vendored
|
Before Width: | Height: | Size: 466 B After Width: | Height: | Size: 151 KiB |
5364
website/assets/sprites/dist/spritesmith-main-2.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-2.png
vendored
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 56 KiB |
6470
website/assets/sprites/dist/spritesmith-main-3.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-3.png
vendored
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 75 KiB |
4662
website/assets/sprites/dist/spritesmith-main-4.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-4.png
vendored
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 73 KiB |
3996
website/assets/sprites/dist/spritesmith-main-5.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-5.png
vendored
|
Before Width: | Height: | Size: 167 KiB After Width: | Height: | Size: 143 KiB |
2922
website/assets/sprites/dist/spritesmith-main-6.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-6.png
vendored
|
Before Width: | Height: | Size: 157 KiB After Width: | Height: | Size: 136 KiB |
3278
website/assets/sprites/dist/spritesmith-main-7.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-7.png
vendored
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 129 KiB |
2968
website/assets/sprites/dist/spritesmith-main-8.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-8.png
vendored
|
Before Width: | Height: | Size: 316 KiB After Width: | Height: | Size: 115 KiB |
2550
website/assets/sprites/dist/spritesmith-main-9.css
vendored
BIN
website/assets/sprites/dist/spritesmith-main-9.png
vendored
|
Before Width: | Height: | Size: 361 KiB After Width: | Height: | Size: 361 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 3 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 447 B |
|
Before Width: | Height: | Size: 833 B After Width: | Height: | Size: 469 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 479 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 447 B |
|
Before Width: | Height: | Size: 524 B After Width: | Height: | Size: 472 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 513 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 455 B |
|
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 416 B |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 618 B |
|
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 435 B |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 618 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 447 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 464 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 441 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 460 B |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 556 B |