Compare commits
271 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 289032047c | |||
| 6f5515214a | |||
| bbbc06733b | |||
| 92c3a640ee | |||
| bb8bd8842d | |||
| 1411706963 | |||
| e94631a002 | |||
| 39bb60638f | |||
| 71e34e654c | |||
| f01aba15be | |||
| fd4e760c05 | |||
| b5ed65b164 | |||
| 4ee14e7c2a | |||
| f40fb510a9 | |||
| 86951916e8 | |||
| fde8e54783 | |||
| 276e882092 | |||
| 88bfed7efe | |||
| 0936c2ff86 | |||
| bdedf8f563 | |||
| 9220323483 | |||
| 80c93ad934 | |||
| 010da977a4 | |||
| b9bfb3f722 | |||
| effb66a089 | |||
| dbdb5f81a5 | |||
| 2062e78959 | |||
| 018c5edfdd | |||
| b0a3e58d66 | |||
| 99960da2eb | |||
| 8c293505c4 | |||
| 10ac99fc2e | |||
| 34c7d4e3b8 | |||
| 50d9a355b0 | |||
| 35b5285ce6 | |||
| 2001b27c26 | |||
| 7064b363e0 | |||
| c5147a696d | |||
| bd8e67a2ea | |||
| db1bda1bcd | |||
| fe6c21800c | |||
| 2ff9dfe965 | |||
| 75068ceb9e | |||
| 462eac2599 | |||
| 3fe307f6ea | |||
| bb418da91f | |||
| 08856ecc9f | |||
| 9e925513b0 | |||
| d747e97cea | |||
| bccd8e0000 | |||
| 1035af0d25 | |||
| 80b302c997 | |||
| f448c8cdfb | |||
| 77195c64cf | |||
| 1efc030544 | |||
| 5ad30e815a | |||
| 966bcf8010 | |||
| 8ebda9f7bd | |||
| 6192b563e9 | |||
| 6763e178d4 | |||
| 6a9025200c | |||
| 4e3481445c | |||
| 8300464cfc | |||
| abb4899552 | |||
| 90f88c42f6 | |||
| a4f84342ca | |||
| a90d1187e0 | |||
| 88b130a219 | |||
| 637e179951 | |||
| 49e0077c67 | |||
| 0787582e58 | |||
| 1c942eb8f3 | |||
| d67f6ae471 | |||
| 55baed38b5 | |||
| 7ef55d0283 | |||
| 8fac74e812 | |||
| 3f2d1bf430 | |||
| 42cfc7d851 | |||
| ef7724203e | |||
| 09cec21cde | |||
| fc987c11e9 | |||
| 3678861c48 | |||
| a6463e1fba | |||
| 0e4d4c2235 | |||
| 09b76008ea | |||
| c2a79e1d7c | |||
| c5208f0ef6 | |||
| 979d0c519d | |||
| 3f5ee32684 | |||
| 6deee0ffc8 | |||
| a11e4d0512 | |||
| 118e3580d6 | |||
| 343f276705 | |||
| c00a1d74f9 | |||
| ae3f014bb2 | |||
| 15e6cef7c4 | |||
| b8c2d5eb20 | |||
| a444e876d1 | |||
| 24b347af8e | |||
| 76039020f5 | |||
| cbcfb21deb | |||
| f47ec3d85f | |||
| 517d56f9fc | |||
| a5c4871183 | |||
| aee08ba0f9 | |||
| e1f9cac37a | |||
| c9bb96d2be | |||
| b0d86ff37b | |||
| 3f3ebeffa1 | |||
| 1bb337d235 | |||
| 07d6969764 | |||
| 5807db9053 | |||
| a5a91a3a9c | |||
| 3650426edc | |||
| 6543a43854 | |||
| a046930097 | |||
| 7579bec587 | |||
| c1e7fed4d4 | |||
| bad148148c | |||
| 0280513a00 | |||
| e502588abc | |||
| 5718d8396d | |||
| b59a63ecbe | |||
| f0465aab5e | |||
| 39ee78127c | |||
| 4658025f3f | |||
| 46417b4124 | |||
| 706a7b441a | |||
| a8baa8fcfe | |||
| 368cf91e32 | |||
| 23fc969432 | |||
| 5db606dcfd | |||
| 6a5e1dda0e | |||
| 70326e5b5b | |||
| c91c152b53 | |||
| a7fd8f7f52 | |||
| 0b57c0a22d | |||
| 362313fe0a | |||
| ed5dfd0228 | |||
| 12afdc1681 | |||
| 5e31278d2a | |||
| 0891908cba | |||
| 6a483edfe1 | |||
| 962f2b7579 | |||
| f413073d35 | |||
| 0df2da6bf4 | |||
| 27b9ffb3f2 | |||
| 79597cc72b | |||
| 353009821f | |||
| b9a3ee7f30 | |||
| ea3938a91e | |||
| fdfbade493 | |||
| 69179c61b1 | |||
| c6f6722af7 | |||
| b362b36e16 | |||
| f40bb9e91d | |||
| bba068efd5 | |||
| c89b20ce42 | |||
| a60022e54d | |||
| 1d72b0e4a2 | |||
| 15f4ce77ac | |||
| 05093c5552 | |||
| ee733c644d | |||
| cb861d266d | |||
| c7b0269fda | |||
| bd5ef97f22 | |||
| 2e76d06f5e | |||
| b5353717c8 | |||
| 52545018b6 | |||
| d82aa869b2 | |||
| 107d633d37 | |||
| 4f41a8c519 | |||
| 72f0e7ffae | |||
| 30e5fad6b7 | |||
| d3d7ad2693 | |||
| 0e590c3623 | |||
| 6e0739c996 | |||
| 588fd43e65 | |||
| 9a6f8021e3 | |||
| bac84f6ce0 | |||
| 98c9f83001 | |||
| 427d2127cb | |||
| c11a384a35 | |||
| 36481b87fa | |||
| b8362af2f2 | |||
| 80de90cc5f | |||
| 142d7e4348 | |||
| 181552c8d1 | |||
| 6324ef72df | |||
| 3719efa874 | |||
| 107444043e | |||
| e6ba1ccca7 | |||
| 8edd2cfd14 | |||
| 897b192852 | |||
| 0648f5d412 | |||
| 732426c176 | |||
| 4df8022811 | |||
| b153c6d054 | |||
| c0e1a31937 | |||
| 7a13d061d7 | |||
| ac29d662ef | |||
| 247246b99d | |||
| 13fa1924ae | |||
| d55400cc80 | |||
| 100c7c4395 | |||
| 53510e3ea7 | |||
| c643f6a16c | |||
| 1c4a941c88 | |||
| 7c0da8051f | |||
| 6c70076c30 | |||
| 15976e906a | |||
| ac52da5be2 | |||
| 1b39338eec | |||
| 6fe87a8140 | |||
| c5d0ff63a5 | |||
| 6f7243c049 | |||
| 71cc313c9a | |||
| 788992b8fa | |||
| ff87a346d6 | |||
| 99a9bfe62e | |||
| 4f10f534ee | |||
| 2053e6cc40 | |||
| 6a2e84e7cc | |||
| 301b171f55 | |||
| 08baa2ca20 | |||
| 2081590a19 | |||
| f719592237 | |||
| 25ac3db8c3 | |||
| 20472caaee | |||
| 37ab993b01 | |||
| b2cfeaf9bd | |||
| 7c83cfe9b4 | |||
| 57e12c67ac | |||
| 775ed7f873 | |||
| b608ca4d72 | |||
| 1536bbfce5 | |||
| d4957f39a2 | |||
| 6d8833a83f | |||
| bb7b1c15ee | |||
| 9b43ff75fc | |||
| 0aaac9988c | |||
| edcd587b03 | |||
| e0b2437f60 | |||
| 3045be3ddf | |||
| 57b2166bde | |||
| 39b3ebe04a | |||
| 81c58d2122 | |||
| a607882214 | |||
| 0d843d53a5 | |||
| 34145ed8ca | |||
| ad3b673fda | |||
| 4e6b411763 | |||
| dec7bd2ec6 | |||
| 1cc3633e64 | |||
| 64c79b7eb6 | |||
| b2d997c5a6 | |||
| 1b14c5f6d5 | |||
| e800cd9a3f | |||
| 68aeda44d4 | |||
| d5c7ced5e3 | |||
| f45fdfbe0d | |||
| 311df85dfc | |||
| 0e8fb62887 | |||
| 4d2b7dbf5c | |||
| ab4009bd32 | |||
| b6407be529 | |||
| 3477dcd226 | |||
| b41ad76c9e | |||
| 9bfc76cd20 | |||
| 8bd27b8313 | |||
| 8fd7e1cd00 |
@@ -1,8 +1,6 @@
|
||||
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/)
|
||||
|
||||
[Habitica](https://habitica.com) is an open source habit building program which treats your life like a Role Playing Game. Level up as you succeed, lose HP as you fail, earn money to buy weapons and armor.
|
||||
|
||||
**We need more programmers!** Your assistance will be greatly appreciated. The wiki pages below and the additional pages they link to will tell you how to get started on contributing code and where you can go to seek further help or ask questions:
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
"LOGGLY_SUBDOMAIN": "example-subdomain",
|
||||
"LOGGLY_TOKEN": "example-token",
|
||||
"MAINTENANCE_MODE": "false",
|
||||
"NODE_DB_URI": "mongodb://localhost/habitrpg",
|
||||
"NODE_DB_URI": "mongodb://localhost:27017/habitrpg",
|
||||
"MONGODB_POOL_SIZE": "10",
|
||||
"NODE_ENV": "development",
|
||||
"PATH": "bin:node_modules/.bin:/usr/local/bin:/usr/bin:/bin",
|
||||
@@ -70,7 +70,7 @@
|
||||
"SLACK_URL": "https://hooks.slack.com/services/some-url",
|
||||
"STRIPE_API_KEY": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"STRIPE_PUB_KEY": "22223333444455556666777788889999",
|
||||
"TEST_DB_URI": "mongodb://localhost/habitrpg_test",
|
||||
"TEST_DB_URI": "mongodb://localhost:27017/habitrpg_test",
|
||||
"TRANSIFEX_SLACK_CHANNEL": "transifex",
|
||||
"WEB_CONCURRENCY": 1,
|
||||
"SKIP_SSL_CHECK_KEY": "key",
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20200218_pet_color_achievements';
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const set = {
|
||||
migration: MIGRATION_NAME,
|
||||
};
|
||||
|
||||
if (user && user.items && user.items.pets) {
|
||||
const pets = user.items.pets;
|
||||
if (pets['Wolf-CottonCandyPink'] > 0
|
||||
&& pets['TigerCub-CottonCandyPink'] > 0
|
||||
&& pets['PandaCub-CottonCandyPink'] > 0
|
||||
&& pets['LionCub-CottonCandyPink'] > 0
|
||||
&& pets['Fox-CottonCandyPink'] > 0
|
||||
&& pets['FlyingPig-CottonCandyPink'] > 0
|
||||
&& pets['Dragon-CottonCandyPink'] > 0
|
||||
&& pets['Cactus-CottonCandyPink'] > 0
|
||||
&& pets['BearCub-CottonCandyPink'] > 0) {
|
||||
set['achievements.tickledPink'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (user && user.items && user.items.mounts) {
|
||||
const mounts = user.items.mounts;
|
||||
if (mounts['Wolf-CottonCandyPink']
|
||||
&& mounts['TigerCub-CottonCandyPink']
|
||||
&& mounts['PandaCub-CottonCandyPink']
|
||||
&& mounts['LionCub-CottonCandyPink']
|
||||
&& mounts['Fox-CottonCandyPink']
|
||||
&& mounts['FlyingPig-CottonCandyPink']
|
||||
&& mounts['Dragon-CottonCandyPink']
|
||||
&& mounts['Cactus-CottonCandyPink']
|
||||
&& mounts['BearCub-CottonCandyPink'] ) {
|
||||
set['achievements.rosyOutlook'] = 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('2020-02-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
|
||||
}
|
||||
};
|
||||
@@ -8,13 +8,16 @@ const BASE_URL = nconf.get('BASE_URL');
|
||||
const EMAIL_SLUG = 'mandrill-email-slug'; // Set email template to send
|
||||
const MIGRATION_NAME = 'bulk-email';
|
||||
|
||||
const progressCount = 1000;
|
||||
const progressCount = 250;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count += 1;
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
if (count % progressCount === 0) {
|
||||
console.warn(`${count} ${user._id}`);
|
||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
}
|
||||
|
||||
await sendTxn(
|
||||
user,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { model as User } from '../../website/server/models/user';
|
||||
|
||||
const MIGRATION_NAME = '20190314_pi_day';
|
||||
const MIGRATION_NAME = '20200314_pi_day';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
@@ -24,27 +24,37 @@ async function updateUser (user) {
|
||||
'items.food.Pie_Red': 1,
|
||||
};
|
||||
const set = {};
|
||||
let push;
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
set['items.gear.owned.head_special_piDay'] = false;
|
||||
set['items.gear.owned.shield_special_piDay'] = false;
|
||||
const push = [
|
||||
{ type: 'marketGear', path: 'gear.flat.head_special_piDay', _id: uuid() },
|
||||
{ type: 'marketGear', path: 'gear.flat.shield_special_piDay', _id: uuid() },
|
||||
];
|
||||
if (typeof user.items.gear.owned.head_special_piDay !== 'undefined') {
|
||||
push = false;
|
||||
} else {
|
||||
set['items.gear.owned.head_special_piDay'] = false;
|
||||
set['items.gear.owned.shield_special_piDay'] = false;
|
||||
push = [
|
||||
{ type: 'marketGear', path: 'gear.flat.head_special_piDay', _id: uuid() },
|
||||
{ type: 'marketGear', path: 'gear.flat.shield_special_piDay', _id: uuid() },
|
||||
];
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
if (push) {
|
||||
return 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 } } })
|
||||
.update({ _id: user._id }, { $inc: inc, $set: set })
|
||||
.exec();
|
||||
}
|
||||
|
||||
export default async function processUsers () {
|
||||
const query = {
|
||||
migration: { $ne: MIGRATION_NAME },
|
||||
'auth.timestamps.loggedin': { $gt: new Date('2019-02-15') },
|
||||
'auth.timestamps.loggedin': { $gt: new Date('2020-02-15') },
|
||||
};
|
||||
|
||||
const fields = {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "habitica",
|
||||
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
||||
"version": "4.131.1",
|
||||
"version": "4.137.1",
|
||||
"main": "./website/server/index.js",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.8.3",
|
||||
"@babel/preset-env": "^7.8.3",
|
||||
"@babel/register": "^7.8.3",
|
||||
"@babel/core": "^7.8.7",
|
||||
"@babel/preset-env": "^7.8.7",
|
||||
"@babel/register": "^7.8.6",
|
||||
"@google-cloud/trace-agent": "^4.2.5",
|
||||
"@slack/client": "^3.8.1",
|
||||
"accepts": "^1.3.5",
|
||||
@@ -14,8 +14,8 @@
|
||||
"amplitude": "^3.5.0",
|
||||
"apidoc": "^0.17.5",
|
||||
"apn": "^2.2.0",
|
||||
"aws-sdk": "^2.610.0",
|
||||
"bcrypt": "^3.0.7",
|
||||
"aws-sdk": "^2.635.0",
|
||||
"bcrypt": "^3.0.8",
|
||||
"body-parser": "^1.18.3",
|
||||
"compression": "^1.7.4",
|
||||
"cookie-session": "^1.4.0",
|
||||
@@ -34,19 +34,19 @@
|
||||
"gulp": "^4.0.0",
|
||||
"gulp-babel": "^8.0.0",
|
||||
"gulp-imagemin": "^6.2.0",
|
||||
"gulp-nodemon": "^2.4.1",
|
||||
"gulp-nodemon": "^2.5.0",
|
||||
"gulp.spritesmith": "^6.9.0",
|
||||
"habitica-markdown": "^1.3.2",
|
||||
"helmet": "^3.21.2",
|
||||
"helmet": "^3.21.3",
|
||||
"image-size": "^0.8.3",
|
||||
"in-app-purchase": "^1.11.3",
|
||||
"js2xmlparser": "^4.0.0",
|
||||
"js2xmlparser": "^4.0.1",
|
||||
"lodash": "^4.17.15",
|
||||
"merge-stream": "^2.0.0",
|
||||
"method-override": "^3.0.0",
|
||||
"moment": "^2.24.0",
|
||||
"moment-recur": "^1.0.7",
|
||||
"mongoose": "^5.8.9",
|
||||
"mongoose": "^5.9.3",
|
||||
"morgan": "^1.7.0",
|
||||
"nconf": "^0.10.0",
|
||||
"node-gcm": "^1.0.2",
|
||||
@@ -60,17 +60,17 @@
|
||||
"ps-tree": "^1.0.0",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
"remove-markdown": "^0.3.0",
|
||||
"rimraf": "^3.0.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"short-uuid": "^3.0.0",
|
||||
"stripe": "^7.15.0",
|
||||
"superagent": "^5.2.1",
|
||||
"superagent": "^5.2.2",
|
||||
"universal-analytics": "^0.4.17",
|
||||
"useragent": "^2.1.9",
|
||||
"uuid": "^3.4.0",
|
||||
"validator": "^11.0.0",
|
||||
"vinyl-buffer": "^1.0.1",
|
||||
"winston": "^2.4.3",
|
||||
"winston-loggly-bulk": "^2.0.2",
|
||||
"winston": "^3.2.1",
|
||||
"winston-loggly-bulk": "^3.0.1",
|
||||
"xml2js": "^0.4.23"
|
||||
},
|
||||
"private": true,
|
||||
@@ -106,14 +106,14 @@
|
||||
"axios": "^0.19.2",
|
||||
"chai": "^4.1.2",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"chalk": "^2.4.1",
|
||||
"chalk": "^3.0.0",
|
||||
"expect.js": "^0.3.1",
|
||||
"istanbul": "^1.1.0-alpha.1",
|
||||
"mocha": "^5.1.1",
|
||||
"monk": "^7.1.2",
|
||||
"require-again": "^2.0.0",
|
||||
"sinon": "^7.2.4",
|
||||
"sinon-chai": "^3.4.0",
|
||||
"sinon-chai": "^3.5.0",
|
||||
"sinon-stub-promise": "^4.0.0"
|
||||
},
|
||||
"optionalDependencies": {}
|
||||
|
||||
@@ -34,11 +34,12 @@ async function deleteAmplitudeData (userId, email) {
|
||||
}
|
||||
|
||||
async function deleteHabiticaData (user, email) {
|
||||
const truncatedEmail = email.slice(0, email.indexOf('@'));
|
||||
await User.update(
|
||||
{ _id: user._id },
|
||||
{
|
||||
$set: {
|
||||
'auth.local.email': email,
|
||||
'auth.local.email': user.auth.local.email ? email : `${truncatedEmail}@example.com`,
|
||||
'auth.local.hashed_password': '$2a$10$QDnNh1j1yMPnTXDEOV38xOePEWFd4X8DSYwAM8XTmqmacG5X0DKjW',
|
||||
'auth.local.passwordHashMethod': 'bcrypt',
|
||||
},
|
||||
|
||||
@@ -1,14 +1,27 @@
|
||||
import winston from 'winston';
|
||||
import logger from '../../../../website/server/libs/logger';
|
||||
import logger, { _loggerConfig } from '../../../../website/server/libs/logger';
|
||||
import {
|
||||
NotFound,
|
||||
} from '../../../../website/server/libs/errors';
|
||||
|
||||
describe('logger', () => {
|
||||
let logSpy;
|
||||
let infoSpy;
|
||||
let warnSpy;
|
||||
let errorSpy;
|
||||
|
||||
const originalLoggingEnabled = _loggerConfig.loggingEnabled;
|
||||
|
||||
before(() => { // enable logging in tests
|
||||
_loggerConfig.loggingEnabled = true;
|
||||
});
|
||||
|
||||
after(() => { // reset value of _loggerConfig.loggingEnabled
|
||||
_loggerConfig.loggingEnabled = originalLoggingEnabled;
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
logSpy = sandbox.stub(winston.Logger.prototype, 'log');
|
||||
infoSpy = sandbox.stub(_loggerConfig.logger, 'info');
|
||||
warnSpy = sandbox.stub(_loggerConfig.logger, 'warn');
|
||||
errorSpy = sandbox.stub(_loggerConfig.logger, 'error');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -18,8 +31,8 @@ describe('logger', () => {
|
||||
describe('info', () => {
|
||||
it('calls winston\'s info log', () => {
|
||||
logger.info(1, 2, 3);
|
||||
expect(logSpy).to.be.calledOnce;
|
||||
expect(logSpy).to.be.calledWith('info', 1, 2, 3);
|
||||
expect(infoSpy).to.be.calledOnce;
|
||||
expect(infoSpy).to.be.calledWith(1, 2, 3);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -27,8 +40,8 @@ describe('logger', () => {
|
||||
context('non-error object', () => {
|
||||
it('passes through arguments if the first arg is not an error object', () => {
|
||||
logger.error(1, 2, 3, 4);
|
||||
expect(logSpy).to.be.calledOnce;
|
||||
expect(logSpy).to.be.calledWith('error', 1, 2, 3, 4);
|
||||
expect(errorSpy).to.be.calledOnce;
|
||||
expect(errorSpy).to.be.calledWith(1, 2, 3, 4);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -39,9 +52,8 @@ describe('logger', () => {
|
||||
data: 1,
|
||||
}, 2, 3);
|
||||
|
||||
expect(logSpy).to.be.calledOnce;
|
||||
expect(logSpy).to.be.calledWith(
|
||||
'error',
|
||||
expect(errorSpy).to.be.calledOnce;
|
||||
expect(errorSpy).to.be.calledWith(
|
||||
errInstance.stack,
|
||||
{ data: 1, fullError: errInstance },
|
||||
2,
|
||||
@@ -58,9 +70,8 @@ describe('logger', () => {
|
||||
fullError: anotherError,
|
||||
}, 2, 3);
|
||||
|
||||
expect(logSpy).to.be.calledOnce;
|
||||
expect(logSpy).to.be.calledWith(
|
||||
'error',
|
||||
expect(errorSpy).to.be.calledOnce;
|
||||
expect(errorSpy).to.be.calledWith(
|
||||
errInstance.stack,
|
||||
{ data: 1, fullError: anotherError },
|
||||
2,
|
||||
@@ -73,9 +84,8 @@ describe('logger', () => {
|
||||
|
||||
logger.error(errInstance, null, 2, 3);
|
||||
|
||||
expect(logSpy).to.be.calledOnce;
|
||||
expect(logSpy).to.be.calledWith(
|
||||
'error',
|
||||
expect(errorSpy).to.be.calledOnce;
|
||||
expect(errorSpy).to.be.calledWith(
|
||||
errInstance.stack,
|
||||
null,
|
||||
2,
|
||||
@@ -88,9 +98,8 @@ describe('logger', () => {
|
||||
|
||||
logger.error(errInstance, true, 2, 3);
|
||||
|
||||
expect(logSpy).to.be.calledOnce;
|
||||
expect(logSpy).to.be.calledWith(
|
||||
'error',
|
||||
expect(errorSpy).to.be.calledOnce;
|
||||
expect(errorSpy).to.be.calledWith(
|
||||
errInstance.stack,
|
||||
true,
|
||||
2,
|
||||
@@ -103,9 +112,8 @@ describe('logger', () => {
|
||||
|
||||
logger.error(errInstance, { httpCode: 400 }, 2, 3);
|
||||
|
||||
expect(logSpy).to.be.calledOnce;
|
||||
expect(logSpy).to.be.calledWith(
|
||||
'error',
|
||||
expect(errorSpy).to.be.calledOnce;
|
||||
expect(errorSpy).to.be.calledWith(
|
||||
errInstance.stack,
|
||||
{ httpCode: 400, fullError: errInstance },
|
||||
2,
|
||||
@@ -121,9 +129,8 @@ describe('logger', () => {
|
||||
httpCode: 502,
|
||||
}, 2, 3);
|
||||
|
||||
expect(logSpy).to.be.calledOnce;
|
||||
expect(logSpy).to.be.calledWith(
|
||||
'error',
|
||||
expect(errorSpy).to.be.calledOnce;
|
||||
expect(errorSpy).to.be.calledWith(
|
||||
errInstance.stack,
|
||||
{ httpCode: 502, isHandledError: true, fullError: errInstance },
|
||||
2,
|
||||
@@ -139,9 +146,8 @@ describe('logger', () => {
|
||||
httpCode: 403,
|
||||
}, 2, 3);
|
||||
|
||||
expect(logSpy).to.be.calledOnce;
|
||||
expect(logSpy).to.be.calledWith(
|
||||
'warn',
|
||||
expect(warnSpy).to.be.calledOnce;
|
||||
expect(warnSpy).to.be.calledWith(
|
||||
errInstance.stack,
|
||||
{ httpCode: 403, isHandledError: true, fullError: errInstance },
|
||||
2,
|
||||
@@ -156,9 +162,8 @@ describe('logger', () => {
|
||||
|
||||
logger.error(errInstance, {}, 2, 3);
|
||||
|
||||
expect(logSpy).to.be.calledOnce;
|
||||
expect(logSpy).to.be.calledWith(
|
||||
'error',
|
||||
expect(errorSpy).to.be.calledOnce;
|
||||
expect(errorSpy).to.be.calledWith(
|
||||
errInstance.stack,
|
||||
{
|
||||
fullError: {
|
||||
|
||||
@@ -278,19 +278,6 @@ describe('Google Payments', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error if subscription is still valid', async () => {
|
||||
iap.getPurchaseData.restore();
|
||||
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
|
||||
.returns([{ expirationDate: expirationDate.add({ day: 1 }).toDate() }]);
|
||||
|
||||
await expect(googlePayments.cancelSubscribe(user, headers))
|
||||
.to.eventually.be.rejected.and.to.eql({
|
||||
httpCode: 401,
|
||||
name: 'NotAuthorized',
|
||||
message: googlePayments.constants.RESPONSE_STILL_VALID,
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error if receipt is invalid', async () => {
|
||||
iap.isValidated.restore();
|
||||
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
|
||||
|
||||
@@ -34,7 +34,7 @@ describe('response middleware', () => {
|
||||
expect(res.json).to.be.calledWith({
|
||||
success: true,
|
||||
data: { field: 1 },
|
||||
notifications: [],
|
||||
notifications: res.locals.user.notifications,
|
||||
userV: res.locals.user._v,
|
||||
appVersion: packageInfo.version,
|
||||
});
|
||||
@@ -52,7 +52,7 @@ describe('response middleware', () => {
|
||||
success: true,
|
||||
data: { field: 1 },
|
||||
message: 'hello',
|
||||
notifications: [],
|
||||
notifications: res.locals.user.notifications,
|
||||
userV: res.locals.user._v,
|
||||
appVersion: packageInfo.version,
|
||||
});
|
||||
@@ -69,7 +69,7 @@ describe('response middleware', () => {
|
||||
expect(res.json).to.be.calledWith({
|
||||
success: false,
|
||||
data: { field: 1 },
|
||||
notifications: [],
|
||||
notifications: res.locals.user.notifications,
|
||||
userV: res.locals.user._v,
|
||||
appVersion: packageInfo.version,
|
||||
});
|
||||
@@ -84,42 +84,9 @@ describe('response middleware', () => {
|
||||
expect(res.json).to.be.calledWith({
|
||||
success: true,
|
||||
data: { field: 1 },
|
||||
notifications: [],
|
||||
notifications: res.locals.user.notifications,
|
||||
userV: 0,
|
||||
appVersion: packageInfo.version,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns notifications if a user is authenticated', () => {
|
||||
const { user } = res.locals;
|
||||
|
||||
user.notifications = [
|
||||
null, // invalid, not an object
|
||||
{ seen: true }, // invalid, no type or id
|
||||
{ id: 123 }, // invalid, no type
|
||||
// invalid, no id, not included here because the id would be added automatically
|
||||
// {type: 'ABC'},
|
||||
{ type: 'ABC', id: '123' }, // valid
|
||||
];
|
||||
|
||||
responseMiddleware(req, res, next);
|
||||
res.respond(200, { field: 1 });
|
||||
|
||||
expect(res.json).to.be.calledOnce;
|
||||
|
||||
expect(res.json).to.be.calledWith({
|
||||
success: true,
|
||||
data: { field: 1 },
|
||||
notifications: [
|
||||
{
|
||||
type: 'ABC',
|
||||
id: '123',
|
||||
data: {},
|
||||
seen: false,
|
||||
},
|
||||
],
|
||||
userV: res.locals.user._v,
|
||||
appVersion: packageInfo.version,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { sanitizeText } from '../../../../website/server/models/message';
|
||||
import { MAX_MESSAGE_LENGTH } from '../../../../website/common/script/constants';
|
||||
|
||||
describe('Message Model', () => {
|
||||
context('sanitizeText', () => {
|
||||
it('trims messages to the max length', () => {
|
||||
const veryLongMessage = `
|
||||
123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789.
|
||||
THIS PART WON'T BE IN THE MESSAGE (over 3000)
|
||||
`;
|
||||
expect(veryLongMessage.length > MAX_MESSAGE_LENGTH).to.equal(true);
|
||||
|
||||
const sanitizedText = sanitizeText(veryLongMessage);
|
||||
expect(sanitizedText).to.not.contain('MESSAGE');
|
||||
expect(sanitizedText.length).to.equal(MAX_MESSAGE_LENGTH);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import { model as PushDevice } from '../../../../website/server/models/pushDevice';
|
||||
|
||||
describe('PushDevice Model', () => {
|
||||
context('cleanupCorruptData', () => {
|
||||
it('converts an array of push devices to a safe version', () => {
|
||||
const pushDevices = [
|
||||
null, // invalid, not an object
|
||||
{ regId: '123' }, // invalid, no type
|
||||
{ type: 'android' }, // invalid, no regId
|
||||
new PushDevice({ type: 'android', regId: '1234' }), // valid
|
||||
];
|
||||
|
||||
const safePushDevices = PushDevice.cleanupCorruptData(pushDevices);
|
||||
expect(safePushDevices.length).to.equal(1);
|
||||
expect(safePushDevices[0].type).to.equal('android');
|
||||
expect(safePushDevices[0].regId).to.equal('1234');
|
||||
});
|
||||
|
||||
it('removes duplicates', () => {
|
||||
const pushDevices = [
|
||||
new PushDevice({ type: 'android', regId: '1234' }),
|
||||
new PushDevice({ type: 'android', regId: '1234' }),
|
||||
new PushDevice({ type: 'iphone', regId: '1234' }), // not duplicate
|
||||
new PushDevice({ type: 'android', regId: '12345' }), // not duplicate
|
||||
];
|
||||
|
||||
const safePushDevices = PushDevice.cleanupCorruptData(pushDevices);
|
||||
expect(safePushDevices.length).to.equal(3);
|
||||
expect(safePushDevices[0].type).to.equal('android');
|
||||
expect(safePushDevices[0].regId).to.equal('1234');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
import { model as Tag } from '../../../../website/server/models/tag';
|
||||
|
||||
describe('Tag Model', () => {
|
||||
context('cleanupCorruptData', () => {
|
||||
it('converts an array of tags to a safe version', () => {
|
||||
const tags = [
|
||||
null, // invalid, not an object
|
||||
{ name: '123' }, // invalid, no id
|
||||
{ id: '123' }, // invalid, no name
|
||||
new Tag({ name: 'ABC', id: 123 }), // valid
|
||||
];
|
||||
|
||||
const safetags = Tag.cleanupCorruptData(tags);
|
||||
expect(safetags.length).to.equal(1);
|
||||
expect(safetags[0].name).to.equal('ABC');
|
||||
expect(safetags[0].id).to.equal('123');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -181,6 +181,146 @@ describe('User Model', () => {
|
||||
});
|
||||
});
|
||||
|
||||
context('post init', () => {
|
||||
it('removes invalid tags when loading the user', async () => {
|
||||
let user = new User();
|
||||
await user.save();
|
||||
await user.update({
|
||||
$set: {
|
||||
tags: [
|
||||
null, // invalid, not an object
|
||||
// { name: '123' }, // invalid, no id - generated automatically
|
||||
{ id: '123' }, // invalid, no name
|
||||
{ name: 'ABC', id: '1234' }, // valid
|
||||
],
|
||||
},
|
||||
}).exec();
|
||||
|
||||
user = await User.findById(user._id).exec();
|
||||
|
||||
const userToJSON = user.toJSON();
|
||||
expect(userToJSON.tags.length).to.equal(1);
|
||||
|
||||
expect(userToJSON.tags[0]).to.have.all.keys(['id', 'name']);
|
||||
expect(userToJSON.tags[0].id).to.equal('1234');
|
||||
expect(userToJSON.tags[0].name).to.equal('ABC');
|
||||
});
|
||||
|
||||
it('removes invalid push devices when loading the user', async () => {
|
||||
let user = new User();
|
||||
await user.save();
|
||||
await user.update({
|
||||
$set: {
|
||||
pushDevices: [
|
||||
null, // invalid, not an object
|
||||
{ regId: '123' }, // invalid, no type
|
||||
{ type: 'android' }, // invalid, no regId
|
||||
{ type: 'android', regId: '1234' }, // valid
|
||||
],
|
||||
},
|
||||
}).exec();
|
||||
|
||||
user = await User.findById(user._id).exec();
|
||||
|
||||
const userToJSON = user.toJSON();
|
||||
expect(userToJSON.pushDevices.length).to.equal(1);
|
||||
|
||||
expect(userToJSON.pushDevices[0]).to.have.all.keys(['regId', 'type', 'createdAt', 'updatedAt']);
|
||||
expect(userToJSON.pushDevices[0].type).to.equal('android');
|
||||
expect(userToJSON.pushDevices[0].regId).to.equal('1234');
|
||||
});
|
||||
|
||||
it('removes duplicate push devices when loading the user', async () => {
|
||||
let user = new User();
|
||||
await user.save();
|
||||
await user.update({
|
||||
$set: {
|
||||
pushDevices: [
|
||||
{ type: 'android', regId: '1234' },
|
||||
{ type: 'android', regId: '1234' },
|
||||
],
|
||||
},
|
||||
}).exec();
|
||||
|
||||
user = await User.findById(user._id).exec();
|
||||
|
||||
const userToJSON = user.toJSON();
|
||||
expect(userToJSON.pushDevices.length).to.equal(1);
|
||||
|
||||
expect(userToJSON.pushDevices[0]).to.have.all.keys(['regId', 'type', 'createdAt', 'updatedAt']);
|
||||
expect(userToJSON.pushDevices[0].type).to.equal('android');
|
||||
expect(userToJSON.pushDevices[0].regId).to.equal('1234');
|
||||
});
|
||||
|
||||
it('removes invalid notifications when loading the user', async () => {
|
||||
let user = new User();
|
||||
await user.save();
|
||||
await user.update({
|
||||
$set: {
|
||||
notifications: [
|
||||
null, // invalid, not an object
|
||||
{ seen: true }, // invalid, no type or id
|
||||
{ id: 123 }, // invalid, no type
|
||||
// invalid, no id, not included here because the id would be added automatically
|
||||
// {type: 'ABC'},
|
||||
{ type: 'ABC', id: '123' }, // valid
|
||||
],
|
||||
},
|
||||
}).exec();
|
||||
|
||||
user = await User.findById(user._id).exec();
|
||||
|
||||
const userToJSON = user.toJSON();
|
||||
expect(userToJSON.notifications.length).to.equal(1);
|
||||
|
||||
expect(userToJSON.notifications[0]).to.have.all.keys(['data', 'id', 'type', 'seen']);
|
||||
expect(userToJSON.notifications[0].type).to.equal('ABC');
|
||||
expect(userToJSON.notifications[0].id).to.equal('123');
|
||||
});
|
||||
|
||||
it('removes multiple NEW_CHAT_MESSAGE for the same group', async () => {
|
||||
let user = new User();
|
||||
await user.save();
|
||||
await user.update({
|
||||
$set: {
|
||||
notifications: [
|
||||
{
|
||||
type: 'NEW_CHAT_MESSAGE',
|
||||
id: 123,
|
||||
data: { group: { id: 12345 } },
|
||||
},
|
||||
{
|
||||
type: 'NEW_CHAT_MESSAGE',
|
||||
id: 1234,
|
||||
data: { group: { id: 12345 } },
|
||||
},
|
||||
{
|
||||
type: 'NEW_CHAT_MESSAGE',
|
||||
id: 123,
|
||||
data: { group: { id: 123456 } },
|
||||
}, // not duplicate, different group
|
||||
{
|
||||
type: 'NEW_CHAT_MESSAGE_DIFF',
|
||||
id: 123,
|
||||
data: { group: { id: 12345 } },
|
||||
}, // not duplicate, different type
|
||||
],
|
||||
},
|
||||
}).exec();
|
||||
|
||||
user = await User.findById(user._id).exec();
|
||||
|
||||
const userToJSON = user.toJSON();
|
||||
expect(userToJSON.notifications.length).to.equal(3);
|
||||
|
||||
expect(userToJSON.notifications[0]).to.have.all.keys(['data', 'id', 'type', 'seen']);
|
||||
expect(userToJSON.notifications[0].type).to.equal('NEW_CHAT_MESSAGE');
|
||||
expect(userToJSON.notifications[0].id).to.equal('123');
|
||||
expect(userToJSON.notifications[0].data).to.deep.equal({ group: { id: 12345 } });
|
||||
expect(userToJSON.notifications[0].seen).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('notifications', () => {
|
||||
it('can add notifications without data', () => {
|
||||
const user = new User();
|
||||
@@ -195,26 +335,6 @@ describe('User Model', () => {
|
||||
expect(userToJSON.notifications[0].seen).to.eql(false);
|
||||
});
|
||||
|
||||
it('removes invalid notifications when calling toJSON', () => {
|
||||
const user = new User();
|
||||
|
||||
user.notifications = [
|
||||
null, // invalid, not an object
|
||||
{ seen: true }, // invalid, no type or id
|
||||
{ id: 123 }, // invalid, no type
|
||||
// invalid, no id, not included here because the id would be added automatically
|
||||
// {type: 'ABC'},
|
||||
{ type: 'ABC', id: '123' }, // valid
|
||||
];
|
||||
|
||||
const userToJSON = user.toJSON();
|
||||
expect(userToJSON.notifications.length).to.equal(1);
|
||||
|
||||
expect(userToJSON.notifications[0]).to.have.all.keys(['data', 'id', 'type', 'seen']);
|
||||
expect(userToJSON.notifications[0].type).to.equal('ABC');
|
||||
expect(userToJSON.notifications[0].id).to.equal('123');
|
||||
});
|
||||
|
||||
it('can add notifications with data and already marked as seen', () => {
|
||||
const user = new User();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { model as UserNotification } from '../../../../website/server/models/userNotification';
|
||||
|
||||
describe('UserNotification Model', () => {
|
||||
context('convertNotificationsToSafeJson', () => {
|
||||
context('cleanupCorruptData', () => {
|
||||
it('converts an array of notifications to a safe version', () => {
|
||||
const notifications = [
|
||||
null, // invalid, not an object
|
||||
@@ -11,11 +11,44 @@ describe('UserNotification Model', () => {
|
||||
new UserNotification({ type: 'ABC', id: 123 }), // valid
|
||||
];
|
||||
|
||||
const notificationsToJSON = UserNotification.convertNotificationsToSafeJson(notifications);
|
||||
expect(notificationsToJSON.length).to.equal(1);
|
||||
expect(notificationsToJSON[0]).to.have.all.keys(['data', 'id', 'type', 'seen']);
|
||||
expect(notificationsToJSON[0].type).to.equal('ABC');
|
||||
expect(notificationsToJSON[0].id).to.equal('123');
|
||||
const safeNotifications = UserNotification.cleanupCorruptData(notifications);
|
||||
expect(safeNotifications.length).to.equal(1);
|
||||
expect(safeNotifications[0].data).to.deep.equal({});
|
||||
expect(safeNotifications[0].seen).to.equal(false);
|
||||
expect(safeNotifications[0].type).to.equal('ABC');
|
||||
expect(safeNotifications[0].id).to.equal('123');
|
||||
});
|
||||
|
||||
it('removes multiple NEW_CHAT_MESSAGE for the same group', () => {
|
||||
const notifications = [
|
||||
new UserNotification({
|
||||
type: 'NEW_CHAT_MESSAGE',
|
||||
id: 123,
|
||||
data: { group: { id: 12345 } },
|
||||
}),
|
||||
new UserNotification({
|
||||
type: 'NEW_CHAT_MESSAGE',
|
||||
id: 1234,
|
||||
data: { group: { id: 12345 } },
|
||||
}),
|
||||
new UserNotification({
|
||||
type: 'NEW_CHAT_MESSAGE',
|
||||
id: 123,
|
||||
data: { group: { id: 123456 } },
|
||||
}), // not duplicate, different group
|
||||
new UserNotification({
|
||||
type: 'NEW_CHAT_MESSAGE_DIFF',
|
||||
id: 123,
|
||||
data: { group: { id: 12345 } },
|
||||
}), // not duplicate, different type
|
||||
];
|
||||
|
||||
const safeNotifications = UserNotification.cleanupCorruptData(notifications);
|
||||
expect(safeNotifications.length).to.equal(3);
|
||||
expect(safeNotifications[0].data).to.deep.equal({ group: { id: 12345 } });
|
||||
expect(safeNotifications[0].seen).to.equal(false);
|
||||
expect(safeNotifications[0].type).to.equal('NEW_CHAT_MESSAGE');
|
||||
expect(safeNotifications[0].id).to.equal('123');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -187,8 +187,7 @@ describe('GET challenges/groups/:groupId', () => {
|
||||
});
|
||||
|
||||
context('official challenge is present', () => {
|
||||
let publicGuild; let user; let officialChallenge; let challenge; let
|
||||
challenge2;
|
||||
let publicGuild; let user; let officialChallenge; let unofficialChallenges;
|
||||
|
||||
before(async () => {
|
||||
const { group, groupLeader } = await createAndPopulateGroup({
|
||||
@@ -214,10 +213,14 @@ describe('GET challenges/groups/:groupId', () => {
|
||||
});
|
||||
await user.post(`/challenges/${officialChallenge._id}/join`);
|
||||
|
||||
challenge = await generateChallenge(user, group);
|
||||
await user.post(`/challenges/${challenge._id}/join`);
|
||||
challenge2 = await generateChallenge(user, group);
|
||||
await user.post(`/challenges/${challenge2._id}/join`);
|
||||
// We add 10 extra challenges to test whether the official challenge
|
||||
// (the oldest) makes it to the front page.
|
||||
unofficialChallenges = [];
|
||||
for (let i = 0; i < 10; i += 1) {
|
||||
const challenge = await generateChallenge(user, group); // eslint-disable-line
|
||||
await user.post(`/challenges/${challenge._id}/join`); // eslint-disable-line
|
||||
unofficialChallenges.push(challenge);
|
||||
}
|
||||
});
|
||||
|
||||
it('should return official challenges first', async () => {
|
||||
@@ -230,18 +233,17 @@ describe('GET challenges/groups/:groupId', () => {
|
||||
it('should return newest challenges first, after official ones', async () => {
|
||||
let challenges = await user.get(`/challenges/groups/${publicGuild._id}`);
|
||||
|
||||
let foundChallengeIndex = _.findIndex(challenges, { _id: challenge._id });
|
||||
expect(foundChallengeIndex).to.eql(2);
|
||||
|
||||
foundChallengeIndex = _.findIndex(challenges, { _id: challenge2._id });
|
||||
expect(foundChallengeIndex).to.eql(1);
|
||||
unofficialChallenges.forEach((chal, index) => {
|
||||
const foundChallengeIndex = _.findIndex(challenges, { _id: chal._id });
|
||||
expect(foundChallengeIndex).to.eql(10 - index);
|
||||
});
|
||||
|
||||
const newChallenge = await generateChallenge(user, publicGuild);
|
||||
await user.post(`/challenges/${newChallenge._id}/join`);
|
||||
|
||||
challenges = await user.get(`/challenges/groups/${publicGuild._id}`);
|
||||
|
||||
foundChallengeIndex = _.findIndex(challenges, { _id: newChallenge._id });
|
||||
const foundChallengeIndex = _.findIndex(challenges, { _id: newChallenge._id });
|
||||
expect(foundChallengeIndex).to.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -242,7 +242,7 @@ describe('GET challenges/user', () => {
|
||||
});
|
||||
|
||||
context('official challenge is present', () => {
|
||||
let user; let officialChallenge; let challenge; let challenge2; let
|
||||
let user; let officialChallenge; let unofficialChallenges; let
|
||||
publicGuild;
|
||||
|
||||
before(async () => {
|
||||
@@ -270,10 +270,14 @@ describe('GET challenges/user', () => {
|
||||
});
|
||||
await user.post(`/challenges/${officialChallenge._id}/join`);
|
||||
|
||||
challenge = await generateChallenge(user, group);
|
||||
await user.post(`/challenges/${challenge._id}/join`);
|
||||
challenge2 = await generateChallenge(user, group);
|
||||
await user.post(`/challenges/${challenge2._id}/join`);
|
||||
// We add 10 extra challenges to test whether the official challenge
|
||||
// (the oldest) makes it to the front page.
|
||||
unofficialChallenges = [];
|
||||
for (let i = 0; i < 10; i += 1) {
|
||||
const challenge = await generateChallenge(user, group); // eslint-disable-line
|
||||
await user.post(`/challenges/${challenge._id}/join`); // eslint-disable-line
|
||||
unofficialChallenges.push(challenge);
|
||||
}
|
||||
});
|
||||
|
||||
it('should return official challenges first', async () => {
|
||||
@@ -284,20 +288,23 @@ describe('GET challenges/user', () => {
|
||||
});
|
||||
|
||||
it('should return newest challenges first, after official ones', async () => {
|
||||
let challenges = await user.get('/challenges/user');
|
||||
let challenges = await user.get('/challenges/user?page=0');
|
||||
|
||||
let foundChallengeIndex = _.findIndex(challenges, { _id: challenge._id });
|
||||
expect(foundChallengeIndex).to.eql(2);
|
||||
|
||||
foundChallengeIndex = _.findIndex(challenges, { _id: challenge2._id });
|
||||
expect(foundChallengeIndex).to.eql(1);
|
||||
unofficialChallenges.forEach((chal, index) => {
|
||||
const foundChallengeIndex = _.findIndex(challenges, { _id: chal._id });
|
||||
if (index === 0) {
|
||||
expect(foundChallengeIndex).to.eql(-1);
|
||||
} else {
|
||||
expect(foundChallengeIndex).to.eql(10 - index);
|
||||
}
|
||||
});
|
||||
|
||||
const newChallenge = await generateChallenge(user, publicGuild);
|
||||
await user.post(`/challenges/${newChallenge._id}/join`);
|
||||
|
||||
challenges = await user.get('/challenges/user');
|
||||
|
||||
foundChallengeIndex = _.findIndex(challenges, { _id: newChallenge._id });
|
||||
const foundChallengeIndex = _.findIndex(challenges, { _id: newChallenge._id });
|
||||
expect(foundChallengeIndex).to.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
SPAM_MIN_EXEMPT_CONTRIB_LEVEL,
|
||||
TAVERN_ID,
|
||||
} from '../../../../../website/server/models/group';
|
||||
import { CHAT_FLAG_FROM_SHADOW_MUTE } from '../../../../../website/common/script/constants';
|
||||
import { CHAT_FLAG_FROM_SHADOW_MUTE, MAX_MESSAGE_LENGTH } from '../../../../../website/common/script/constants';
|
||||
import { getMatchesByWordArray } from '../../../../../website/server/libs/stringUtils';
|
||||
import bannedWords from '../../../../../website/server/libs/bannedWords';
|
||||
import guildsAllowingBannedWords from '../../../../../website/server/libs/guildsAllowingBannedWords';
|
||||
@@ -494,6 +494,7 @@ describe('POST /chat', () => {
|
||||
123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789.
|
||||
THIS PART WON'T BE IN THE MESSAGE (over 3000)
|
||||
`;
|
||||
expect(veryLongMessage.length > MAX_MESSAGE_LENGTH).to.equal(true);
|
||||
|
||||
const newMessage = await user.post(`/groups/${groupWithChat._id}/chat`, { message: veryLongMessage });
|
||||
const groupMessages = await user.get(`/groups/${groupWithChat._id}/chat`);
|
||||
@@ -501,9 +502,27 @@ describe('POST /chat', () => {
|
||||
expect(newMessage.message.id).to.exist;
|
||||
expect(groupMessages[0].id).to.exist;
|
||||
|
||||
expect(newMessage.message.text.length).to.eql(3000);
|
||||
expect(newMessage.message.text.length).to.eql(MAX_MESSAGE_LENGTH);
|
||||
expect(newMessage.message.text).to.not.contain('MESSAGE');
|
||||
expect(groupMessages[0].text.length).to.eql(3000);
|
||||
expect(groupMessages[0].text.length).to.eql(MAX_MESSAGE_LENGTH);
|
||||
});
|
||||
|
||||
it('chat message with mentions - mention link should not count towards 3000 chars limit', async () => {
|
||||
const memberUsername = 'memberUsername';
|
||||
await member.update({ 'auth.local.username': memberUsername });
|
||||
|
||||
const messageWithMentions = `hi @${memberUsername} 123456789
|
||||
123456789 123456789 123456789 123456789 123456789 123456789 89 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 12345678 END.`;
|
||||
expect(messageWithMentions.length).to.equal(MAX_MESSAGE_LENGTH);
|
||||
const newMessage = await user.post(`/groups/${groupWithChat._id}/chat`, { message: messageWithMentions });
|
||||
const groupMessages = await user.get(`/groups/${groupWithChat._id}/chat`);
|
||||
|
||||
const mentionLink = `[@${memberUsername}](/profile/${member._id})`;
|
||||
expect(newMessage.message.text).to.include(mentionLink);
|
||||
expect(newMessage.message.text).to.include(' END.');
|
||||
expect(newMessage.message.text.length)
|
||||
.to.eql(messageWithMentions.length - (`@${memberUsername}`).length + mentionLink.length);
|
||||
expect(groupMessages[0].text.length).to.eql(newMessage.message.text.length);
|
||||
});
|
||||
|
||||
it('creates a chat with user styles', async () => {
|
||||
|
||||
@@ -17,7 +17,7 @@ describe('payments - stripe - #checkout', () => {
|
||||
await expect(user.post(endpoint, { id: 123 })).to.eventually.be.rejected.and.include({
|
||||
code: 401,
|
||||
error: 'Error',
|
||||
message: 'Invalid API Key provided: aaaabbbb********************1111',
|
||||
// message: 'Invalid API Key provided: aaaabbbb********************1111',
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ describe('POST /groups/:groupId/quests/accept', () => {
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('questAlreadyUnderway'),
|
||||
message: t('questAlreadyStartedFriendly'),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -73,7 +73,7 @@ describe('POST /groups/:groupId/quests/force-start', () => {
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('questAlreadyUnderway'),
|
||||
message: t('questAlreadyStarted'),
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ describe('POST /groups/:groupId/quests/reject', () => {
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
error: 'NotAuthorized',
|
||||
message: t('questAlreadyUnderway'),
|
||||
message: t('questAlreadyStartedFriendly'),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -125,7 +125,7 @@ describe('PUT /user', () => {
|
||||
context('Sub-Level Protected Operations', () => {
|
||||
const protectedOperations = {
|
||||
'class stat': { 'stats.class': 'wizard' },
|
||||
'flags unless whitelisted': { 'flags.dropsEnabled': true },
|
||||
'flags unless whitelisted': { 'flags.chatRevoked': true },
|
||||
webhooks: { 'preferences.webhooks': [1, 2, 3] },
|
||||
sleep: { 'preferences.sleep': true },
|
||||
'disable classes': { 'preferences.disableClasses': true },
|
||||
|
||||
@@ -109,7 +109,7 @@ describe('PUT /user', () => {
|
||||
context('Sub-Level Protected Operations', () => {
|
||||
const protectedOperations = {
|
||||
'class stat': { 'stats.class': 'wizard' },
|
||||
'flags unless whitelisted': { 'flags.dropsEnabled': true },
|
||||
'flags unless whitelisted': { 'flags.chatRevoked': true },
|
||||
webhooks: { 'preferences.webhooks': [1, 2, 3] },
|
||||
sleep: { 'preferences.sleep': true },
|
||||
'disable classes': { 'preferences.disableClasses': true },
|
||||
|
||||
@@ -15,6 +15,7 @@ describe('common.fns.randomDrop', () => {
|
||||
beforeEach(() => {
|
||||
user = generateUser();
|
||||
user._tmp = user._tmp ? user._tmp : {};
|
||||
user.items.eggs.Wolf = 0;
|
||||
task = generateTodo({ userId: user._id });
|
||||
predictableRandom = sandbox.stub().returns(0.5);
|
||||
});
|
||||
@@ -34,10 +35,17 @@ describe('common.fns.randomDrop', () => {
|
||||
|
||||
context('drops enabled', () => {
|
||||
beforeEach(() => {
|
||||
user.flags.dropsEnabled = true;
|
||||
task.priority = 100000;
|
||||
});
|
||||
|
||||
it('awards an egg and a hatching potion if user has never received any', () => {
|
||||
delete user.items.eggs.Wolf;
|
||||
randomDrop(user, { task, predictableRandom });
|
||||
|
||||
expect(user._tmp.firstDrops.egg).to.be.a.string;
|
||||
expect(user._tmp.firstDrops.hatchingPotion).to.be.a.string;
|
||||
});
|
||||
|
||||
it('does nothing if user.items.lastDrop.count is exceeded', () => {
|
||||
user.items.lastDrop.count = 100;
|
||||
randomDrop(user, { task, predictableRandom });
|
||||
@@ -46,7 +54,6 @@ describe('common.fns.randomDrop', () => {
|
||||
|
||||
it('drops something when the task is a todo', () => {
|
||||
expect(user._tmp).to.eql({});
|
||||
user.flags.dropsEnabled = true;
|
||||
predictableRandom.returns(0.1);
|
||||
|
||||
randomDrop(user, { task, predictableRandom });
|
||||
@@ -56,7 +63,6 @@ describe('common.fns.randomDrop', () => {
|
||||
it('drops something when the task is a habit', () => {
|
||||
task = generateHabit({ userId: user._id });
|
||||
expect(user._tmp).to.eql({});
|
||||
user.flags.dropsEnabled = true;
|
||||
predictableRandom.returns(0.1);
|
||||
|
||||
randomDrop(user, { task, predictableRandom });
|
||||
@@ -66,7 +72,6 @@ describe('common.fns.randomDrop', () => {
|
||||
it('drops something when the task is a daily', () => {
|
||||
task = generateDaily({ userId: user._id });
|
||||
expect(user._tmp).to.eql({});
|
||||
user.flags.dropsEnabled = true;
|
||||
predictableRandom.returns(0.1);
|
||||
|
||||
randomDrop(user, { task, predictableRandom });
|
||||
@@ -76,7 +81,6 @@ describe('common.fns.randomDrop', () => {
|
||||
it('drops something when the task is a reward', () => {
|
||||
task = generateReward({ userId: user._id });
|
||||
expect(user._tmp).to.eql({});
|
||||
user.flags.dropsEnabled = true;
|
||||
predictableRandom.returns(0.1);
|
||||
|
||||
randomDrop(user, { task, predictableRandom });
|
||||
|
||||
@@ -110,13 +110,6 @@ describe('common.fns.updateStats', () => {
|
||||
expect(user.stats.points).to.eql(10);
|
||||
});
|
||||
|
||||
it('add user notification when drops are enabled', () => {
|
||||
user.stats.lvl = 3;
|
||||
updateStats(user, { });
|
||||
expect(user.addNotification).to.be.calledOnce;
|
||||
expect(user.addNotification).to.be.calledWith('DROPS_ENABLED');
|
||||
});
|
||||
|
||||
it('add user notification when the user levels up', () => {
|
||||
const initialLvl = user.stats.lvl;
|
||||
updateStats(user, {
|
||||
@@ -131,7 +124,7 @@ describe('common.fns.updateStats', () => {
|
||||
it('add user notification when rebirth is enabled', () => {
|
||||
user.stats.lvl = 51;
|
||||
updateStats(user, { });
|
||||
expect(user.addNotification).to.be.calledTwice; // once is for drops enabled
|
||||
expect(user.addNotification).to.be.calledOnce;
|
||||
expect(user.addNotification).to.be.calledWith('REBIRTH_ENABLED');
|
||||
});
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from '../../../helpers/common.helper';
|
||||
|
||||
describe('shared.ops.purchase', () => {
|
||||
const SEASONAL_FOOD = 'Cake_Base';
|
||||
const SEASONAL_FOOD = 'Meat';
|
||||
let user;
|
||||
const goldPoints = 40;
|
||||
const analytics = { track () {} };
|
||||
|
||||
@@ -173,7 +173,6 @@ describe('shared.ops.rebirth', () => {
|
||||
|
||||
it('resets a user\'s flags', () => {
|
||||
user.flags.itemsEnabled = true;
|
||||
user.flags.dropsEnabled = true;
|
||||
user.flags.classSelected = true;
|
||||
user.flags.rebirthEnabled = true;
|
||||
user.flags.levelDrops = { test: 'test' };
|
||||
@@ -181,7 +180,6 @@ describe('shared.ops.rebirth', () => {
|
||||
rebirth(user);
|
||||
|
||||
expect(user.flags.itemsEnabled).to.be.false;
|
||||
expect(user.flags.dropsEnabled).to.be.false;
|
||||
expect(user.flags.classSelected).to.be.false;
|
||||
expect(user.flags.rebirthEnabled).to.be.false;
|
||||
expect(user.flags.levelDrops).to.be.empty;
|
||||
|
||||
@@ -13,41 +13,41 @@
|
||||
"test:unit": "vue-cli-service test:unit --require ./tests/unit/helpers.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vue/cli-plugin-babel": "^4.1.2",
|
||||
"@vue/cli-plugin-eslint": "^4.1.2",
|
||||
"@vue/cli-plugin-router": "^4.1.2",
|
||||
"@vue/cli-plugin-unit-mocha": "^4.1.2",
|
||||
"@vue/cli-service": "^4.1.2",
|
||||
"@storybook/addon-actions": "^5.3.9",
|
||||
"@storybook/addon-knobs": "^5.3.9",
|
||||
"@storybook/addon-links": "^5.3.9",
|
||||
"@storybook/addon-notes": "^5.3.9",
|
||||
"@storybook/vue": "^5.3.9",
|
||||
"@vue/cli-plugin-babel": "^4.2.3",
|
||||
"@vue/cli-plugin-eslint": "^4.2.3",
|
||||
"@vue/cli-plugin-router": "^4.2.3",
|
||||
"@vue/cli-plugin-unit-mocha": "^4.2.3",
|
||||
"@vue/cli-service": "^4.2.3",
|
||||
"@storybook/addon-actions": "^5.3.14",
|
||||
"@storybook/addon-knobs": "^5.3.14",
|
||||
"@storybook/addon-links": "^5.3.14",
|
||||
"@storybook/addon-notes": "^5.3.14",
|
||||
"@storybook/vue": "^5.3.14",
|
||||
"@vue/test-utils": "1.0.0-beta.29",
|
||||
"amplitude-js": "^5.8.0",
|
||||
"amplitude-js": "^5.9.0",
|
||||
"axios": "^0.19.2",
|
||||
"axios-progress-bar": "^1.2.0",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"bootstrap": "^4.4.1",
|
||||
"bootstrap-vue": "^2.3.0",
|
||||
"bootstrap-vue": "^2.6.1",
|
||||
"chai": "^4.1.2",
|
||||
"core-js": "^3.6.4",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-habitrpg": "^6.2.0",
|
||||
"eslint-plugin-mocha": "^5.3.0",
|
||||
"eslint-plugin-vue": "^6.1.2",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"habitica-markdown": "^1.3.2",
|
||||
"hellojs": "^1.18.4",
|
||||
"inspectpack": "^4.3.1",
|
||||
"inspectpack": "^4.4.0",
|
||||
"intro.js": "^2.9.3",
|
||||
"jquery": "^3.4.1",
|
||||
"lodash": "^4.17.15",
|
||||
"moment": "^2.24.0",
|
||||
"nconf": "^0.10.0",
|
||||
"sass": "^1.25.0",
|
||||
"sass": "^1.26.2",
|
||||
"sass-loader": "^8.0.2",
|
||||
"smartbanner.js": "^1.15.0",
|
||||
"svg-inline-loader": "^0.8.0",
|
||||
"svg-inline-loader": "^0.8.2",
|
||||
"svg-url-loader": "^3.0.3",
|
||||
"svgo": "^1.3.2",
|
||||
"svgo-loader": "^2.2.1",
|
||||
@@ -56,11 +56,11 @@
|
||||
"vue": "^2.6.11",
|
||||
"vue-cli-plugin-storybook": "^0.6.1",
|
||||
"vue-mugen-scroll": "^0.2.6",
|
||||
"vue-router": "^3.1.5",
|
||||
"vue-router": "^3.1.6",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"vue2-perfect-scrollbar": "^1.3.0",
|
||||
"vuedraggable": "^2.23.1",
|
||||
"vuejs-datepicker": "git://github.com/habitrpg/vuejs-datepicker.git#5d237615463a84a23dd6f3f77c6ab577d68593ec",
|
||||
"webpack": "^4.41.5"
|
||||
"webpack": "^4.42.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -757,5 +757,6 @@ export default {
|
||||
<style src="@/assets/css/sprites/spritesmith-main-24.css"></style>
|
||||
<style src="@/assets/css/sprites/spritesmith-main-25.css"></style>
|
||||
<style src="@/assets/css/sprites/spritesmith-main-26.css"></style>
|
||||
<style src="@/assets/css/sprites/spritesmith-main-27.css"></style>
|
||||
<style src="@/assets/css/sprites.css"></style>
|
||||
<style src="smartbanner.js/dist/smartbanner.min.css"></style>
|
||||
|
||||
@@ -1,96 +1,60 @@
|
||||
.promo_armoire_backgrounds_202001 {
|
||||
.promo_achievement_CottonCandyPink {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -323px;
|
||||
background-position: -328px -316px;
|
||||
width: 204px;
|
||||
height: 102px;
|
||||
}
|
||||
.promo_armoire_backgrounds_202003 {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -445px;
|
||||
width: 423px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_birthday_2020 {
|
||||
.promo_cosplay {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -421px 0px;
|
||||
width: 498px;
|
||||
height: 144px;
|
||||
background-position: 0px 0px;
|
||||
width: 623px;
|
||||
height: 167px;
|
||||
}
|
||||
.promo_mystery_022020 {
|
||||
.promo_hugabug_bundle {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -619px;
|
||||
background-position: -424px -445px;
|
||||
width: 420px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_mystery_202003 {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -624px -211px;
|
||||
width: 282px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_mystery_202001 {
|
||||
.promo_pi_day {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -566px -619px;
|
||||
width: 279px;
|
||||
background-position: 0px -593px;
|
||||
width: 273px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_seasonal_shop {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -920px -181px;
|
||||
width: 162px;
|
||||
height: 138px;
|
||||
}
|
||||
.promo_snowballs {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px 0px;
|
||||
width: 420px;
|
||||
height: 174px;
|
||||
}
|
||||
.promo_take_this {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -920px -396px;
|
||||
background-position: -624px -359px;
|
||||
width: 96px;
|
||||
height: 69px;
|
||||
}
|
||||
.promo_winter_potions_2020 {
|
||||
.scene_dailies {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -469px -175px;
|
||||
width: 423px;
|
||||
height: 147px;
|
||||
background-position: 0px -168px;
|
||||
width: 327px;
|
||||
height: 276px;
|
||||
}
|
||||
.promo_winter_quests_bundle {
|
||||
.scene_gaining_achievement {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -424px -323px;
|
||||
width: 423px;
|
||||
height: 147px;
|
||||
background-position: -624px 0px;
|
||||
width: 339px;
|
||||
height: 210px;
|
||||
}
|
||||
.promo_winter_wonderland_2019 {
|
||||
.scene_shanaqui {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -421px -471px;
|
||||
width: 402px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_winter_wonderland_2020 {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -175px;
|
||||
width: 468px;
|
||||
height: 147px;
|
||||
}
|
||||
.promo_wintery_hair {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -920px -320px;
|
||||
width: 152px;
|
||||
height: 75px;
|
||||
}
|
||||
.promo_wintery_skins {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: 0px -471px;
|
||||
width: 420px;
|
||||
height: 147px;
|
||||
}
|
||||
.customize-option.promo_wintery_skins {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -25px -486px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
.scene_beffymaroo {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -283px -619px;
|
||||
background-position: -328px -168px;
|
||||
width: 282px;
|
||||
height: 147px;
|
||||
}
|
||||
.scene_rewards {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
|
||||
background-position: -920px 0px;
|
||||
width: 207px;
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,552 @@
|
||||
.Pet-Whale-Skeleton {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -82px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-White {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -492px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Whale-Zombie {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -164px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Amber {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: 0px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Aquatic {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -82px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Aurora {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -164px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Base {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -246px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Bronze {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -246px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Celestial {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: 0px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-CottonCandyBlue {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -82px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-CottonCandyPink {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -164px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Cupid {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -246px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Desert {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -328px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Ember {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -328px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Fairy {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -328px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Floral {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: 0px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Frost {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -82px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Ghost {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -164px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Glass {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -246px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Glow {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -328px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Golden {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -410px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Holly {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -410px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-IcySnow {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -410px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Peppermint {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -410px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Rainbow {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -492px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Red {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -492px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-RoseQuartz {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -492px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-RoyalPurple {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -492px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Ruby {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: 0px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Shade {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -82px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Shadow {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -164px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Shimmer {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -246px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Silver {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -328px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Skeleton {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -410px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Spooky {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -492px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-StarryNight {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -574px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Sunshine {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -574px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Thunderstorm {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -574px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Veggie {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -574px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Veteran {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -574px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Watery {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: 0px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-White {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -82px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Zombie {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -164px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Base {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -246px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-CottonCandyBlue {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -328px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-CottonCandyPink {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -410px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Desert {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: 0px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Golden {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -574px -500px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Red {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -656px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Shade {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -656px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Skeleton {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -656px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-White {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -656px -300px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Yarn-Zombie {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -656px -400px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet_HatchingPotion_Amber {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: 0px -600px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Aquatic {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -552px -669px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Aurora {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -69px -600px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Base {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -138px -600px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Bronze {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -207px -600px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Celestial {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -276px -600px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_CottonCandyBlue {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -345px -600px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_CottonCandyPink {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -414px -600px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Cupid {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -483px -600px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Desert {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -552px -600px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Ember {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -621px -600px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Fairy {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: 0px -669px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Floral {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -69px -669px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Frost {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -138px -669px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Ghost {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -207px -669px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Glass {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -276px -669px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Glow {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -345px -669px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Golden {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -414px -669px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Holly {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -483px -669px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_IcySnow {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -656px -500px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Peppermint {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -621px -669px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Purple {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -738px 0px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Rainbow {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -738px -69px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Red {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -738px -138px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_RoseQuartz {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -738px -207px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_RoyalPurple {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -738px -276px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Ruby {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -738px -345px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Shade {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -738px -414px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Shadow {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -738px -483px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Shimmer {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -738px -552px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Silver {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -738px -621px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Skeleton {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: 0px -738px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Spooky {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -69px -738px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_StarryNight {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -138px -738px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Sunshine {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -207px -738px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Thunderstorm {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -276px -738px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Watery {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -345px -738px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_White {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -414px -738px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
.Pet_HatchingPotion_Zombie {
|
||||
background-image: url('~@/assets/images/sprites/spritesmith-main-27.png');
|
||||
background-position: -483px -738px;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
}
|
||||
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 179 KiB |
|
Before Width: | Height: | Size: 476 KiB After Width: | Height: | Size: 473 KiB |
|
Before Width: | Height: | Size: 687 KiB After Width: | Height: | Size: 658 KiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 305 KiB After Width: | Height: | Size: 286 KiB |
|
Before Width: | Height: | Size: 350 KiB After Width: | Height: | Size: 353 KiB |
|
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 189 KiB |
|
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 156 KiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 151 KiB |
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 151 KiB |
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 143 KiB |
|
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 153 KiB |
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 146 KiB |
|
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 183 KiB |
|
Before Width: | Height: | Size: 161 KiB After Width: | Height: | Size: 165 KiB |
|
Before Width: | Height: | Size: 163 KiB After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 119 KiB |
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 138 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
@@ -41,6 +41,7 @@
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
|
||||
&:active, &:hover, &.active {
|
||||
background-color: rgba(#d5c8ff, 0.32);
|
||||
color: $purple-200;
|
||||
@@ -48,7 +49,7 @@
|
||||
|
||||
&.dropdown-inactive {
|
||||
cursor: default;
|
||||
|
||||
|
||||
&:active, &:hover, &.active {
|
||||
background-color: inherit;
|
||||
color: inherit;
|
||||
@@ -97,4 +98,4 @@
|
||||
.dropdown-menu.show {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ input, textarea, input.form-control, textarea.form-control {
|
||||
border-radius: 2px;
|
||||
font-size: 14px;
|
||||
line-height: 1.43;
|
||||
color: $gray-200;
|
||||
color: $gray-50;
|
||||
border: 1px solid $gray-400;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
@@ -32,7 +32,6 @@ input, textarea, input.form-control, textarea.form-control {
|
||||
|
||||
&:active:not(:disabled), &:focus:not(:disabled) {
|
||||
border-color: $purple-500;
|
||||
color: $gray-50;
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ h3 {
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
color: $gray-50;
|
||||
margin-bottom: 9px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
// possible values are: normal, fall, habitoween, thanksgiving, winter, nye, birthday, valentines, spring, summer
|
||||
// more to be added on future seasons
|
||||
|
||||
$npc_market_flavor: 'birthday';
|
||||
$npc_quests_flavor: 'birthday';
|
||||
$npc_seasonal_flavor: 'birthday';
|
||||
$npc_timetravelers_flavor: 'birthday';
|
||||
$npc_tavern_flavor: 'birthday';
|
||||
$npc_market_flavor: 'normal';
|
||||
$npc_quests_flavor: 'normal';
|
||||
$npc_seasonal_flavor: 'normal';
|
||||
$npc_timetravelers_flavor: 'normal';
|
||||
$npc_tavern_flavor: 'normal';
|
||||
|
||||
$restingToolbarHeight: 40px;
|
||||
$menuToolbarHeight: 56px;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="98" height="40" viewBox="0 0 98 40">
|
||||
<path fill="#000" fill-rule="nonzero" d="M17.744 5.137c-1.137 1.346-2.957 2.408-4.777 2.256-.228-1.82.663-3.753 1.706-4.948C15.81 1.062 17.801.075 19.413 0c.189 1.896-.55 3.754-1.669 5.137zm1.65 2.617c-2.636-.152-4.892 1.497-6.143 1.497-1.27 0-3.185-1.422-5.27-1.384-2.71.038-5.232 1.574-6.616 4.02C-1.48 16.776.625 24.018 3.375 28c1.345 1.972 2.957 4.133 5.08 4.057 2.01-.076 2.806-1.308 5.232-1.308 2.446 0 3.147 1.308 5.27 1.27 2.2-.038 3.583-1.972 4.93-3.943 1.535-2.237 2.16-4.417 2.198-4.531-.038-.038-4.246-1.65-4.284-6.502-.038-4.057 3.317-5.99 3.47-6.105-1.897-2.805-4.854-3.109-5.878-3.184zm15.222-5.498V31.81h4.588V21.706h6.35c5.801 0 9.877-3.98 9.877-9.744 0-5.763-4-9.706-9.725-9.706h-11.09zm4.588 3.867h5.289c3.98 0 6.256 2.123 6.256 5.858 0 3.735-2.275 5.877-6.275 5.877h-5.27V6.123zM63.81 32.038c2.882 0 5.555-1.46 6.768-3.773h.095v3.545h4.246V17.1c0-4.266-3.412-7.015-8.663-7.015-4.872 0-8.474 2.787-8.607 6.616h4.133c.341-1.82 2.028-3.014 4.341-3.014 2.806 0 4.38 1.308 4.38 3.716v1.63l-5.726.341c-5.327.323-8.208 2.503-8.208 6.294 0 3.83 2.976 6.37 7.241 6.37zm1.233-3.507c-2.446 0-4-1.176-4-2.976 0-1.858 1.497-2.939 4.36-3.11l5.1-.322v1.668c0 2.768-2.351 4.74-5.46 4.74zm15.545 11.317c4.474 0 6.578-1.706 8.417-6.881l8.057-22.597h-4.664l-5.403 17.46H86.9l-5.402-17.46H76.7l7.773 21.516-.417 1.308c-.702 2.218-1.839 3.071-3.867 3.071-.36 0-1.062-.038-1.346-.075v3.545c.265.075 1.402.113 1.744.113z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="#9A62FF" d="M20.571 3.429V0h-3.428v3.429H6.857V0H3.43v3.429A3.428 3.428 0 0 0 0 6.857v13.714A3.428 3.428 0 0 0 3.429 24H20.57A3.428 3.428 0 0 0 24 20.571V6.857a3.428 3.428 0 0 0-3.429-3.428z"/>
|
||||
<path fill="#D5C8FF" d="M3.429 20.571H20.57V10.286H3.43z"/>
|
||||
<path fill="#9A62FF" d="M3.429 13.286H20.57v-3H3.43z"/>
|
||||
<path fill="#BDA8FF" d="M3.429 13.286H20.57v-3H3.43z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 550 B |
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
|
||||
<g fill="none" fill-rule="evenodd" stroke="#8EEDF6" stroke-width="2">
|
||||
<path d="M1 11L11 1M11 11L1 1"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 215 B |