fix test lint

This commit is contained in:
Matteo Pagliazzi
2019-10-08 20:45:38 +02:00
parent e37f4467f8
commit 85fb5f33aa
367 changed files with 6635 additions and 6080 deletions

View File

@@ -1,7 +1,7 @@
/* eslint-disable camelcase */
import * as analyticsService from '../../../../website/server/libs/analyticsService';
import Amplitude from 'amplitude';
import { Visitor } from 'universal-analytics';
import * as analyticsService from '../../../../website/server/libs/analyticsService';
describe('analyticsService', () => {
beforeEach(() => {
@@ -16,7 +16,8 @@ describe('analyticsService', () => {
});
describe('#track', () => {
let eventType, data;
let eventType; let
data;
beforeEach(() => {
Visitor.prototype.event.yields();
@@ -35,12 +36,10 @@ describe('analyticsService', () => {
});
context('Amplitude', () => {
it('calls out to amplitude', () => {
return analyticsService.track(eventType, data)
.then(() => {
expect(Amplitude.prototype.track).to.be.calledOnce;
});
});
it('calls out to amplitude', () => analyticsService.track(eventType, data)
.then(() => {
expect(Amplitude.prototype.track).to.be.calledOnce;
}));
it('uses a dummy user id if none is provided', () => {
delete data.uuid;
@@ -55,7 +54,7 @@ describe('analyticsService', () => {
context('platform', () => {
it('logs web platform', () => {
data.headers = {'x-client': 'habitica-web'};
data.headers = { 'x-client': 'habitica-web' };
return analyticsService.track(eventType, data)
.then(() => {
@@ -66,7 +65,7 @@ describe('analyticsService', () => {
});
it('logs iOS platform', () => {
data.headers = {'x-client': 'habitica-ios'};
data.headers = { 'x-client': 'habitica-ios' };
return analyticsService.track(eventType, data)
.then(() => {
@@ -77,7 +76,7 @@ describe('analyticsService', () => {
});
it('logs Android platform', () => {
data.headers = {'x-client': 'habitica-android'};
data.headers = { 'x-client': 'habitica-android' };
return analyticsService.track(eventType, data)
.then(() => {
@@ -88,7 +87,7 @@ describe('analyticsService', () => {
});
it('logs 3rd Party platform', () => {
data.headers = {'x-client': 'some-third-party'};
data.headers = { 'x-client': 'some-third-party' };
return analyticsService.track(eventType, data)
.then(() => {
@@ -169,18 +168,16 @@ describe('analyticsService', () => {
});
});
it('sends details about event', () => {
return analyticsService.track(eventType, data)
.then(() => {
expect(Amplitude.prototype.track).to.be.calledWithMatch({
event_properties: {
category: 'behavior',
resting: true,
cronCount: 5,
},
});
it('sends details about event', () => analyticsService.track(eventType, data)
.then(() => {
expect(Amplitude.prototype.track).to.be.calledWithMatch({
event_properties: {
category: 'behavior',
resting: true,
cronCount: 5,
},
});
});
}));
it('sends english item name for gear if itemKey is provided', () => {
data.itemKey = 'headAccessory_special_foxEars';
@@ -267,16 +264,18 @@ describe('analyticsService', () => {
});
it('sends user data if provided', () => {
let stats = { class: 'wizard', exp: 5, gp: 23, hp: 10, lvl: 4, mp: 30 };
let user = {
const stats = {
class: 'wizard', exp: 5, gp: 23, hp: 10, lvl: 4, mp: 30,
};
const user = {
stats,
contributor: { level: 1 },
purchased: { plan: { planId: 'foo-plan' } },
flags: {tour: {intro: -2}},
habits: [{_id: 'habit'}],
dailys: [{_id: 'daily'}],
todos: [{_id: 'todo'}],
rewards: [{_id: 'reward'}],
flags: { tour: { intro: -2 } },
habits: [{ _id: 'habit' }],
dailys: [{ _id: 'daily' }],
todos: [{ _id: 'todo' }],
rewards: [{ _id: 'reward' }],
balance: 12,
loginIncentives: 1,
};
@@ -312,27 +311,24 @@ describe('analyticsService', () => {
});
context('GA', () => {
it('calls out to GA', () => {
return analyticsService.track(eventType, data)
.then(() => {
expect(Visitor.prototype.event).to.be.calledOnce;
});
});
it('calls out to GA', () => analyticsService.track(eventType, data)
.then(() => {
expect(Visitor.prototype.event).to.be.calledOnce;
}));
it('sends details about event', () => {
return analyticsService.track(eventType, data)
.then(() => {
expect(Visitor.prototype.event).to.be.calledWith({
ea: 'Cron',
ec: 'behavior',
});
it('sends details about event', () => analyticsService.track(eventType, data)
.then(() => {
expect(Visitor.prototype.event).to.be.calledWith({
ea: 'Cron',
ec: 'behavior',
});
});
}));
});
});
describe('#trackPurchase', () => {
let data, itemSpy;
let data; let
itemSpy;
beforeEach(() => {
Visitor.prototype.event.yields();
@@ -361,12 +357,10 @@ describe('analyticsService', () => {
});
context('Amplitude', () => {
it('calls out to amplitude', () => {
return analyticsService.trackPurchase(data)
.then(() => {
expect(Amplitude.prototype.track).to.be.calledOnce;
});
});
it('calls out to amplitude', () => analyticsService.trackPurchase(data)
.then(() => {
expect(Amplitude.prototype.track).to.be.calledOnce;
}));
it('uses a dummy user id if none is provided', () => {
delete data.uuid;
@@ -381,7 +375,7 @@ describe('analyticsService', () => {
context('platform', () => {
it('logs web platform', () => {
data.headers = {'x-client': 'habitica-web'};
data.headers = { 'x-client': 'habitica-web' };
return analyticsService.trackPurchase(data)
.then(() => {
@@ -392,7 +386,7 @@ describe('analyticsService', () => {
});
it('logs iOS platform', () => {
data.headers = {'x-client': 'habitica-ios'};
data.headers = { 'x-client': 'habitica-ios' };
return analyticsService.trackPurchase(data)
.then(() => {
@@ -403,7 +397,7 @@ describe('analyticsService', () => {
});
it('logs Android platform', () => {
data.headers = {'x-client': 'habitica-android'};
data.headers = { 'x-client': 'habitica-android' };
return analyticsService.trackPurchase(data)
.then(() => {
@@ -414,7 +408,7 @@ describe('analyticsService', () => {
});
it('logs 3rd Party platform', () => {
data.headers = {'x-client': 'some-third-party'};
data.headers = { 'x-client': 'some-third-party' };
return analyticsService.trackPurchase(data)
.then(() => {
@@ -495,33 +489,33 @@ describe('analyticsService', () => {
});
});
it('sends details about purchase', () => {
return analyticsService.trackPurchase(data)
.then(() => {
expect(Amplitude.prototype.track).to.be.calledWithMatch({
event_properties: {
gift: false,
itemPurchased: 'Gems',
paymentMethod: 'PayPal',
purchaseType: 'checkout',
quantity: 1,
sku: 'paypal-checkout',
},
});
it('sends details about purchase', () => analyticsService.trackPurchase(data)
.then(() => {
expect(Amplitude.prototype.track).to.be.calledWithMatch({
event_properties: {
gift: false,
itemPurchased: 'Gems',
paymentMethod: 'PayPal',
purchaseType: 'checkout',
quantity: 1,
sku: 'paypal-checkout',
},
});
});
}));
it('sends user data if provided', () => {
let stats = { class: 'wizard', exp: 5, gp: 23, hp: 10, lvl: 4, mp: 30 };
let user = {
const stats = {
class: 'wizard', exp: 5, gp: 23, hp: 10, lvl: 4, mp: 30,
};
const user = {
stats,
contributor: { level: 1 },
purchased: { plan: { planId: 'foo-plan' } },
flags: {tour: {intro: -2}},
habits: [{_id: 'habit'}],
dailys: [{_id: 'daily'}],
todos: [{_id: 'todo'}],
rewards: [{_id: 'reward'}],
flags: { tour: { intro: -2 } },
habits: [{ _id: 'habit' }],
dailys: [{ _id: 'daily' }],
todos: [{ _id: 'todo' }],
rewards: [{ _id: 'reward' }],
};
data.user = user;
@@ -552,27 +546,23 @@ describe('analyticsService', () => {
});
context('GA', () => {
it('calls out to GA', () => {
return analyticsService.trackPurchase(data)
.then(() => {
expect(Visitor.prototype.event).to.be.calledOnce;
expect(Visitor.prototype.transaction).to.be.calledOnce;
});
});
it('calls out to GA', () => analyticsService.trackPurchase(data)
.then(() => {
expect(Visitor.prototype.event).to.be.calledOnce;
expect(Visitor.prototype.transaction).to.be.calledOnce;
}));
it('sends details about purchase', () => {
return analyticsService.trackPurchase(data)
.then(() => {
expect(Visitor.prototype.event).to.be.calledWith({
ea: 'checkout',
ec: 'commerce',
el: 'PayPal',
ev: 8,
});
expect(Visitor.prototype.transaction).to.be.calledWith('user-id', 8);
expect(itemSpy).to.be.calledWith(8, 1, 'paypal-checkout', 'Gems', 'checkout');
it('sends details about purchase', () => analyticsService.trackPurchase(data)
.then(() => {
expect(Visitor.prototype.event).to.be.calledWith({
ea: 'checkout',
ec: 'commerce',
el: 'PayPal',
ev: 8,
});
});
expect(Visitor.prototype.transaction).to.be.calledWith('user-id', 8);
expect(itemSpy).to.be.calledWith(8, 1, 'paypal-checkout', 'Gems', 'checkout');
}));
});
});

View File

@@ -11,7 +11,7 @@ describe('API Messages', () => {
});
it('clones the passed variables', () => {
let vars = {a: 1};
const vars = { a: 1 };
sandbox.stub(_, 'clone').returns({});
apiError('guildsOnlyPaginate', vars);
expect(_.clone).to.have.been.calledOnce;
@@ -19,8 +19,8 @@ describe('API Messages', () => {
});
it('pass the message through _.template', () => {
let vars = {a: 1};
let stub = sinon.stub().returns('string');
const vars = { a: 1 };
const stub = sinon.stub().returns('string');
sandbox.stub(_, 'template').returns(stub);
apiError('guildsOnlyPaginate', vars);
expect(_.template).to.have.been.calledOnce;

View File

@@ -1,5 +1,5 @@
import baseModel from '../../../../website/server/libs/baseModel';
import mongoose from 'mongoose';
import baseModel from '../../../../website/server/libs/baseModel';
describe('Base model plugin', () => {
let schema;
@@ -25,7 +25,7 @@ describe('Base model plugin', () => {
});
it('can add timestamps fields', () => {
schema.plugin(baseModel, {timestamps: true});
schema.plugin(baseModel, { timestamps: true });
expect(schema.add).to.be.calledTwice;
});
@@ -36,7 +36,7 @@ describe('Base model plugin', () => {
});
expect(schema.statics.sanitize).to.exist;
let sanitized = schema.statics.sanitize({ok: true, noUpdateForMe: true});
const sanitized = schema.statics.sanitize({ ok: true, noUpdateForMe: true });
expect(sanitized).to.have.property('ok');
expect(sanitized).not.to.have.property('noUpdateForMe');
@@ -49,7 +49,7 @@ describe('Base model plugin', () => {
});
expect(schema.statics.sanitize).to.exist;
let sanitized = schema.statics.sanitize({ok: true, noUpdateForMe: true, usuallySettable: true}, ['usuallySettable']);
const sanitized = schema.statics.sanitize({ ok: true, noUpdateForMe: true, usuallySettable: true }, ['usuallySettable']);
expect(sanitized).to.have.property('ok');
expect(sanitized).not.to.have.property('noUpdateForMe');
@@ -63,31 +63,31 @@ describe('Base model plugin', () => {
});
expect(schema.options.toJSON.transform).to.exist;
let objToTransform = {ok: true, amPrivate: true};
let privatized = schema.options.toJSON.transform({}, objToTransform);
const objToTransform = { ok: true, amPrivate: true };
const privatized = schema.options.toJSON.transform({}, objToTransform);
expect(privatized).to.have.property('ok');
expect(privatized).not.to.have.property('amPrivate');
});
it('accepts a further transform function for toJSON', () => {
let options = {
const options = {
private: ['amPrivate'],
toJSONTransform: sandbox.stub().returns(true),
};
schema.plugin(baseModel, options);
let objToTransform = {ok: true, amPrivate: true};
let doc = {doc: true};
let privatized = schema.options.toJSON.transform(doc, objToTransform);
const objToTransform = { ok: true, amPrivate: true };
const doc = { doc: true };
const privatized = schema.options.toJSON.transform(doc, objToTransform);
expect(privatized).to.equals(true);
expect(options.toJSONTransform).to.be.calledWith(objToTransform, doc);
});
it('accepts a transform function for sanitize', () => {
let options = {
const options = {
private: ['amPrivate'],
sanitizeTransform: sandbox.stub().returns(true),
};
@@ -95,8 +95,8 @@ describe('Base model plugin', () => {
schema.plugin(baseModel, options);
expect(schema.options.toJSON.transform).to.exist;
let objToSanitize = {ok: true, noUpdateForMe: true};
let sanitized = schema.statics.sanitize(objToSanitize);
const objToSanitize = { ok: true, noUpdateForMe: true };
const sanitized = schema.statics.sanitize(objToSanitize);
expect(sanitized).to.equals(true);
expect(options.sanitizeTransform).to.be.calledWith(objToSanitize);

View File

@@ -6,7 +6,7 @@ import {
describe('Collection Manipulators', () => {
describe('removeFromArray', () => {
it('removes element from array', () => {
let array = ['a', 'b', 'c', 'd'];
const array = ['a', 'b', 'c', 'd'];
removeFromArray(array, 'c');
@@ -14,7 +14,7 @@ describe('Collection Manipulators', () => {
});
it('removes object from array', () => {
let array = [
const array = [
{ id: 'a', foo: 'bar' },
{ id: 'b', foo: 'bar' },
{ id: 'c', foo: 'bar' },
@@ -28,7 +28,7 @@ describe('Collection Manipulators', () => {
});
it('does not change array if value is not found', () => {
let array = ['a', 'b', 'c', 'd'];
const array = ['a', 'b', 'c', 'd'];
removeFromArray(array, 'z');
@@ -40,15 +40,15 @@ describe('Collection Manipulators', () => {
});
it('returns the removed element', () => {
let array = ['a', 'b', 'c'];
const array = ['a', 'b', 'c'];
let result = removeFromArray(array, 'b');
const result = removeFromArray(array, 'b');
expect(result).to.eql('b');
});
it('returns the removed object element', () => {
let array = [
const array = [
{ id: 'a', foo: 'bar' },
{ id: 'b', foo: 'bar' },
{ id: 'c', foo: 'bar' },
@@ -56,31 +56,31 @@ describe('Collection Manipulators', () => {
{ id: 'e', foo: 'bar' },
];
let result = removeFromArray(array, { id: 'c' });
const result = removeFromArray(array, { id: 'c' });
expect(result).to.eql({ id: 'c', foo: 'bar' });
});
it('returns false if item is not found', () => {
let array = ['a', 'b', 'c'];
const array = ['a', 'b', 'c'];
let result = removeFromArray(array, 'z');
const result = removeFromArray(array, 'z');
expect(result).to.eql(false);
});
it('persists removal of element when mongoose document is saved', async () => {
let schema = new mongoose.Schema({
const schema = new mongoose.Schema({
array: Array,
});
let Model = mongoose.model('ModelToTestRemoveFromArray', schema);
let model = await new Model({
const Model = mongoose.model('ModelToTestRemoveFromArray', schema);
const model = await new Model({
array: ['a', 'b', 'c'],
}).save(); // Initial creation
removeFromArray(model.array, 'b');
let savedModel = await model.save();
const savedModel = await model.save();
expect(savedModel.array).to.not.include('b');
});

File diff suppressed because it is too large Load Diff

View File

@@ -31,20 +31,20 @@ function getUser () {
}
describe('emails', () => {
let pathToEmailLib = '../../../../website/server/libs/email';
const pathToEmailLib = '../../../../website/server/libs/email';
describe('getUserInfo', () => {
it('returns an empty object if no field request', () => {
let attachEmail = requireAgain(pathToEmailLib);
let getUserInfo = attachEmail.getUserInfo;
const attachEmail = requireAgain(pathToEmailLib);
const { getUserInfo } = attachEmail;
expect(getUserInfo({}, [])).to.be.empty;
});
it('returns correct user data', () => {
let attachEmail = requireAgain(pathToEmailLib);
let getUserInfo = attachEmail.getUserInfo;
let user = getUser();
let data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
const attachEmail = requireAgain(pathToEmailLib);
const { getUserInfo } = attachEmail;
const user = getUser();
const data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
expect(data).to.have.property('name', user.auth.local.username);
expect(data).to.have.property('email', user.auth.local.email);
@@ -53,13 +53,13 @@ describe('emails', () => {
});
it('returns correct user data [facebook users]', () => {
let attachEmail = requireAgain(pathToEmailLib);
let getUserInfo = attachEmail.getUserInfo;
let user = getUser();
const attachEmail = requireAgain(pathToEmailLib);
const { getUserInfo } = attachEmail;
const user = getUser();
delete user.profile.name;
delete user.auth.local.email;
let data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
const data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
expect(data).to.have.property('name', user.auth.local.username);
expect(data).to.have.property('email', user.auth.facebook.emails[0].value);
@@ -68,13 +68,13 @@ describe('emails', () => {
});
it('has fallbacks for missing data', () => {
let attachEmail = requireAgain(pathToEmailLib);
let getUserInfo = attachEmail.getUserInfo;
let user = getUser();
const attachEmail = requireAgain(pathToEmailLib);
const { getUserInfo } = attachEmail;
const user = getUser();
delete user.auth.local.email;
delete user.auth.facebook;
let data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
const data = getUserInfo(user, ['name', 'email', '_id', 'canSend']);
expect(data).to.have.property('name', user.auth.local.username);
expect(data).not.to.have.property('email');
@@ -85,18 +85,18 @@ 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('/groups/tavern');
const { getGroupUrl } = require(pathToEmailLib); // eslint-disable-line import/no-dynamic-require, max-len
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('/groups/guild/random _id');
const { getGroupUrl } = require(pathToEmailLib); // eslint-disable-line import/no-dynamic-require, max-len
expect(getGroupUrl({ _id: 'random _id', type: 'guild' })).to.eql('/groups/guild/random _id');
});
it('returns correct url if group is a party', () => {
let getGroupUrl = require(pathToEmailLib).getGroupUrl;
expect(getGroupUrl({_id: 'random _id', type: 'party'})).to.eql('party');
const { getGroupUrl } = require(pathToEmailLib); // eslint-disable-line import/no-dynamic-require, max-len
expect(getGroupUrl({ _id: 'random _id', type: 'party' })).to.eql('party');
});
});
@@ -111,10 +111,10 @@ describe('emails', () => {
it('can send a txn email to one recipient', () => {
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(true);
let attachEmail = requireAgain(pathToEmailLib);
let sendTxnEmail = attachEmail.sendTxn;
let emailType = 'an email type';
let mailingInfo = {
const attachEmail = requireAgain(pathToEmailLib);
const sendTxnEmail = attachEmail.sendTxn;
const emailType = 'an email type';
const mailingInfo = {
name: 'my name',
email: 'my@email',
};
@@ -125,9 +125,7 @@ describe('emails', () => {
body: {
data: {
emailType: sinon.match.same(emailType),
to: sinon.match((value) => {
return Array.isArray(value) && value[0].name === mailingInfo.name;
}, 'matches mailing info array'),
to: sinon.match(value => Array.isArray(value) && value[0].name === mailingInfo.name, 'matches mailing info array'),
},
},
}));
@@ -135,10 +133,10 @@ describe('emails', () => {
it('does not send email if address is missing', () => {
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(true);
let attachEmail = requireAgain(pathToEmailLib);
let sendTxnEmail = attachEmail.sendTxn;
let emailType = 'an email type';
let mailingInfo = {
const attachEmail = requireAgain(pathToEmailLib);
const sendTxnEmail = attachEmail.sendTxn;
const emailType = 'an email type';
const mailingInfo = {
name: 'my name',
// email: 'my@email',
};
@@ -149,10 +147,10 @@ describe('emails', () => {
it('uses getUserInfo in case of user data', () => {
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(true);
let attachEmail = requireAgain(pathToEmailLib);
let sendTxnEmail = attachEmail.sendTxn;
let emailType = 'an email type';
let mailingInfo = getUser();
const attachEmail = requireAgain(pathToEmailLib);
const sendTxnEmail = attachEmail.sendTxn;
const emailType = 'an email type';
const mailingInfo = getUser();
sendTxnEmail(mailingInfo, emailType);
expect(got.post).to.be.calledWith('undefined/job', sinon.match({
@@ -168,28 +166,24 @@ describe('emails', () => {
it('sends email with some default variables', () => {
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(true);
let attachEmail = requireAgain(pathToEmailLib);
let sendTxnEmail = attachEmail.sendTxn;
let emailType = 'an email type';
let mailingInfo = {
const attachEmail = requireAgain(pathToEmailLib);
const sendTxnEmail = attachEmail.sendTxn;
const emailType = 'an email type';
const mailingInfo = {
name: 'my name',
email: 'my@email',
};
let variables = [1, 2, 3];
const variables = [1, 2, 3];
sendTxnEmail(mailingInfo, emailType, variables);
expect(got.post).to.be.calledWith('undefined/job', sinon.match({
json: true,
body: {
data: {
variables: sinon.match((value) => {
return value[0].name === 'BASE_URL';
}, 'matches variables'),
personalVariables: sinon.match((value) => {
return value[0].rcpt === mailingInfo.email &&
value[0].vars[0].name === 'RECIPIENT_NAME' &&
value[0].vars[1].name === 'RECIPIENT_UNSUB_URL';
}, 'matches personal variables'),
variables: sinon.match(value => value[0].name === 'BASE_URL', 'matches variables'),
personalVariables: sinon.match(value => value[0].rcpt === mailingInfo.email
&& value[0].vars[0].name === 'RECIPIENT_NAME'
&& value[0].vars[1].name === 'RECIPIENT_UNSUB_URL', 'matches personal variables'),
},
},
}));

View File

@@ -5,9 +5,9 @@ import {
describe('encryption', () => {
it('can encrypt and decrypt', () => {
let data = 'some secret text';
let encrypted = encrypt(data);
let decrypted = decrypt(encrypted);
const data = 'some secret text';
const encrypted = encrypt(data);
const decrypted = decrypt(encrypted);
expect(encrypted).not.to.equal(data);
expect(data).to.equal(decrypted);

View File

@@ -12,7 +12,7 @@ import i18n from '../../../../website/common/script/i18n';
describe('Custom Errors', () => {
describe('CustomError', () => {
it('is an instance of Error', () => {
let customError = new CustomError();
const customError = new CustomError();
expect(customError).to.be.an.instanceOf(Error);
});
@@ -20,25 +20,25 @@ describe('Custom Errors', () => {
describe('NotAuthorized', () => {
it('is an instance of CustomError', () => {
let notAuthorizedError = new NotAuthorized();
const notAuthorizedError = new NotAuthorized();
expect(notAuthorizedError).to.be.an.instanceOf(CustomError);
});
it('it returns an http code of 401', () => {
let notAuthorizedError = new NotAuthorized();
const notAuthorizedError = new NotAuthorized();
expect(notAuthorizedError.httpCode).to.eql(401);
});
it('returns a default message', () => {
let notAuthorizedError = new NotAuthorized();
const notAuthorizedError = new NotAuthorized();
expect(notAuthorizedError.message).to.eql('Not authorized.');
});
it('allows a custom message', () => {
let notAuthorizedError = new NotAuthorized('Custom Error Message');
const notAuthorizedError = new NotAuthorized('Custom Error Message');
expect(notAuthorizedError.message).to.eql('Custom Error Message');
});
@@ -46,25 +46,25 @@ describe('Custom Errors', () => {
describe('NotFound', () => {
it('is an instance of CustomError', () => {
let notAuthorizedError = new NotFound();
const notAuthorizedError = new NotFound();
expect(notAuthorizedError).to.be.an.instanceOf(CustomError);
});
it('it returns an http code of 404', () => {
let notAuthorizedError = new NotFound();
const notAuthorizedError = new NotFound();
expect(notAuthorizedError.httpCode).to.eql(404);
});
it('returns a default message', () => {
let notAuthorizedError = new NotFound();
const notAuthorizedError = new NotFound();
expect(notAuthorizedError.message).to.eql('Not found.');
});
it('allows a custom message', () => {
let notAuthorizedError = new NotFound('Custom Error Message');
const notAuthorizedError = new NotFound('Custom Error Message');
expect(notAuthorizedError.message).to.eql('Custom Error Message');
});
@@ -89,25 +89,25 @@ describe('Custom Errors', () => {
describe('BadRequest', () => {
it('is an instance of CustomError', () => {
let badRequestError = new BadRequest();
const badRequestError = new BadRequest();
expect(badRequestError).to.be.an.instanceOf(CustomError);
});
it('it returns an http code of 401', () => {
let badRequestError = new BadRequest();
const badRequestError = new BadRequest();
expect(badRequestError.httpCode).to.eql(400);
});
it('returns a default message', () => {
let badRequestError = new BadRequest();
const badRequestError = new BadRequest();
expect(badRequestError.message).to.eql('Bad request.');
});
it('allows a custom message', () => {
let badRequestError = new BadRequest('Custom Error Message');
const badRequestError = new BadRequest('Custom Error Message');
expect(badRequestError.message).to.eql('Custom Error Message');
});
@@ -115,25 +115,25 @@ describe('Custom Errors', () => {
describe('InternalServerError', () => {
it('is an instance of CustomError', () => {
let internalServerError = new InternalServerError();
const internalServerError = new InternalServerError();
expect(internalServerError).to.be.an.instanceOf(CustomError);
});
it('it returns an http code of 500', () => {
let internalServerError = new InternalServerError();
const internalServerError = new InternalServerError();
expect(internalServerError.httpCode).to.eql(500);
});
it('returns a default message', () => {
let internalServerError = new InternalServerError();
const internalServerError = new InternalServerError();
expect(internalServerError.message).to.eql('An unexpected error occurred.');
});
it('allows a custom message', () => {
let internalServerError = new InternalServerError('Custom Error Message');
const internalServerError = new InternalServerError('Custom Error Message');
expect(internalServerError.message).to.eql('Custom Error Message');
});

View File

@@ -5,11 +5,11 @@ import {
} from '../../../../website/server/libs/i18n';
describe('i18n', () => {
let listOfLocales = approvedLanguages.sort();
const listOfLocales = approvedLanguages.sort();
describe('translations', () => {
it('includes a translation object for each locale', () => {
listOfLocales.forEach((locale) => {
listOfLocales.forEach(locale => {
expect(translations[locale]).to.be.an('object');
});
});

View File

@@ -2,7 +2,7 @@ import winston from 'winston';
import logger from '../../../../website/server/libs/logger';
import {
NotFound,
} from '../../../../website/server/libs//errors';
} from '../../../../website/server/libs/errors';
describe('logger', () => {
let logSpy;
@@ -34,7 +34,7 @@ describe('logger', () => {
context('error object', () => {
it('logs the stack and the err data', () => {
let errInstance = new Error('An error.');
const errInstance = new Error('An error.');
logger.error(errInstance, {
data: 1,
}, 2, 3);
@@ -45,13 +45,13 @@ describe('logger', () => {
errInstance.stack,
{ data: 1, fullError: errInstance },
2,
3
3,
);
});
it('logs the stack and the err data with it\'s own fullError property', () => {
let errInstance = new Error('An error.');
let anotherError = new Error('another error');
const errInstance = new Error('An error.');
const anotherError = new Error('another error');
logger.error(errInstance, {
data: 1,
@@ -64,12 +64,12 @@ describe('logger', () => {
errInstance.stack,
{ data: 1, fullError: anotherError },
2,
3
3,
);
});
it('logs the error when errorData is null', () => {
let errInstance = new Error('An error.');
const errInstance = new Error('An error.');
logger.error(errInstance, null, 2, 3);
@@ -79,12 +79,12 @@ describe('logger', () => {
errInstance.stack,
null,
2,
3
3,
);
});
it('logs the error when errorData is not an object', () => {
let errInstance = new Error('An error.');
const errInstance = new Error('An error.');
logger.error(errInstance, true, 2, 3);
@@ -94,12 +94,12 @@ describe('logger', () => {
errInstance.stack,
true,
2,
3
3,
);
});
it('logs the error when errorData does not include isHandledError property', () => {
let errInstance = new Error('An error.');
const errInstance = new Error('An error.');
logger.error(errInstance, { httpCode: 400 }, 2, 3);
@@ -109,12 +109,12 @@ describe('logger', () => {
errInstance.stack,
{ httpCode: 400, fullError: errInstance },
2,
3
3,
);
});
it('logs the error when errorData includes isHandledError property but is a 500 error', () => {
let errInstance = new Error('An error.');
const errInstance = new Error('An error.');
logger.error(errInstance, {
isHandledError: true,
@@ -127,12 +127,12 @@ describe('logger', () => {
errInstance.stack,
{ httpCode: 502, isHandledError: true, fullError: errInstance },
2,
3
3,
);
});
it('logs a warning when errorData includes isHandledError property and is not a 500 error', () => {
let errInstance = new Error('An error.');
const errInstance = new Error('An error.');
logger.error(errInstance, {
isHandledError: true,
@@ -145,12 +145,12 @@ describe('logger', () => {
errInstance.stack,
{ httpCode: 403, isHandledError: true, fullError: errInstance },
2,
3
3,
);
});
it('logs additional data from a CustomError', () => {
let errInstance = new NotFound('An error.');
const errInstance = new NotFound('An error.');
errInstance.customField = 'Some interesting data';
@@ -166,7 +166,7 @@ describe('logger', () => {
},
},
2,
3
3,
);
});
});

View File

@@ -1,9 +1,9 @@
/* eslint-disable camelcase */
import moment from 'moment';
import {
encrypt,
} from '../../../../website/server/libs/encryption';
import moment from 'moment';
import {
generateUser,
} from '../../../helpers/api-integration/v3';
@@ -20,11 +20,11 @@ import {
describe('Password Utilities', () => {
describe('compare', () => {
it('can compare a correct password hashed with SHA1', async () => {
let textPassword = 'mySecretPassword';
let salt = sha1MakeSalt();
let hashedPassword = sha1EncryptPassword(textPassword, salt);
const textPassword = 'mySecretPassword';
const salt = sha1MakeSalt();
const hashedPassword = sha1EncryptPassword(textPassword, salt);
let user = {
const user = {
auth: {
local: {
hashed_password: hashedPassword,
@@ -34,16 +34,16 @@ describe('Password Utilities', () => {
},
};
let isValidPassword = await compare(user, textPassword);
const isValidPassword = await compare(user, textPassword);
expect(isValidPassword).to.eql(true);
});
it('can compare an invalid password hashed with SHA1', async () => {
let textPassword = 'mySecretPassword';
let salt = sha1MakeSalt();
let hashedPassword = sha1EncryptPassword(textPassword, salt);
const textPassword = 'mySecretPassword';
const salt = sha1MakeSalt();
const hashedPassword = sha1EncryptPassword(textPassword, salt);
let user = {
const user = {
auth: {
local: {
hashed_password: hashedPassword,
@@ -53,15 +53,15 @@ describe('Password Utilities', () => {
},
};
let isValidPassword = await compare(user, 'wrongPassword');
const isValidPassword = await compare(user, 'wrongPassword');
expect(isValidPassword).to.eql(false);
});
it('can compare a correct password hashed with bcrypt', async () => {
let textPassword = 'mySecretPassword';
let hashedPassword = await bcryptHash(textPassword);
const textPassword = 'mySecretPassword';
const hashedPassword = await bcryptHash(textPassword);
let user = {
const user = {
auth: {
local: {
hashed_password: hashedPassword,
@@ -70,15 +70,15 @@ describe('Password Utilities', () => {
},
};
let isValidPassword = await compare(user, textPassword);
const isValidPassword = await compare(user, textPassword);
expect(isValidPassword).to.eql(true);
});
it('can compare an invalid password hashed with bcrypt', async () => {
let textPassword = 'mySecretPassword';
let hashedPassword = await bcryptHash(textPassword);
const textPassword = 'mySecretPassword';
const hashedPassword = await bcryptHash(textPassword);
let user = {
const user = {
auth: {
local: {
hashed_password: hashedPassword,
@@ -87,7 +87,7 @@ describe('Password Utilities', () => {
},
};
let isValidPassword = await compare(user, 'wrongPassword');
const isValidPassword = await compare(user, 'wrongPassword');
expect(isValidPassword).to.eql(false);
});
@@ -101,18 +101,18 @@ describe('Password Utilities', () => {
it('throws an error if passwordToCheck is missing', async () => {
try {
await compare({a: true});
await compare({ a: true });
} catch (e) {
expect(e.toString()).to.equal('Error: user and passwordToCheck are required parameters.');
}
});
it('defaults to SHA1 encryption if salt is provided', async () => {
let textPassword = 'mySecretPassword';
let salt = sha1MakeSalt();
let hashedPassword = sha1EncryptPassword(textPassword, salt);
const textPassword = 'mySecretPassword';
const salt = sha1MakeSalt();
const hashedPassword = sha1EncryptPassword(textPassword, salt);
let user = {
const user = {
auth: {
local: {
hashed_password: hashedPassword,
@@ -122,7 +122,7 @@ describe('Password Utilities', () => {
},
};
let isValidPassword = await compare(user, textPassword);
const isValidPassword = await compare(user, textPassword);
expect(isValidPassword).to.eql(true);
});
@@ -141,29 +141,29 @@ describe('Password Utilities', () => {
});
it('returns true if comparing the same password', async () => {
let textPassword = 'mySecretPassword';
let hashedPassword = await bcryptHash(textPassword);
const textPassword = 'mySecretPassword';
const hashedPassword = await bcryptHash(textPassword);
let isValidPassword = await bcryptCompare(textPassword, hashedPassword);
const isValidPassword = await bcryptCompare(textPassword, hashedPassword);
expect(isValidPassword).to.eql(true);
});
it('returns true if comparing a different password', async () => {
let textPassword = 'mySecretPassword';
let hashedPassword = await bcryptHash(textPassword);
const textPassword = 'mySecretPassword';
const hashedPassword = await bcryptHash(textPassword);
let isValidPassword = await bcryptCompare('anotherPassword', hashedPassword);
const isValidPassword = await bcryptCompare('anotherPassword', hashedPassword);
expect(isValidPassword).to.eql(false);
});
});
describe('convertToBcrypt', () => {
it('converts an user password hashed with sha1 to bcrypt', async () => {
let textPassword = 'mySecretPassword';
let salt = sha1MakeSalt();
let hashedPassword = sha1EncryptPassword(textPassword, salt);
const textPassword = 'mySecretPassword';
const salt = sha1MakeSalt();
const hashedPassword = sha1EncryptPassword(textPassword, salt);
let user = {
const user = {
auth: {
local: {
hashed_password: hashedPassword,
@@ -178,7 +178,7 @@ describe('Password Utilities', () => {
expect(user.auth.local.passwordHashMethod).to.equal('bcrypt');
expect(user.auth.local.hashed_password).to.be.a.string;
let isValidPassword = await compare(user, textPassword);
const isValidPassword = await compare(user, textPassword);
expect(isValidPassword).to.eql(true);
});
@@ -192,7 +192,7 @@ describe('Password Utilities', () => {
it('throws an error if plainTextPassword is missing', async () => {
try {
await convertToBcrypt({a: true});
await convertToBcrypt({ a: true });
} catch (e) {
expect(e.toString()).to.equal('Error: user and plainTextPassword are required parameters.');
}
@@ -201,18 +201,18 @@ describe('Password Utilities', () => {
describe('validatePasswordResetCodeAndFindUser', () => {
it('returns false if the code is missing', async () => {
let res = await validatePasswordResetCodeAndFindUser();
const res = await validatePasswordResetCodeAndFindUser();
expect(res).to.equal(false);
});
it('returns false if the code is invalid json', async () => {
let res = await validatePasswordResetCodeAndFindUser('invalid json');
const res = await validatePasswordResetCodeAndFindUser('invalid json');
expect(res).to.equal(false);
});
it('returns false if the code cannot be decrypted', async () => {
let user = await generateUser();
let res = await validatePasswordResetCodeAndFindUser(JSON.stringify({ // not encrypted
const user = await generateUser();
const res = await validatePasswordResetCodeAndFindUser(JSON.stringify({ // not encrypted
userId: user._id,
expiresAt: new Date(),
}));
@@ -220,71 +220,71 @@ describe('Password Utilities', () => {
});
it('returns false if the code is expired', async () => {
let user = await generateUser();
const user = await generateUser();
let code = encrypt(JSON.stringify({
const code = encrypt(JSON.stringify({
userId: user._id,
expiresAt: moment().subtract({minutes: 1}),
expiresAt: moment().subtract({ minutes: 1 }),
}));
await user.update({
'auth.local.passwordResetCode': code,
});
let res = await validatePasswordResetCodeAndFindUser(code);
const res = await validatePasswordResetCodeAndFindUser(code);
expect(res).to.equal(false);
});
it('returns false if the user does not exist', async () => {
let res = await validatePasswordResetCodeAndFindUser(encrypt(JSON.stringify({
const res = await validatePasswordResetCodeAndFindUser(encrypt(JSON.stringify({
userId: Date.now().toString(),
expiresAt: moment().add({days: 1}),
expiresAt: moment().add({ days: 1 }),
})));
expect(res).to.equal(false);
});
it('returns false if the user has no local auth', async () => {
let user = await generateUser({
const user = await generateUser({
auth: {
facebook: {},
},
});
let res = await validatePasswordResetCodeAndFindUser(encrypt(JSON.stringify({
const res = await validatePasswordResetCodeAndFindUser(encrypt(JSON.stringify({
userId: user._id,
expiresAt: moment().add({days: 1}),
expiresAt: moment().add({ days: 1 }),
})));
expect(res).to.equal(false);
});
it('returns false if the code doesn\'t match the one saved at user.auth.passwordResetCode', async () => {
let user = await generateUser();
const user = await generateUser();
let code = encrypt(JSON.stringify({
const code = encrypt(JSON.stringify({
userId: user._id,
expiresAt: moment().add({days: 1}),
expiresAt: moment().add({ days: 1 }),
}));
await user.update({
'auth.local.passwordResetCode': 'invalid',
});
let res = await validatePasswordResetCodeAndFindUser(code);
const res = await validatePasswordResetCodeAndFindUser(code);
expect(res).to.equal(false);
});
it('returns the user if the password reset code is valid', async () => {
let user = await generateUser();
const user = await generateUser();
let code = encrypt(JSON.stringify({
const code = encrypt(JSON.stringify({
userId: user._id,
expiresAt: moment().add({days: 1}),
expiresAt: moment().add({ days: 1 }),
}));
await user.update({
'auth.local.passwordResetCode': code,
});
let res = await validatePasswordResetCodeAndFindUser(code);
const res = await validatePasswordResetCodeAndFindUser(code);
expect(res).not.to.equal(false);
expect(res._id).to.equal(user._id);
});
@@ -293,8 +293,8 @@ describe('Password Utilities', () => {
describe('bcrypt', () => {
describe('Hash', () => {
it('returns a hashed string', async () => {
let textPassword = 'mySecretPassword';
let hashedPassword = await bcryptHash(textPassword);
const textPassword = 'mySecretPassword';
const hashedPassword = await bcryptHash(textPassword);
expect(hashedPassword).to.be.a.string;
});
@@ -302,18 +302,18 @@ describe('Password Utilities', () => {
describe('Compare', () => {
it('returns true if comparing the same password', async () => {
let textPassword = 'mySecretPassword';
let hashedPassword = await bcryptHash(textPassword);
const textPassword = 'mySecretPassword';
const hashedPassword = await bcryptHash(textPassword);
let isValidPassword = await bcryptCompare(textPassword, hashedPassword);
const isValidPassword = await bcryptCompare(textPassword, hashedPassword);
expect(isValidPassword).to.eql(true);
});
it('returns true if comparing a different password', async () => {
let textPassword = 'mySecretPassword';
let hashedPassword = await bcryptHash(textPassword);
const textPassword = 'mySecretPassword';
const hashedPassword = await bcryptHash(textPassword);
let isValidPassword = await bcryptCompare('anotherPassword', hashedPassword);
const isValidPassword = await bcryptCompare('anotherPassword', hashedPassword);
expect(isValidPassword).to.eql(false);
});
});
@@ -322,19 +322,19 @@ describe('Password Utilities', () => {
describe('SHA1', () => {
describe('Encrypt', () => {
it('always encrypt the same password to the same value when using the same salt', () => {
let textPassword = 'mySecretPassword';
let salt = sha1MakeSalt();
let encryptedPassword = sha1EncryptPassword(textPassword, salt);
const textPassword = 'mySecretPassword';
const salt = sha1MakeSalt();
const encryptedPassword = sha1EncryptPassword(textPassword, salt);
expect(sha1EncryptPassword(textPassword, salt)).to.eql(encryptedPassword);
});
it('never encrypt the same password to the same value when using a different salt', () => {
let textPassword = 'mySecretPassword';
let aSalt = sha1MakeSalt();
let anotherSalt = sha1MakeSalt();
let anEncryptedPassword = sha1EncryptPassword(textPassword, aSalt);
let anotherEncryptedPassword = sha1EncryptPassword(textPassword, anotherSalt);
const textPassword = 'mySecretPassword';
const aSalt = sha1MakeSalt();
const anotherSalt = sha1MakeSalt();
const anEncryptedPassword = sha1EncryptPassword(textPassword, aSalt);
const anotherEncryptedPassword = sha1EncryptPassword(textPassword, anotherSalt);
expect(anEncryptedPassword).not.to.eql(anotherEncryptedPassword);
});
@@ -342,14 +342,14 @@ describe('Password Utilities', () => {
describe('Make Salt', () => {
it('creates a salt with length 10 by default', () => {
let salt = sha1MakeSalt();
const salt = sha1MakeSalt();
expect(salt.length).to.eql(10);
});
it('can create a salt of any length', () => {
let length = 24;
let salt = sha1MakeSalt(length);
const length = 24;
const salt = sha1MakeSalt(length);
expect(salt.length).to.eql(length);
});

View File

@@ -2,19 +2,20 @@ import moment from 'moment';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper.js';
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import amzLib from '../../../../../../website/server/libs/payments/amazon';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
import { createNonLeaderGroupMember } from '../paymentHelpers';
const i18n = common.i18n;
const { i18n } = common;
describe('Amazon Payments - Cancel Subscription', () => {
const subKey = 'basic_3mo';
let user, group, headers, billingAgreementId, subscriptionBlock, subscriptionLength;
let user; let group; let headers; let billingAgreementId; let subscriptionBlock; let
subscriptionLength;
let getBillingAgreementDetailsSpy;
let paymentCancelSubscriptionSpy;
@@ -50,7 +51,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
getBillingAgreementDetailsSpy = sinon.stub(amzLib, 'getBillingAgreementDetails')
.resolves({
BillingAgreementDetails: {
BillingAgreementStatus: {State: 'Open'},
BillingAgreementStatus: { State: 'Open' },
},
});
}
@@ -81,7 +82,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
getBillingAgreementDetailsSpy = sinon.stub(amzLib, 'getBillingAgreementDetails');
getBillingAgreementDetailsSpy.resolves({
BillingAgreementDetails: {
BillingAgreementStatus: {State: 'Closed'},
BillingAgreementStatus: { State: 'Closed' },
},
});
@@ -89,7 +90,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
paymentCancelSubscriptionSpy.resolves({});
});
afterEach(function () {
afterEach(() => {
amzLib.getBillingAgreementDetails.restore();
payments.cancelSubscription.restore();
});
@@ -97,7 +98,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
it('should throw an error if we are missing a subscription', async () => {
user.purchased.plan.customerId = undefined;
await expect(amzLib.cancelSubscription({user}))
await expect(amzLib.cancelSubscription({ user }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
@@ -108,7 +109,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
it('should cancel a user subscription', async () => {
billingAgreementId = user.purchased.plan.customerId;
await amzLib.cancelSubscription({user, headers});
await amzLib.cancelSubscription({ user, headers });
expectAmazonCancelUserSubscriptionSpy();
expectAmazonStubs();
@@ -117,10 +118,10 @@ describe('Amazon Payments - Cancel Subscription', () => {
it('should close a user subscription if amazon not closed', async () => {
amzLib.getBillingAgreementDetails.restore();
expectBillingAggreementDetailSpy();
let closeBillingAgreementSpy = sinon.stub(amzLib, 'closeBillingAgreement').resolves({});
const closeBillingAgreementSpy = sinon.stub(amzLib, 'closeBillingAgreement').resolves({});
billingAgreementId = user.purchased.plan.customerId;
await amzLib.cancelSubscription({user, headers});
await amzLib.cancelSubscription({ user, headers });
expectAmazonStubs();
expect(closeBillingAgreementSpy).to.be.calledOnce;
@@ -132,7 +133,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
});
it('should throw an error if group is not found', async () => {
await expect(amzLib.cancelSubscription({user, groupId: 'fake-id'}))
await expect(amzLib.cancelSubscription({ user, groupId: 'fake-id' }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 404,
name: 'NotFound',
@@ -141,9 +142,9 @@ describe('Amazon Payments - Cancel Subscription', () => {
});
it('should throw an error if user is not group leader', async () => {
let nonLeader = await createNonLeaderGroupMember(group);
const nonLeader = await createNonLeaderGroupMember(group);
await expect(amzLib.cancelSubscription({user: nonLeader, groupId: group._id}))
await expect(amzLib.cancelSubscription({ user: nonLeader, groupId: group._id }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
@@ -154,7 +155,7 @@ describe('Amazon Payments - Cancel Subscription', () => {
it('should cancel a group subscription', async () => {
billingAgreementId = group.purchased.plan.customerId;
await amzLib.cancelSubscription({user, groupId: group._id, headers});
await amzLib.cancelSubscription({ user, groupId: group._id, headers });
expectAmazonCancelGroupSubscriptionSpy(group._id);
expectAmazonStubs();
@@ -163,10 +164,10 @@ describe('Amazon Payments - Cancel Subscription', () => {
it('should close a group subscription if amazon not closed', async () => {
amzLib.getBillingAgreementDetails.restore();
expectBillingAggreementDetailSpy();
let closeBillingAgreementSpy = sinon.stub(amzLib, 'closeBillingAgreement').resolves({});
const closeBillingAgreementSpy = sinon.stub(amzLib, 'closeBillingAgreement').resolves({});
billingAgreementId = group.purchased.plan.customerId;
await amzLib.cancelSubscription({user, groupId: group._id, headers});
await amzLib.cancelSubscription({ user, groupId: group._id, headers });
expectAmazonStubs();
expect(closeBillingAgreementSpy).to.be.calledOnce;

View File

@@ -3,11 +3,12 @@ import amzLib from '../../../../../../website/server/libs/payments/amazon';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
const i18n = common.i18n;
const { i18n } = common;
describe('Amazon Payments - Checkout', () => {
const subKey = 'basic_3mo';
let user, orderReferenceId, headers;
let user; let orderReferenceId; let
headers;
let setOrderReferenceDetailsSpy;
let confirmOrderReferenceSpy;
let authorizeSpy;
@@ -62,7 +63,7 @@ describe('Amazon Payments - Checkout', () => {
expect(closeOrderReferenceSpy).to.be.calledWith({ AmazonOrderReferenceId: orderReferenceId });
}
beforeEach(function () {
beforeEach(() => {
user = new User();
headers = {};
orderReferenceId = 'orderReferenceId';
@@ -88,7 +89,7 @@ describe('Amazon Payments - Checkout', () => {
sinon.stub(common, 'uuid').returns('uuid-generated');
});
afterEach(function () {
afterEach(() => {
amzLib.setOrderReferenceDetails.restore();
amzLib.confirmOrderReference.restore();
amzLib.authorize.restore();
@@ -101,7 +102,7 @@ describe('Amazon Payments - Checkout', () => {
function expectBuyGemsStub (paymentMethod, gift) {
expect(paymentBuyGemsStub).to.be.calledOnce;
let expectedArgs = {
const expectedArgs = {
user,
paymentMethod,
headers,
@@ -112,7 +113,7 @@ describe('Amazon Payments - Checkout', () => {
it('should purchase gems', async () => {
sinon.stub(user, 'canGetGems').resolves(true);
await amzLib.checkout({user, orderReferenceId, headers});
await amzLib.checkout({ user, orderReferenceId, headers });
expectBuyGemsStub(amzLib.constants.PAYMENT_METHOD);
expectAmazonStubs();
@@ -121,9 +122,9 @@ describe('Amazon Payments - Checkout', () => {
});
it('should error if gem amount is too low', async () => {
let receivingUser = new User();
const receivingUser = new User();
receivingUser.save();
let gift = {
const gift = {
type: 'gems',
gems: {
amount: 0,
@@ -131,7 +132,9 @@ describe('Amazon Payments - Checkout', () => {
},
};
await expect(amzLib.checkout({gift, user, orderReferenceId, headers}))
await expect(amzLib.checkout({
gift, user, orderReferenceId, headers,
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
message: 'Amount must be at least 1.',
@@ -141,18 +144,19 @@ describe('Amazon Payments - Checkout', () => {
it('should error if user cannot get gems gems', async () => {
sinon.stub(user, 'canGetGems').resolves(false);
await expect(amzLib.checkout({user, orderReferenceId, headers})).to.eventually.be.rejected.and.to.eql({
httpCode: 401,
message: i18n.t('groupPolicyCannotGetGems'),
name: 'NotAuthorized',
});
await expect(amzLib.checkout({ user, orderReferenceId, headers }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
message: i18n.t('groupPolicyCannotGetGems'),
name: 'NotAuthorized',
});
user.canGetGems.restore();
});
it('should gift gems', async () => {
let receivingUser = new User();
const receivingUser = new User();
await receivingUser.save();
let gift = {
const gift = {
type: 'gems',
uuid: receivingUser._id,
gems: {
@@ -160,16 +164,18 @@ describe('Amazon Payments - Checkout', () => {
},
};
amount = 16 / 4;
await amzLib.checkout({gift, user, orderReferenceId, headers});
await amzLib.checkout({
gift, user, orderReferenceId, headers,
});
expectBuyGemsStub(amzLib.constants.PAYMENT_METHOD_GIFT, gift);
expectAmazonStubs();
});
it('should gift a subscription', async () => {
let receivingUser = new User();
const receivingUser = new User();
receivingUser.save();
let gift = {
const gift = {
type: 'subscription',
subscription: {
key: subKey,
@@ -178,7 +184,9 @@ describe('Amazon Payments - Checkout', () => {
};
amount = common.content.subscriptionBlocks[subKey].price;
await amzLib.checkout({user, orderReferenceId, headers, gift});
await amzLib.checkout({
user, orderReferenceId, headers, gift,
});
gift.member = receivingUser;
expect(paymentCreateSubscritionStub).to.be.calledOnce;

View File

@@ -2,18 +2,19 @@ import cc from 'coupon-code';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper.js';
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import { model as Coupon } from '../../../../../../website/server/models/coupon';
import amzLib from '../../../../../../website/server/libs/payments/amazon';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
const i18n = common.i18n;
const { i18n } = common;
describe('Amazon Payments - Subscribe', () => {
const subKey = 'basic_3mo';
let user, group, amount, billingAgreementId, sub, coupon, groupId, headers;
let user; let group; let amount; let billingAgreementId; let sub; let coupon; let groupId; let
headers;
let amazonSetBillingAgreementDetailsSpy;
let amazonConfirmBillingAgreementSpy;
let amazonAuthorizeOnBillingAgreementSpy;
@@ -60,7 +61,7 @@ describe('Amazon Payments - Subscribe', () => {
sinon.stub(common, 'uuid').returns('uuid-generated');
});
afterEach(function () {
afterEach(() => {
amzLib.setBillingAgreementDetails.restore();
amzLib.confirmBillingAgreement.restore();
amzLib.authorizeOnBillingAgreement.restore();
@@ -168,7 +169,7 @@ describe('Amazon Payments - Subscribe', () => {
sub.key = 'google_6mo';
coupon = 'example-coupon';
let couponModel = new Coupon();
const couponModel = new Coupon();
couponModel.event = 'google_6mo';
await couponModel.save();
@@ -195,9 +196,9 @@ describe('Amazon Payments - Subscribe', () => {
sub.key = 'google_6mo';
coupon = 'example-coupon';
let couponModel = new Coupon();
const couponModel = new Coupon();
couponModel.event = 'google_6mo';
let updatedCouponModel = await couponModel.save();
const updatedCouponModel = await couponModel.save();
sinon.stub(cc, 'validate').returns(updatedCouponModel._id);

View File

@@ -2,16 +2,17 @@ import uuid from 'uuid';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper.js';
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import { model as Group } from '../../../../../../website/server/models/group';
import amzLib from '../../../../../../website/server/libs/payments/amazon';
import payments from '../../../../../../website/server/libs/payments/payments';
describe('#upgradeGroupPlan', () => {
let spy, data, user, group, uuidString;
let spy; let data; let user; let group; let
uuidString;
beforeEach(async function () {
beforeEach(async () => {
user = new User();
user.profile.name = 'sender';
@@ -46,7 +47,7 @@ describe('#upgradeGroupPlan', () => {
data.sub.quantity = 3;
});
afterEach(function () {
afterEach(() => {
amzLib.authorizeOnBillingAgreement.restore();
uuid.v4.restore();
});
@@ -55,7 +56,7 @@ describe('#upgradeGroupPlan', () => {
data.paymentMethod = amzLib.constants.PAYMENT_METHOD;
await payments.createSubscription(data);
let updatedGroup = await Group.findById(group._id).exec();
const updatedGroup = await Group.findById(group._id).exec();
updatedGroup.memberCount += 1;
await updatedGroup.save();

View File

@@ -1,21 +1,22 @@
/* eslint-disable camelcase */
import iapModule from '../../../../../website/server/libs/inAppPurchases';
import moment from 'moment';
import payments from '../../../../../website/server/libs/payments/payments';
import applePayments from '../../../../../website/server/libs/payments/apple';
import iap from '../../../../../website/server/libs/inAppPurchases';
import {model as User} from '../../../../../website/server/models/user';
import { model as User } from '../../../../../website/server/models/user';
import common from '../../../../../website/common';
import moment from 'moment';
import {mockFindById, restoreFindById} from '../../../../helpers/mongoose.helper';
import { mockFindById, restoreFindById } from '../../../../helpers/mongoose.helper';
const i18n = common.i18n;
const { i18n } = common;
describe('Apple Payments', () => {
let subKey = 'basic_3mo';
describe('Apple Payments', () => {
const subKey = 'basic_3mo';
describe('verifyGemPurchase', () => {
let sku, user, token, receipt, headers;
let iapSetupStub, iapValidateStub, iapIsValidatedStub, paymentBuyGemsStub, iapGetPurchaseDataStub;
let sku; let user; let token; let receipt; let
headers;
let iapSetupStub; let iapValidateStub; let iapIsValidatedStub; let paymentBuyGemsStub; let
iapGetPurchaseDataStub;
beforeEach(() => {
token = 'testToken';
@@ -24,33 +25,34 @@ describe('Apple Payments', () => {
receipt = `{"token": "${token}", "productId": "${sku}"}`;
headers = {};
iapSetupStub = sinon.stub(iapModule, 'setup')
iapSetupStub = sinon.stub(iap, 'setup')
.resolves();
iapValidateStub = sinon.stub(iapModule, 'validate')
iapValidateStub = sinon.stub(iap, 'validate')
.resolves({});
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(true);
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
.returns([{productId: 'com.habitrpg.ios.Habitica.21gems',
transactionId: token,
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
productId: 'com.habitrpg.ios.Habitica.21gems',
transactionId: token,
}]);
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').resolves({});
});
afterEach(() => {
iapModule.setup.restore();
iapModule.validate.restore();
iapModule.isValidated.restore();
iapModule.getPurchaseData.restore();
iap.setup.restore();
iap.validate.restore();
iap.isValidated.restore();
iap.getPurchaseData.restore();
payments.buyGems.restore();
});
it('should throw an error if receipt is invalid', async () => {
iapModule.isValidated.restore();
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
iap.isValidated.restore();
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(false);
await expect(applePayments.verifyGemPurchase({user, receipt, headers}))
await expect(applePayments.verifyGemPurchase({ user, receipt, headers }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
@@ -60,9 +62,9 @@ describe('Apple Payments', () => {
it('should throw an error if getPurchaseData is invalid', async () => {
iapGetPurchaseDataStub.restore();
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData').returns([]);
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData').returns([]);
await expect(applePayments.verifyGemPurchase({user, receipt, headers}))
await expect(applePayments.verifyGemPurchase({ user, receipt, headers }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
@@ -72,7 +74,7 @@ describe('Apple Payments', () => {
it('errors if the user cannot purchase gems', async () => {
sinon.stub(user, 'canGetGems').resolves(false);
await expect(applePayments.verifyGemPurchase({user, receipt, headers}))
await expect(applePayments.verifyGemPurchase({ user, receipt, headers }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
@@ -85,12 +87,13 @@ describe('Apple Payments', () => {
it('errors if amount does not exist', async () => {
sinon.stub(user, 'canGetGems').resolves(true);
iapGetPurchaseDataStub.restore();
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
.returns([{productId: 'badProduct',
transactionId: token,
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
productId: 'badProduct',
transactionId: token,
}]);
await expect(applePayments.verifyGemPurchase({user, receipt, headers}))
await expect(applePayments.verifyGemPurchase({ user, receipt, headers }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
@@ -126,13 +129,14 @@ describe('Apple Payments', () => {
gemsCanPurchase.forEach(gemTest => {
it(`purchases ${gemTest.productId} gems`, async () => {
iapGetPurchaseDataStub.restore();
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
.returns([{productId: gemTest.productId,
transactionId: token,
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
productId: gemTest.productId,
transactionId: token,
}]);
sinon.stub(user, 'canGetGems').resolves(true);
await applePayments.verifyGemPurchase({user, receipt, headers});
await applePayments.verifyGemPurchase({ user, receipt, headers });
expect(iapSetupStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledOnce;
@@ -160,13 +164,16 @@ describe('Apple Payments', () => {
mockFindById(receivingUser);
iapGetPurchaseDataStub.restore();
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
.returns([{productId: gemsCanPurchase[0].productId,
transactionId: token,
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
productId: gemsCanPurchase[0].productId,
transactionId: token,
}]);
const gift = {uuid: receivingUser._id};
await applePayments.verifyGemPurchase({user, gift, receipt, headers});
const gift = { uuid: receivingUser._id };
await applePayments.verifyGemPurchase({
user, gift, receipt, headers,
});
expect(iapSetupStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledOnce;
@@ -187,8 +194,11 @@ describe('Apple Payments', () => {
});
describe('subscribe', () => {
let sub, sku, user, token, receipt, headers, nextPaymentProcessing;
let iapSetupStub, iapValidateStub, iapIsValidatedStub, paymentsCreateSubscritionStub, iapGetPurchaseDataStub;
let sub; let sku; let user; let token; let receipt; let headers; let
nextPaymentProcessing;
let iapSetupStub; let iapValidateStub; let iapIsValidatedStub;
let paymentsCreateSubscritionStub; let
iapGetPurchaseDataStub;
beforeEach(() => {
sub = common.content.subscriptionBlocks[subKey];
@@ -197,25 +207,25 @@ describe('Apple Payments', () => {
token = 'test-token';
headers = {};
receipt = `{"token": "${token}"}`;
nextPaymentProcessing = moment.utc().add({days: 2});
nextPaymentProcessing = moment.utc().add({ days: 2 });
iapSetupStub = sinon.stub(iapModule, 'setup')
iapSetupStub = sinon.stub(iap, 'setup')
.resolves();
iapValidateStub = sinon.stub(iapModule, 'validate')
iapValidateStub = sinon.stub(iap, 'validate')
.resolves({});
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(true);
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
expirationDate: moment.utc().subtract({day: 1}).toDate(),
expirationDate: moment.utc().subtract({ day: 1 }).toDate(),
productId: sku,
transactionId: token,
}, {
expirationDate: moment.utc().add({day: 1}).toDate(),
expirationDate: moment.utc().add({ day: 1 }).toDate(),
productId: 'wrongsku',
transactionId: token,
}, {
expirationDate: moment.utc().add({day: 1}).toDate(),
expirationDate: moment.utc().add({ day: 1 }).toDate(),
productId: sku,
transactionId: token,
}]);
@@ -223,10 +233,10 @@ describe('Apple Payments', () => {
});
afterEach(() => {
iapModule.setup.restore();
iapModule.validate.restore();
iapModule.isValidated.restore();
iapModule.getPurchaseData.restore();
iap.setup.restore();
iap.validate.restore();
iap.isValidated.restore();
iap.getPurchaseData.restore();
if (payments.createSubscription.restore) payments.createSubscription.restore();
});
@@ -240,8 +250,8 @@ describe('Apple Payments', () => {
});
it('should throw an error if receipt is invalid', async () => {
iapModule.isValidated.restore();
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
iap.isValidated.restore();
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(false);
await expect(applePayments.subscribe(sku, user, receipt, headers, nextPaymentProcessing))
@@ -272,10 +282,10 @@ describe('Apple Payments', () => {
];
subOptions.forEach(option => {
it(`creates a user subscription for ${option.sku}`, async () => {
iapModule.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
expirationDate: moment.utc().add({day: 1}).toDate(),
expirationDate: moment.utc().add({ day: 1 }).toDate(),
productId: option.sku,
transactionId: token,
}]);
@@ -319,8 +329,10 @@ describe('Apple Payments', () => {
});
describe('cancelSubscribe ', () => {
let user, token, receipt, headers, customerId, expirationDate;
let iapSetupStub, iapValidateStub, iapIsValidatedStub, iapGetPurchaseDataStub, paymentCancelSubscriptionSpy;
let user; let token; let receipt; let headers; let customerId; let
expirationDate;
let iapSetupStub; let iapValidateStub; let iapIsValidatedStub; let iapGetPurchaseDataStub; let
paymentCancelSubscriptionSpy;
beforeEach(async () => {
token = 'test-token';
@@ -329,15 +341,15 @@ describe('Apple Payments', () => {
customerId = 'test-customerId';
expirationDate = moment.utc();
iapSetupStub = sinon.stub(iapModule, 'setup')
iapSetupStub = sinon.stub(iap, 'setup')
.resolves();
iapValidateStub = sinon.stub(iapModule, 'validate')
iapValidateStub = sinon.stub(iap, 'validate')
.resolves({
expirationDate,
});
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
.returns([{expirationDate: expirationDate.toDate()}]);
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{ expirationDate: expirationDate.toDate() }]);
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(true);
user = new User();
@@ -350,11 +362,11 @@ describe('Apple Payments', () => {
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
});
afterEach(function () {
iapModule.setup.restore();
iapModule.validate.restore();
iapModule.isValidated.restore();
iapModule.getPurchaseData.restore();
afterEach(() => {
iap.setup.restore();
iap.validate.restore();
iap.isValidated.restore();
iap.getPurchaseData.restore();
payments.cancelSubscription.restore();
});
@@ -370,9 +382,9 @@ describe('Apple Payments', () => {
});
it('should throw an error if subscription is still valid', async () => {
iapModule.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
.returns([{expirationDate: expirationDate.add({day: 1}).toDate()}]);
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{ expirationDate: expirationDate.add({ day: 1 }).toDate() }]);
await expect(applePayments.cancelSubscribe(user, headers))
.to.eventually.be.rejected.and.to.eql({
@@ -383,8 +395,8 @@ describe('Apple Payments', () => {
});
it('should throw an error if receipt is invalid', async () => {
iapModule.isValidated.restore();
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
iap.isValidated.restore();
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(false);
await expect(applePayments.cancelSubscribe(user, headers))

View File

@@ -1,21 +1,22 @@
/* eslint-disable camelcase */
import iapModule from '../../../../../website/server/libs/inAppPurchases';
import moment from 'moment';
import payments from '../../../../../website/server/libs/payments/payments';
import googlePayments from '../../../../../website/server/libs/payments/google';
import iap from '../../../../../website/server/libs/inAppPurchases';
import {model as User} from '../../../../../website/server/models/user';
import { model as User } from '../../../../../website/server/models/user';
import common from '../../../../../website/common';
import moment from 'moment';
import {mockFindById, restoreFindById} from '../../../../helpers/mongoose.helper';
import { mockFindById, restoreFindById } from '../../../../helpers/mongoose.helper';
const i18n = common.i18n;
const { i18n } = common;
describe('Google Payments', () => {
let subKey = 'basic_3mo';
describe('Google Payments', () => {
const subKey = 'basic_3mo';
describe('verifyGemPurchase', () => {
let sku, user, token, receipt, signature, headers;
let iapSetupStub, iapValidateStub, iapIsValidatedStub, paymentBuyGemsStub;
let sku; let user; let token; let receipt; let signature; let
headers;
let iapSetupStub; let iapValidateStub; let iapIsValidatedStub; let
paymentBuyGemsStub;
beforeEach(() => {
sku = 'com.habitrpg.android.habitica.iap.21gems';
@@ -24,28 +25,30 @@ describe('Google Payments', () => {
signature = '';
headers = {};
iapSetupStub = sinon.stub(iapModule, 'setup')
iapSetupStub = sinon.stub(iap, 'setup')
.resolves();
iapValidateStub = sinon.stub(iapModule, 'validate')
iapValidateStub = sinon.stub(iap, 'validate')
.resolves({});
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(true);
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').resolves({});
});
afterEach(() => {
iapModule.setup.restore();
iapModule.validate.restore();
iapModule.isValidated.restore();
iap.setup.restore();
iap.validate.restore();
iap.isValidated.restore();
payments.buyGems.restore();
});
it('should throw an error if receipt is invalid', async () => {
iapModule.isValidated.restore();
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
iap.isValidated.restore();
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(false);
await expect(googlePayments.verifyGemPurchase({user, receipt, signature, headers}))
await expect(googlePayments.verifyGemPurchase({
user, receipt, signature, headers,
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
@@ -56,7 +59,9 @@ describe('Google Payments', () => {
it('should throw an error if productId is invalid', async () => {
receipt = `{"token": "${token}", "productId": "invalid"}`;
await expect(googlePayments.verifyGemPurchase({user, receipt, signature, headers}))
await expect(googlePayments.verifyGemPurchase({
user, receipt, signature, headers,
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
@@ -67,7 +72,9 @@ describe('Google Payments', () => {
it('should throw an error if user cannot purchase gems', async () => {
sinon.stub(user, 'canGetGems').resolves(false);
await expect(googlePayments.verifyGemPurchase({user, receipt, signature, headers}))
await expect(googlePayments.verifyGemPurchase({
user, receipt, signature, headers,
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
@@ -79,7 +86,9 @@ describe('Google Payments', () => {
it('purchases gems', async () => {
sinon.stub(user, 'canGetGems').resolves(true);
await googlePayments.verifyGemPurchase({user, receipt, signature, headers});
await googlePayments.verifyGemPurchase({
user, receipt, signature, headers,
});
expect(iapSetupStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledOnce;
@@ -107,8 +116,10 @@ describe('Google Payments', () => {
mockFindById(receivingUser);
const gift = {uuid: receivingUser._id};
await googlePayments.verifyGemPurchase({user, gift, receipt, signature, headers});
const gift = { uuid: receivingUser._id };
await googlePayments.verifyGemPurchase({
user, gift, receipt, signature, headers,
});
expect(iapSetupStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledOnce;
@@ -131,8 +142,10 @@ describe('Google Payments', () => {
});
describe('subscribe', () => {
let sub, sku, user, token, receipt, signature, headers, nextPaymentProcessing;
let iapSetupStub, iapValidateStub, iapIsValidatedStub, paymentsCreateSubscritionStub;
let sub; let sku; let user; let token; let receipt; let signature; let headers; let
nextPaymentProcessing;
let iapSetupStub; let iapValidateStub; let iapIsValidatedStub; let
paymentsCreateSubscritionStub;
beforeEach(() => {
sub = common.content.subscriptionBlocks[subKey];
@@ -142,30 +155,31 @@ describe('Google Payments', () => {
headers = {};
receipt = `{"token": "${token}"}`;
signature = '';
nextPaymentProcessing = moment.utc().add({days: 2});
nextPaymentProcessing = moment.utc().add({ days: 2 });
iapSetupStub = sinon.stub(iapModule, 'setup')
iapSetupStub = sinon.stub(iap, 'setup')
.resolves();
iapValidateStub = sinon.stub(iapModule, 'validate')
iapValidateStub = sinon.stub(iap, 'validate')
.resolves({});
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(true);
paymentsCreateSubscritionStub = sinon.stub(payments, 'createSubscription').resolves({});
});
afterEach(() => {
iapModule.setup.restore();
iapModule.validate.restore();
iapModule.isValidated.restore();
iap.setup.restore();
iap.validate.restore();
iap.isValidated.restore();
payments.createSubscription.restore();
});
it('should throw an error if receipt is invalid', async () => {
iapModule.isValidated.restore();
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
iap.isValidated.restore();
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(false);
await expect(googlePayments.subscribe(sku, user, receipt, signature, headers, nextPaymentProcessing))
await expect(googlePayments
.subscribe(sku, user, receipt, signature, headers, nextPaymentProcessing))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
@@ -176,7 +190,8 @@ describe('Google Payments', () => {
it('should throw an error if sku is invalid', async () => {
sku = 'invalid';
await expect(googlePayments.subscribe(sku, user, receipt, signature, headers, nextPaymentProcessing))
await expect(googlePayments
.subscribe(sku, user, receipt, signature, headers, nextPaymentProcessing))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
@@ -203,15 +218,17 @@ describe('Google Payments', () => {
paymentMethod: googlePayments.constants.PAYMENT_METHOD_GOOGLE,
sub,
headers,
additionalData: {data: receipt, signature},
additionalData: { data: receipt, signature },
nextPaymentProcessing,
});
});
});
describe('cancelSubscribe ', () => {
let user, token, receipt, signature, headers, customerId, expirationDate;
let iapSetupStub, iapValidateStub, iapIsValidatedStub, iapGetPurchaseDataStub, paymentCancelSubscriptionSpy;
let user; let token; let receipt; let signature; let headers; let customerId; let
expirationDate;
let iapSetupStub; let iapValidateStub; let iapIsValidatedStub; let iapGetPurchaseDataStub; let
paymentCancelSubscriptionSpy;
beforeEach(async () => {
token = 'test-token';
@@ -221,15 +238,15 @@ describe('Google Payments', () => {
customerId = 'test-customerId';
expirationDate = moment.utc();
iapSetupStub = sinon.stub(iapModule, 'setup')
iapSetupStub = sinon.stub(iap, 'setup')
.resolves();
iapValidateStub = sinon.stub(iapModule, 'validate')
iapValidateStub = sinon.stub(iap, 'validate')
.resolves({
expirationDate,
});
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
.returns([{expirationDate: expirationDate.toDate()}]);
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{ expirationDate: expirationDate.toDate() }]);
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(true);
user = new User();
@@ -237,16 +254,16 @@ describe('Google Payments', () => {
user.purchased.plan.customerId = customerId;
user.purchased.plan.paymentMethod = googlePayments.constants.PAYMENT_METHOD_GOOGLE;
user.purchased.plan.planId = subKey;
user.purchased.plan.additionalData = {data: receipt, signature};
user.purchased.plan.additionalData = { data: receipt, signature };
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
});
afterEach(function () {
iapModule.setup.restore();
iapModule.validate.restore();
iapModule.isValidated.restore();
iapModule.getPurchaseData.restore();
afterEach(() => {
iap.setup.restore();
iap.validate.restore();
iap.isValidated.restore();
iap.getPurchaseData.restore();
payments.cancelSubscription.restore();
});
@@ -262,9 +279,9 @@ describe('Google Payments', () => {
});
it('should throw an error if subscription is still valid', async () => {
iapModule.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iapModule, 'getPurchaseData')
.returns([{expirationDate: expirationDate.add({day: 1}).toDate()}]);
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({
@@ -275,8 +292,8 @@ describe('Google Payments', () => {
});
it('should throw an error if receipt is invalid', async () => {
iapModule.isValidated.restore();
iapIsValidatedStub = sinon.stub(iapModule, 'isValidated')
iap.isValidated.restore();
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(false);
await expect(googlePayments.cancelSubscribe(user, headers))

View File

@@ -6,11 +6,12 @@ import { model as User } from '../../../../../../website/server/models/user';
import { model as Group } from '../../../../../../website/server/models/group';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper.js';
} from '../../../../../helpers/api-unit.helper';
import i18n from '../../../../../../website/common/script/i18n';
describe('Canceling a subscription for group', () => {
let plan, group, user, data;
let plan; let group; let user; let
data;
beforeEach(async () => {
user = new User();
@@ -67,9 +68,9 @@ describe('Canceling a subscription for group', () => {
data.groupId = group._id;
await api.cancelSubscription(data);
let now = new Date();
let updatedGroup = await Group.findById(group._id).exec();
let daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
const now = new Date();
const updatedGroup = await Group.findById(group._id).exec();
const daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
expect(daysTillTermination).to.be.within(29, 30); // 1 month +/- 1 days
});
@@ -81,9 +82,9 @@ describe('Canceling a subscription for group', () => {
await api.cancelSubscription(data);
let now = new Date();
let updatedGroup = await Group.findById(group._id).exec();
let daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
const now = new Date();
const updatedGroup = await Group.findById(group._id).exec();
const daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
expect(daysTillTermination).to.be.within(89, 90); // 3 months +/- 1 days
});
@@ -95,9 +96,9 @@ describe('Canceling a subscription for group', () => {
await api.cancelSubscription(data);
let now = new Date();
let updatedGroup = await Group.findById(group._id).exec();
let daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
const now = new Date();
const updatedGroup = await Group.findById(group._id).exec();
const daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
expect(daysTillTermination).to.be.within(38, 39); // should be about 1 month + 1/3 month
});
@@ -108,9 +109,9 @@ describe('Canceling a subscription for group', () => {
await api.cancelSubscription(data);
let now = new Date();
let updatedGroup = await Group.findById(group._id).exec();
let daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
const now = new Date();
const updatedGroup = await Group.findById(group._id).exec();
const daysTillTermination = moment(updatedGroup.purchased.plan.dateTerminated).diff(now, 'days');
expect(daysTillTermination).to.be.within(13, 15);
});
@@ -122,7 +123,7 @@ describe('Canceling a subscription for group', () => {
await api.cancelSubscription(data);
let updatedGroup = await Group.findById(group._id).exec();
const updatedGroup = await Group.findById(group._id).exec();
expect(updatedGroup.purchased.plan.extraMonths).to.eql(0);
});
@@ -134,12 +135,12 @@ describe('Canceling a subscription for group', () => {
expect(sender.sendTxn.firstCall.args[0]._id).to.equal(user._id);
expect(sender.sendTxn.firstCall.args[1]).to.equal('group-cancel-subscription');
expect(sender.sendTxn.firstCall.args[2]).to.eql([
{name: 'GROUP_NAME', content: group.name},
{ name: 'GROUP_NAME', content: group.name },
]);
});
it('prevents non group leader from managing subscription', async () => {
let groupMember = new User();
const groupMember = new User();
data.user = groupMember;
data.groupId = group._id;
@@ -160,7 +161,7 @@ describe('Canceling a subscription for group', () => {
await api.createSubscription(data);
let updatedGroup = await Group.findById(group._id).exec();
let newLeader = new User();
const newLeader = new User();
updatedGroup.leader = newLeader._id;
await updatedGroup.save();
@@ -192,15 +193,15 @@ describe('Canceling a subscription for group', () => {
await api.cancelSubscription(data);
let now = new Date();
const now = new Date();
now.setHours(0, 0, 0, 0);
let updatedLeader = await User.findById(user._id).exec();
let daysTillTermination = moment(updatedLeader.purchased.plan.dateTerminated).diff(now, 'days');
const updatedLeader = await User.findById(user._id).exec();
const daysTillTermination = moment(updatedLeader.purchased.plan.dateTerminated).diff(now, 'days');
expect(daysTillTermination).to.be.within(2, 3); // only a few days
});
it('sends an email to members of group', async () => {
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
recipient.guilds.push(group._id);
await recipient.save();
@@ -214,8 +215,8 @@ describe('Canceling a subscription for group', () => {
expect(sender.sendTxn.thirdCall.args[0]._id).to.equal(recipient._id);
expect(sender.sendTxn.thirdCall.args[1]).to.equal('group-member-cancel');
expect(sender.sendTxn.thirdCall.args[2]).to.eql([
{name: 'LEADER', content: user.profile.name},
{name: 'GROUP_NAME', content: group.name},
{ name: 'LEADER', content: user.profile.name },
{ name: 'GROUP_NAME', content: group.name },
]);
});
@@ -223,7 +224,7 @@ describe('Canceling a subscription for group', () => {
plan.key = 'basic_earned';
plan.customerId = api.constants.UNLIMITED_CUSTOMER_ID;
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
recipient.purchased.plan = plan;
recipient.guilds.push(group._id);
@@ -233,12 +234,12 @@ describe('Canceling a subscription for group', () => {
await api.cancelSubscription(data);
let updatedLeader = await User.findById(user._id).exec();
const updatedLeader = await User.findById(user._id).exec();
expect(updatedLeader.purchased.plan.dateTerminated).to.not.exist;
});
it('does not cancel a user subscription if they are still in another active group plan', async () => {
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
plan.key = 'basic_earned';
recipient.purchased.plan = plan;
@@ -252,10 +253,10 @@ describe('Canceling a subscription for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
let firstDateCreated = updatedUser.purchased.plan.dateCreated;
let extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
const firstDateCreated = updatedUser.purchased.plan.dateCreated;
const extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
let group2 = generateGroup({
const group2 = generateGroup({
name: 'test group2',
type: 'guild',
privacy: 'public',
@@ -291,10 +292,10 @@ describe('Canceling a subscription for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(user._id).exec();
let firstDateCreated = updatedUser.purchased.plan.dateCreated;
let extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
const firstDateCreated = updatedUser.purchased.plan.dateCreated;
const extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
let group2 = generateGroup({
const group2 = generateGroup({
name: 'test group2',
type: 'guild',
privacy: 'public',

View File

@@ -11,7 +11,7 @@ import { model as User } from '../../../../../../website/server/models/user';
import { model as Group } from '../../../../../../website/server/models/group';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper.js';
} from '../../../../../helpers/api-unit.helper';
describe('Purchasing a group plan for group', () => {
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_GOOGLE = 'Google_subscription';
@@ -19,10 +19,11 @@ describe('Purchasing a group plan for group', () => {
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL = 'normal_subscription';
const EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NONE = 'no_subscription';
let plan, group, user, data;
let stripe = stripeModule('test');
let groupLeaderName = 'sender';
let groupName = 'test group';
let plan; let group; let user; let
data;
const stripe = stripeModule('test');
const groupLeaderName = 'sender';
const groupName = 'test group';
beforeEach(async () => {
user = new User();
@@ -68,14 +69,17 @@ describe('Purchasing a group plan for group', () => {
},
};
let subscriptionId = 'subId';
const subscriptionId = 'subId';
sinon.stub(stripe.customers, 'del').resolves({});
let currentPeriodEndTimeStamp = moment().add(3, 'months').unix();
const currentPeriodEndTimeStamp = moment().add(3, 'months').unix();
sinon.stub(stripe.customers, 'retrieve')
.resolves({
subscriptions: {
data: [{id: subscriptionId, current_period_end: currentPeriodEndTimeStamp}], // eslint-disable-line camelcase
data: [{
id: subscriptionId,
current_period_end: currentPeriodEndTimeStamp,
}], // eslint-disable-line camelcase
},
});
@@ -95,7 +99,7 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedGroup = await Group.findById(group._id).exec();
const updatedGroup = await Group.findById(group._id).exec();
expect(updatedGroup.purchased.plan.planId).to.eql('basic_3mo');
expect(updatedGroup.purchased.plan.customerId).to.eql('customer-id');
@@ -126,7 +130,7 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedGroup = await Group.findById(group._id).exec();
const updatedGroup = await Group.findById(group._id).exec();
expect(updatedGroup.purchased.plan.extraMonths).to.within(1.9, 2);
});
@@ -139,7 +143,7 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedGroup = await Group.findById(group._id).exec();
const updatedGroup = await Group.findById(group._id).exec();
expect(updatedGroup.purchased.plan.extraMonths).to.eql(0);
});
@@ -150,7 +154,7 @@ describe('Purchasing a group plan for group', () => {
data.groupId = group._id;
await api.createSubscription(data);
let updatedLeader = await User.findById(user._id).exec();
const updatedLeader = await User.findById(user._id).exec();
expect(updatedLeader.purchased.plan.planId).to.eql('group_plan_auto');
expect(updatedLeader.purchased.plan.customerId).to.eql('group-plan');
@@ -166,7 +170,7 @@ describe('Purchasing a group plan for group', () => {
});
it('sends an email to member of group who was not a subscriber', async () => {
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
recipient.guilds.push(group._id);
await recipient.save();
@@ -179,9 +183,9 @@ describe('Purchasing a group plan for group', () => {
expect(sender.sendTxn.firstCall.args[0]._id).to.equal(recipient._id);
expect(sender.sendTxn.firstCall.args[1]).to.equal('group-member-join');
expect(sender.sendTxn.firstCall.args[2]).to.eql([
{name: 'LEADER', content: user.profile.name},
{name: 'GROUP_NAME', content: group.name},
{name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NONE},
{ name: 'LEADER', content: user.profile.name },
{ name: 'GROUP_NAME', content: group.name },
{ name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NONE },
]);
// confirm that the other email sent is appropriate:
expect(sender.sendTxn.secondCall.args[0]._id).to.equal(group.leader);
@@ -189,7 +193,7 @@ describe('Purchasing a group plan for group', () => {
});
it('sends one email to subscribed member of group, stating subscription is cancelled (Stripe)', async () => {
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
plan.key = 'basic_earned';
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
@@ -205,9 +209,9 @@ describe('Purchasing a group plan for group', () => {
expect(sender.sendTxn.firstCall.args[0]._id).to.equal(recipient._id);
expect(sender.sendTxn.firstCall.args[1]).to.equal('group-member-join');
expect(sender.sendTxn.firstCall.args[2]).to.eql([
{name: 'LEADER', content: user.profile.name},
{name: 'GROUP_NAME', content: group.name},
{name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL},
{ name: 'LEADER', content: user.profile.name },
{ name: 'GROUP_NAME', content: group.name },
{ name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL },
]);
// confirm that the other email sent is not a cancel-subscription email:
expect(sender.sendTxn.secondCall.args[0]._id).to.equal(group.leader);
@@ -218,11 +222,11 @@ describe('Purchasing a group plan for group', () => {
sinon.stub(amzLib, 'getBillingAgreementDetails')
.resolves({
BillingAgreementDetails: {
BillingAgreementStatus: {State: 'Closed'},
BillingAgreementStatus: { State: 'Closed' },
},
});
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
plan.planId = 'basic_earned';
plan.paymentMethod = amzLib.constants.PAYMENT_METHOD;
@@ -238,9 +242,9 @@ describe('Purchasing a group plan for group', () => {
expect(sender.sendTxn.firstCall.args[0]._id).to.equal(recipient._id);
expect(sender.sendTxn.firstCall.args[1]).to.equal('group-member-join');
expect(sender.sendTxn.firstCall.args[2]).to.eql([
{name: 'LEADER', content: user.profile.name},
{name: 'GROUP_NAME', content: group.name},
{name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL},
{ name: 'LEADER', content: user.profile.name },
{ name: 'GROUP_NAME', content: group.name },
{ name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL },
]);
// confirm that the other email sent is not a cancel-subscription email:
expect(sender.sendTxn.secondCall.args[0]._id).to.equal(group.leader);
@@ -259,7 +263,7 @@ describe('Purchasing a group plan for group', () => {
},
});
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
plan.planId = 'basic_earned';
plan.paymentMethod = paypalPayments.constants.PAYMENT_METHOD;
@@ -275,9 +279,9 @@ describe('Purchasing a group plan for group', () => {
expect(sender.sendTxn.firstCall.args[0]._id).to.equal(recipient._id);
expect(sender.sendTxn.firstCall.args[1]).to.equal('group-member-join');
expect(sender.sendTxn.firstCall.args[2]).to.eql([
{name: 'LEADER', content: user.profile.name},
{name: 'GROUP_NAME', content: group.name},
{name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL},
{ name: 'LEADER', content: user.profile.name },
{ name: 'GROUP_NAME', content: group.name },
{ name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_NORMAL },
]);
// confirm that the other email sent is not a cancel-subscription email:
expect(sender.sendTxn.secondCall.args[0]._id).to.equal(group.leader);
@@ -292,7 +296,7 @@ describe('Purchasing a group plan for group', () => {
plan.customerId = 'random';
plan.paymentMethod = api.constants.GOOGLE_PAYMENT_METHOD;
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
recipient.purchased.plan = plan;
recipient.guilds.push(group._id);
@@ -310,9 +314,9 @@ describe('Purchasing a group plan for group', () => {
expect(sender.sendTxn.args[1][0]._id).to.equal(recipient._id);
expect(sender.sendTxn.args[1][1]).to.equal('group-member-join');
expect(sender.sendTxn.args[1][2]).to.eql([
{name: 'LEADER', content: groupLeaderName},
{name: 'GROUP_NAME', content: groupName},
{name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_GOOGLE},
{ name: 'LEADER', content: groupLeaderName },
{ name: 'GROUP_NAME', content: groupName },
{ name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_GOOGLE },
]);
expect(sender.sendTxn.args[2][0]._id).to.equal(group.leader);
expect(sender.sendTxn.args[2][1]).to.equal('group-member-join');
@@ -325,7 +329,7 @@ describe('Purchasing a group plan for group', () => {
plan.customerId = 'random';
plan.paymentMethod = api.constants.IOS_PAYMENT_METHOD;
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
recipient.purchased.plan = plan;
recipient.guilds.push(group._id);
@@ -343,9 +347,9 @@ describe('Purchasing a group plan for group', () => {
expect(sender.sendTxn.args[1][0]._id).to.equal(recipient._id);
expect(sender.sendTxn.args[1][1]).to.equal('group-member-join');
expect(sender.sendTxn.args[1][2]).to.eql([
{name: 'LEADER', content: groupLeaderName},
{name: 'GROUP_NAME', content: groupName},
{name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_IOS},
{ name: 'LEADER', content: groupLeaderName },
{ name: 'GROUP_NAME', content: groupName },
{ name: 'PREVIOUS_SUBSCRIPTION_TYPE', content: EMAIL_TEMPLATE_SUBSCRIPTION_TYPE_IOS },
]);
expect(sender.sendTxn.args[2][0]._id).to.equal(group.leader);
expect(sender.sendTxn.args[2][1]).to.equal('group-member-join');
@@ -354,7 +358,7 @@ describe('Purchasing a group plan for group', () => {
});
it('adds months to members with existing gift subscription', async () => {
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
recipient.purchased.plan = plan;
recipient.guilds.push(group._id);
@@ -378,7 +382,7 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
const updatedUser = await User.findById(recipient._id).exec();
expect(updatedUser.purchased.plan.planId).to.eql('group_plan_auto');
expect(updatedUser.purchased.plan.customerId).to.eql('group-plan');
@@ -392,7 +396,7 @@ describe('Purchasing a group plan for group', () => {
});
it('adds months to members with existing multi-month gift subscription', async () => {
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
recipient.purchased.plan = plan;
recipient.guilds.push(group._id);
@@ -414,7 +418,7 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
const updatedUser = await User.findById(recipient._id).exec();
expect(updatedUser.purchased.plan.planId).to.eql('group_plan_auto');
expect(updatedUser.purchased.plan.customerId).to.eql('group-plan');
@@ -428,7 +432,7 @@ describe('Purchasing a group plan for group', () => {
});
it('adds months to members with existing recurring subscription (Stripe)', async () => {
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
plan.key = 'basic_earned';
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
@@ -450,11 +454,11 @@ describe('Purchasing a group plan for group', () => {
sinon.stub(amzLib, 'getBillingAgreementDetails')
.resolves({
BillingAgreementDetails: {
BillingAgreementStatus: {State: 'Closed'},
BillingAgreementStatus: { State: 'Closed' },
},
});
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
plan.planId = 'basic_earned';
plan.paymentMethod = amzLib.constants.PAYMENT_METHOD;
@@ -470,7 +474,7 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
const updatedUser = await User.findById(recipient._id).exec();
expect(updatedUser.purchased.plan.extraMonths).to.within(3, 5);
});
@@ -485,7 +489,7 @@ describe('Purchasing a group plan for group', () => {
},
});
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
plan.planId = 'basic_earned';
plan.paymentMethod = paypalPayments.constants.PAYMENT_METHOD;
@@ -500,7 +504,7 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
const updatedUser = await User.findById(recipient._id).exec();
expect(updatedUser.purchased.plan.extraMonths).to.within(2, 3);
paypalPayments.paypalBillingAgreementGet.restore();
@@ -511,7 +515,7 @@ describe('Purchasing a group plan for group', () => {
it('adds months to members with existing recurring subscription (iOS)');
it('adds months to members who already cancelled but not yet terminated recurring subscription', async () => {
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
plan.key = 'basic_earned';
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
@@ -527,13 +531,13 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
const updatedUser = await User.findById(recipient._id).exec();
expect(updatedUser.purchased.plan.extraMonths).to.within(2, 3);
});
it('adds months to members who already cancelled but not yet terminated group plan subscription', async () => {
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
plan.key = 'basic_earned';
plan.paymentMethod = api.constants.GROUP_PLAN_PAYMENT_METHOD;
@@ -550,12 +554,12 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
const updatedUser = await User.findById(recipient._id).exec();
expect(updatedUser.purchased.plan.extraMonths).to.within(3, 4);
});
it('resets date terminated if user has old subscription', async () => {
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
plan.key = 'basic_earned';
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
@@ -570,13 +574,13 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
const updatedUser = await User.findById(recipient._id).exec();
expect(updatedUser.purchased.plan.dateTerminated).to.not.exist;
});
it('adds months to members with existing recurring subscription and includes existing extraMonths', async () => {
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
plan.key = 'basic_earned';
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
@@ -591,13 +595,13 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
const updatedUser = await User.findById(recipient._id).exec();
expect(updatedUser.purchased.plan.extraMonths).to.within(7, 9);
});
it('adds months to members with existing recurring subscription and ignores existing negative extraMonths', async () => {
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
plan.key = 'basic_earned';
plan.paymentMethod = stripePayments.constants.PAYMENT_METHOD;
@@ -612,23 +616,23 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
const updatedUser = await User.findById(recipient._id).exec();
expect(updatedUser.purchased.plan.extraMonths).to.within(2, 3);
});
it('does not override gemsBought, mysteryItems, dateCreated, and consective fields', async () => {
let planCreatedDate = moment().toDate();
let mysteryItem = {title: 'item'};
let mysteryItems = [mysteryItem];
let consecutive = {
const planCreatedDate = moment().toDate();
const mysteryItem = { title: 'item' };
const mysteryItems = [mysteryItem];
const consecutive = {
trinkets: 3,
gemCapExtra: 20,
offset: 1,
count: 13,
};
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
plan.key = 'basic_earned';
@@ -647,7 +651,7 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
const updatedUser = await User.findById(recipient._id).exec();
expect(updatedUser.purchased.plan.gemsBought).to.equal(3);
expect(updatedUser.purchased.plan.mysteryItems[0]).to.eql(mysteryItem);
@@ -659,7 +663,7 @@ describe('Purchasing a group plan for group', () => {
});
it('does not modify a user with a group subscription when they join another group', async () => {
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
plan.key = 'basic_earned';
recipient.purchased.plan = plan;
@@ -673,10 +677,10 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
let firstDateCreated = updatedUser.purchased.plan.dateCreated;
let extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
const firstDateCreated = updatedUser.purchased.plan.dateCreated;
const extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
let group2 = generateGroup({
const group2 = generateGroup({
name: 'test group2',
type: 'guild',
privacy: 'public',
@@ -703,7 +707,7 @@ describe('Purchasing a group plan for group', () => {
});
it('does not remove a user who is in two groups plans and leaves one', async () => {
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
plan.key = 'basic_earned';
recipient.purchased.plan = plan;
@@ -717,10 +721,10 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
let firstDateCreated = updatedUser.purchased.plan.dateCreated;
let extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
const firstDateCreated = updatedUser.purchased.plan.dateCreated;
const extraMonthsBeforeSecond = updatedUser.purchased.plan.extraMonths;
let group2 = generateGroup({
const group2 = generateGroup({
name: 'test group2',
type: 'guild',
privacy: 'public',
@@ -733,7 +737,7 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedGroup = await Group.findById(group._id).exec();
const updatedGroup = await Group.findById(group._id).exec();
await updatedGroup.leave(recipient);
updatedUser = await User.findById(recipient._id).exec();
@@ -753,7 +757,7 @@ describe('Purchasing a group plan for group', () => {
plan.key = 'basic_earned';
plan.customerId = api.constants.UNLIMITED_CUSTOMER_ID;
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
recipient.purchased.plan = plan;
recipient.guilds.push(group._id);
@@ -765,7 +769,7 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
const updatedUser = await User.findById(recipient._id).exec();
expect(updatedUser.purchased.plan.planId).to.eql('basic_3mo');
expect(updatedUser.purchased.plan.customerId).to.eql(api.constants.UNLIMITED_CUSTOMER_ID);
@@ -782,7 +786,7 @@ describe('Purchasing a group plan for group', () => {
plan.customerId = 'random';
plan.paymentMethod = api.constants.GOOGLE_PAYMENT_METHOD;
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
recipient.purchased.plan = plan;
recipient.guilds.push(group._id);
@@ -794,7 +798,7 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
const updatedUser = await User.findById(recipient._id).exec();
expect(updatedUser.purchased.plan.planId).to.eql('basic_3mo');
expect(updatedUser.purchased.plan.customerId).to.eql('random');
@@ -811,7 +815,7 @@ describe('Purchasing a group plan for group', () => {
plan.customerId = 'random';
plan.paymentMethod = api.constants.IOS_PAYMENT_METHOD;
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
recipient.purchased.plan = plan;
recipient.guilds.push(group._id);
@@ -823,7 +827,7 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
const updatedUser = await User.findById(recipient._id).exec();
expect(updatedUser.purchased.plan.planId).to.eql('basic_3mo');
expect(updatedUser.purchased.plan.customerId).to.eql('random');
@@ -841,7 +845,7 @@ describe('Purchasing a group plan for group', () => {
plan.customerId = api.constants.GROUP_PLAN_CUSTOMER_ID;
plan.dateTerminated = moment().add(1, 'months');
let recipient = new User();
const recipient = new User();
recipient.profile.name = 'recipient';
recipient.purchased.plan = plan;
recipient.guilds.push(group._id);
@@ -853,7 +857,7 @@ describe('Purchasing a group plan for group', () => {
await api.createSubscription(data);
let updatedUser = await User.findById(recipient._id).exec();
const updatedUser = await User.findById(recipient._id).exec();
expect(updatedUser.purchased.plan.planId).to.eql('group_plan_auto');
expect(updatedUser.purchased.plan.customerId).to.eql(api.constants.GROUP_PLAN_CUSTOMER_ID);

View File

@@ -1,7 +1,7 @@
import { model as User } from '../../../../../website/server/models/user';
export async function createNonLeaderGroupMember (group) {
let nonLeader = new User();
export async function createNonLeaderGroupMember (group) { // eslint-disable-line import/prefer-default-export, max-len
const nonLeader = new User();
nonLeader.guilds.push(group._id);
return await nonLeader.save();
return nonLeader.save();
}

View File

@@ -8,10 +8,11 @@ import { model as User } from '../../../../../website/server/models/user';
import { translate as t } from '../../../../helpers/api-integration/v3';
import {
generateGroup,
} from '../../../../helpers/api-unit.helper.js';
} from '../../../../helpers/api-unit.helper';
describe('payments/index', () => {
let user, group, data, plan;
let user; let group; let data; let
plan;
beforeEach(async () => {
user = new User();
@@ -102,7 +103,7 @@ describe('payments/index', () => {
});
it('does not set negative extraMonths if plan has past dateTerminated date', async () => {
let dateTerminated = moment().subtract(2, 'months').toDate();
const dateTerminated = moment().subtract(2, 'months').toDate();
recipient.purchased.plan.dateTerminated = dateTerminated;
await api.createSubscription(data);
@@ -120,7 +121,7 @@ describe('payments/index', () => {
});
it('adds to date terminated for an existing plan with a future terminated date', async () => {
let dateTerminated = moment().add(1, 'months').toDate();
const dateTerminated = moment().add(1, 'months').toDate();
recipient.purchased.plan = plan;
recipient.purchased.plan.dateTerminated = dateTerminated;
@@ -130,7 +131,7 @@ describe('payments/index', () => {
});
it('replaces date terminated for an account with a past terminated date', async () => {
let dateTerminated = moment().subtract(1, 'months').toDate();
const dateTerminated = moment().subtract(1, 'months').toDate();
recipient.purchased.plan.dateTerminated = dateTerminated;
await api.createSubscription(data);
@@ -208,18 +209,21 @@ describe('payments/index', () => {
it('sends a private message about the gift', async () => {
await api.createSubscription(data);
let msg = '\`Hello recipient, sender has sent you 3 months of subscription!\`';
const msg = '`Hello recipient, sender has sent you 3 months of subscription!`';
expect(user.sendMessage).to.be.calledOnce;
expect(user.sendMessage).to.be.calledWith(recipient, { receiverMsg: msg, senderMsg: msg, save: false });
expect(user.sendMessage).to.be.calledWith(
recipient,
{ receiverMsg: msg, senderMsg: msg, save: false },
);
});
it('sends an email about the gift', async () => {
await api.createSubscription(data);
expect(sender.sendTxn).to.be.calledWith(recipient, 'gifted-subscription', [
{name: 'GIFTER', content: 'sender'},
{name: 'X_MONTHS_SUBSCRIPTION', content: 3},
{ name: 'GIFTER', content: 'sender' },
{ name: 'X_MONTHS_SUBSCRIPTION', content: 3 },
]);
});
@@ -416,8 +420,8 @@ describe('payments/index', () => {
context('Mystery Items', () => {
it('awards mystery items when within the timeframe for a mystery item', async () => {
let mayMysteryItemTimeframe = 1464725113000; // May 31st 2016
let fakeClock = sinon.useFakeTimers(mayMysteryItemTimeframe);
const mayMysteryItemTimeframe = 1464725113000; // May 31st 2016
const fakeClock = sinon.useFakeTimers(mayMysteryItemTimeframe);
data = { paymentMethod: 'PaymentMethod', user, sub: { key: 'basic_3mo' } };
@@ -437,7 +441,7 @@ describe('payments/index', () => {
it('does not awards mystery items when not within the timeframe for a mystery item', async () => {
const noMysteryItemTimeframe = 1462183920000; // May 2nd 2016
let fakeClock = sinon.useFakeTimers(noMysteryItemTimeframe);
const fakeClock = sinon.useFakeTimers(noMysteryItemTimeframe);
data = { paymentMethod: 'PaymentMethod', user, sub: { key: 'basic_3mo' } };
await api.createSubscription(data);
@@ -449,7 +453,7 @@ describe('payments/index', () => {
it('does not add a notification for mystery items if none was awarded', async () => {
const noMysteryItemTimeframe = 1462183920000; // May 2nd 2016
let fakeClock = sinon.useFakeTimers(noMysteryItemTimeframe);
const fakeClock = sinon.useFakeTimers(noMysteryItemTimeframe);
data = { paymentMethod: 'PaymentMethod', user, sub: { key: 'basic_3mo' } };
await api.createSubscription(data);
@@ -461,9 +465,9 @@ describe('payments/index', () => {
});
it('does not award mystery item when user already owns the item', async () => {
let mayMysteryItemTimeframe = 1464725113000; // May 31st 2016
let fakeClock = sinon.useFakeTimers(mayMysteryItemTimeframe);
let mayMysteryItem = 'armor_mystery_201605';
const mayMysteryItemTimeframe = 1464725113000; // May 31st 2016
const fakeClock = sinon.useFakeTimers(mayMysteryItemTimeframe);
const mayMysteryItem = 'armor_mystery_201605';
user.items.gear.owned[mayMysteryItem] = true;
data = { paymentMethod: 'PaymentMethod', user, sub: { key: 'basic_3mo' } };
@@ -477,9 +481,9 @@ describe('payments/index', () => {
});
it('does not award mystery item when user already has the item in the mystery box', async () => {
let mayMysteryItemTimeframe = 1464725113000; // May 31st 2016
let fakeClock = sinon.useFakeTimers(mayMysteryItemTimeframe);
let mayMysteryItem = 'armor_mystery_201605';
const mayMysteryItemTimeframe = 1464725113000; // May 31st 2016
const fakeClock = sinon.useFakeTimers(mayMysteryItemTimeframe);
const mayMysteryItem = 'armor_mystery_201605';
user.purchased.plan.mysteryItems = [mayMysteryItem];
sandbox.spy(user.purchased.plan.mysteryItems, 'push');
@@ -504,8 +508,8 @@ describe('payments/index', () => {
it('adds a month termination date by default', async () => {
await api.cancelSubscription(data);
let now = new Date();
let daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
const now = new Date();
const daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
expect(daysTillTermination).to.be.within(29, 30); // 1 month +/- 1 days
});
@@ -515,8 +519,8 @@ describe('payments/index', () => {
await api.cancelSubscription(data);
let now = new Date();
let daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
const now = new Date();
const daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
expect(daysTillTermination).to.be.within(89, 90); // 3 months +/- 1 days
});
@@ -526,8 +530,8 @@ describe('payments/index', () => {
await api.cancelSubscription(data);
let now = new Date();
let daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
const now = new Date();
const daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
expect(daysTillTermination).to.be.within(38, 39); // should be about 1 month + 1/3 month
});
@@ -537,8 +541,8 @@ describe('payments/index', () => {
await api.cancelSubscription(data);
let now = new Date();
let daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
const now = new Date();
const daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
expect(daysTillTermination).to.be.within(13, 15);
});
@@ -549,8 +553,8 @@ describe('payments/index', () => {
await api.cancelSubscription(data);
let now = new Date();
let daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
const now = new Date();
const daysTillTermination = moment(user.purchased.plan.dateTerminated).diff(now, 'days');
expect(daysTillTermination).to.be.within(13, 15);
});
@@ -641,9 +645,10 @@ describe('payments/index', () => {
it('sends a message from purchaser to recipient', async () => {
await api.buyGems(data);
let msg = '\`Hello recipient, sender has sent you 4 gems!\`';
const msg = '`Hello recipient, sender has sent you 4 gems!`';
expect(user.sendMessage).to.be.calledWith(recipient, { receiverMsg: msg, senderMsg: msg, save: false });
expect(user.sendMessage).to.be
.calledWith(recipient, { receiverMsg: msg, senderMsg: msg, save: false });
});
it('sends a message from purchaser to recipient wtih custom message', async () => {
@@ -652,7 +657,8 @@ describe('payments/index', () => {
await api.buyGems(data);
const msg = `\`Hello recipient, sender has sent you 4 gems!\` ${data.gift.message}`;
expect(user.sendMessage).to.be.calledWith(recipient, { receiverMsg: msg, senderMsg: msg, save: false });
expect(user.sendMessage).to.be
.calledWith(recipient, { receiverMsg: msg, senderMsg: msg, save: false });
});
it('sends a push notification if user did not gift to self', async () => {
@@ -671,8 +677,8 @@ describe('payments/index', () => {
});
await api.buyGems(data);
let [recipientsMessageContent, sendersMessageContent] = ['en', 'en'].map((lang) => {
let messageContent = t('giftedGemsFull', {
const [recipientsMessageContent, sendersMessageContent] = ['en', 'en'].map(lang => {
const messageContent = t('giftedGemsFull', {
username: recipient.profile.name,
sender: user.profile.name,
gemAmount: data.gift.gems.amount,
@@ -681,7 +687,10 @@ describe('payments/index', () => {
return `\`${messageContent}\``;
});
expect(user.sendMessage).to.be.calledWith(recipient, { receiverMsg: recipientsMessageContent, senderMsg: sendersMessageContent, save: false });
expect(user.sendMessage).to.be.calledWith(
recipient,
{ receiverMsg: recipientsMessageContent, senderMsg: sendersMessageContent, save: false },
);
});
});
});
@@ -693,7 +702,7 @@ describe('payments/index', () => {
await api.addSubToGroupUser(user, group);
let updatedUser = await User.findById(user._id).exec();
const updatedUser = await User.findById(user._id).exec();
expect(updatedUser.purchased.plan.planId).to.eql('group_plan_auto');
expect(updatedUser.purchased.plan.customerId).to.eql('group-plan');
@@ -709,17 +718,17 @@ describe('payments/index', () => {
it('awards the Royal Purple Jackalope pet', async () => {
await api.addSubToGroupUser(user, group);
let updatedUser = await User.findById(user._id).exec();
const updatedUser = await User.findById(user._id).exec();
expect(updatedUser.items.pets['Jackalope-RoyalPurple']).to.eql(5);
});
it('saves previously unused Mystery Items and Hourglasses for an expired subscription', async () => {
let planExpirationDate = new Date();
const planExpirationDate = new Date();
planExpirationDate.setDate(planExpirationDate.getDate() - 2);
let mysteryItem = 'item';
let mysteryItems = [mysteryItem];
let consecutive = {
const mysteryItem = 'item';
const mysteryItems = [mysteryItem];
const consecutive = {
trinkets: 3,
};
@@ -735,7 +744,7 @@ describe('payments/index', () => {
await user.save();
await api.addSubToGroupUser(user, group);
let updatedUser = await User.findById(user._id).exec();
const updatedUser = await User.findById(user._id).exec();
expect(updatedUser.purchased.plan.mysteryItems[0]).to.eql(mysteryItem);
expect(updatedUser.purchased.plan.consecutive.trinkets).to.equal(consecutive.trinkets);

View File

@@ -5,8 +5,10 @@ import { model as User } from '../../../../../../website/server/models/user';
describe('checkout success', () => {
const subKey = 'basic_3mo';
let user, gift, customerId, paymentId;
let paypalPaymentExecuteStub, paymentBuyGemsStub, paymentsCreateSubscritionStub;
let user; let gift; let customerId; let
paymentId;
let paypalPaymentExecuteStub; let paymentBuyGemsStub; let
paymentsCreateSubscritionStub;
beforeEach(() => {
user = new User();
@@ -25,7 +27,9 @@ describe('checkout success', () => {
});
it('purchases gems', async () => {
await paypalPayments.checkoutSuccess({user, gift, paymentId, customerId});
await paypalPayments.checkoutSuccess({
user, gift, paymentId, customerId,
});
expect(paypalPaymentExecuteStub).to.be.calledOnce;
expect(paypalPaymentExecuteStub).to.be.calledWith(paymentId, { payer_id: customerId });
@@ -38,7 +42,7 @@ describe('checkout success', () => {
});
it('gifts gems', async () => {
let receivingUser = new User();
const receivingUser = new User();
await receivingUser.save();
gift = {
type: 'gems',
@@ -48,7 +52,9 @@ describe('checkout success', () => {
},
};
await paypalPayments.checkoutSuccess({user, gift, paymentId, customerId});
await paypalPayments.checkoutSuccess({
user, gift, paymentId, customerId,
});
expect(paypalPaymentExecuteStub).to.be.calledOnce;
expect(paypalPaymentExecuteStub).to.be.calledWith(paymentId, { payer_id: customerId });
@@ -62,7 +68,7 @@ describe('checkout success', () => {
});
it('gifts subscription', async () => {
let receivingUser = new User();
const receivingUser = new User();
await receivingUser.save();
gift = {
type: 'subscription',
@@ -72,7 +78,9 @@ describe('checkout success', () => {
},
};
await paypalPayments.checkoutSuccess({user, gift, paymentId, customerId});
await paypalPayments.checkoutSuccess({
user, gift, paymentId, customerId,
});
expect(paypalPaymentExecuteStub).to.be.calledOnce;
expect(paypalPaymentExecuteStub).to.be.calledWith(paymentId, { payer_id: customerId });

View File

@@ -6,7 +6,7 @@ import { model as User } from '../../../../../../website/server/models/user';
import common from '../../../../../../website/common';
const BASE_URL = nconf.get('BASE_URL');
const i18n = common.i18n;
const { i18n } = common;
describe('checkout', () => {
const subKey = 'basic_3mo';
@@ -53,7 +53,7 @@ describe('checkout', () => {
});
it('creates a link for gem purchases', async () => {
let link = await paypalPayments.checkout({user: new User()});
const link = await paypalPayments.checkout({ user: new User() });
expect(paypalPaymentCreateStub).to.be.calledOnce;
expect(paypalPaymentCreateStub).to.be.calledWith(getPaypalCreateOptions('Habitica Gems', 5.00));
@@ -61,9 +61,9 @@ describe('checkout', () => {
});
it('should error if gem amount is too low', async () => {
let receivingUser = new User();
const receivingUser = new User();
receivingUser.save();
let gift = {
const gift = {
type: 'gems',
gems: {
amount: 0,
@@ -71,7 +71,7 @@ describe('checkout', () => {
},
};
await expect(paypalPayments.checkout({gift}))
await expect(paypalPayments.checkout({ gift }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
message: 'Amount must be at least 1.',
@@ -80,10 +80,10 @@ describe('checkout', () => {
});
it('should error if the user cannot get gems', async () => {
let user = new User();
const user = new User();
sinon.stub(user, 'canGetGems').resolves(false);
await expect(paypalPayments.checkout({user})).to.eventually.be.rejected.and.to.eql({
await expect(paypalPayments.checkout({ user })).to.eventually.be.rejected.and.to.eql({
httpCode: 401,
message: i18n.t('groupPolicyCannotGetGems'),
name: 'NotAuthorized',
@@ -91,9 +91,9 @@ describe('checkout', () => {
});
it('creates a link for gifting gems', async () => {
let receivingUser = new User();
const receivingUser = new User();
await receivingUser.save();
let gift = {
const gift = {
type: 'gems',
uuid: receivingUser._id,
gems: {
@@ -101,7 +101,7 @@ describe('checkout', () => {
},
};
let link = await paypalPayments.checkout({gift});
const link = await paypalPayments.checkout({ gift });
expect(paypalPaymentCreateStub).to.be.calledOnce;
expect(paypalPaymentCreateStub).to.be.calledWith(getPaypalCreateOptions('Habitica Gems (Gift)', '4.00'));
@@ -109,9 +109,9 @@ describe('checkout', () => {
});
it('creates a link for gifting a subscription', async () => {
let receivingUser = new User();
const receivingUser = new User();
receivingUser.save();
let gift = {
const gift = {
type: 'subscription',
subscription: {
key: subKey,
@@ -119,7 +119,7 @@ describe('checkout', () => {
},
};
let link = await paypalPayments.checkout({gift});
const link = await paypalPayments.checkout({ gift });
expect(paypalPaymentCreateStub).to.be.calledOnce;
expect(paypalPaymentCreateStub).to.be.calledWith(getPaypalCreateOptions('mo. Habitica Subscription (Gift)', '15.00'));

View File

@@ -3,13 +3,15 @@ import paypalPayments from '../../../../../../website/server/libs/payments/paypa
import payments from '../../../../../../website/server/libs/payments/payments';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper.js';
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
describe('ipn', () => {
const subKey = 'basic_3mo';
let user, group, txn_type, userPaymentId, groupPaymentId;
let ipnVerifyAsyncStub, paymentCancelSubscriptionSpy;
let user; let group; let txn_type; let userPaymentId; let
groupPaymentId;
let ipnVerifyAsyncStub; let
paymentCancelSubscriptionSpy;
beforeEach(async () => {
txn_type = 'recurring_payment_profile_cancel';
@@ -38,16 +40,16 @@ describe('ipn', () => {
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
});
afterEach(function () {
afterEach(() => {
paypalPayments.ipnVerifyAsync.restore();
payments.cancelSubscription.restore();
});
it('should cancel a user subscription', async () => {
await paypalPayments.ipn({txn_type, recurring_payment_id: userPaymentId});
await paypalPayments.ipn({ txn_type, recurring_payment_id: userPaymentId });
expect(ipnVerifyAsyncStub).to.be.calledOnce;
expect(ipnVerifyAsyncStub).to.be.calledWith({txn_type, recurring_payment_id: userPaymentId});
expect(ipnVerifyAsyncStub).to.be.calledWith({ txn_type, recurring_payment_id: userPaymentId });
expect(paymentCancelSubscriptionSpy).to.be.calledOnce;
expect(paymentCancelSubscriptionSpy.args[0][0].user._id).to.eql(user._id);
@@ -55,10 +57,10 @@ describe('ipn', () => {
});
it('should cancel a group subscription', async () => {
await paypalPayments.ipn({txn_type, recurring_payment_id: groupPaymentId});
await paypalPayments.ipn({ txn_type, recurring_payment_id: groupPaymentId });
expect(ipnVerifyAsyncStub).to.be.calledOnce;
expect(ipnVerifyAsyncStub).to.be.calledWith({txn_type, recurring_payment_id: groupPaymentId});
expect(ipnVerifyAsyncStub).to.be.calledWith({ txn_type, recurring_payment_id: groupPaymentId });
expect(paymentCancelSubscriptionSpy).to.be.calledOnce;
expect(paymentCancelSubscriptionSpy).to.be.calledWith({ groupId: group._id, paymentMethod: 'Paypal' });

View File

@@ -3,17 +3,19 @@ import paypalPayments from '../../../../../../website/server/libs/payments/paypa
import payments from '../../../../../../website/server/libs/payments/payments';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper.js';
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import common from '../../../../../../website/common';
import { createNonLeaderGroupMember } from '../paymentHelpers';
const i18n = common.i18n;
const { i18n } = common;
describe('subscribeCancel', () => {
const subKey = 'basic_3mo';
let user, group, groupId, customerId, groupCustomerId, nextBillingDate;
let paymentCancelSubscriptionSpy, paypalBillingAgreementCancelStub, paypalBillingAgreementGetStub;
let user; let group; let groupId; let customerId; let groupCustomerId; let
nextBillingDate;
let paymentCancelSubscriptionSpy; let paypalBillingAgreementCancelStub; let
paypalBillingAgreementGetStub;
beforeEach(async () => {
customerId = 'customer-id';
@@ -49,7 +51,7 @@ describe('subscribeCancel', () => {
paymentCancelSubscriptionSpy = sinon.stub(payments, 'cancelSubscription').resolves({});
});
afterEach(function () {
afterEach(() => {
paypalPayments.paypalBillingAgreementGet.restore();
paypalPayments.paypalBillingAgreementCancel.restore();
payments.cancelSubscription.restore();
@@ -58,7 +60,7 @@ describe('subscribeCancel', () => {
it('should throw an error if we are missing a subscription', async () => {
user.purchased.plan.customerId = undefined;
await expect(paypalPayments.subscribeCancel({user}))
await expect(paypalPayments.subscribeCancel({ user }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
@@ -67,7 +69,7 @@ describe('subscribeCancel', () => {
});
it('should throw an error if group is not found', async () => {
await expect(paypalPayments.subscribeCancel({user, groupId: 'fake-id'}))
await expect(paypalPayments.subscribeCancel({ user, groupId: 'fake-id' }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 404,
name: 'NotFound',
@@ -76,9 +78,9 @@ describe('subscribeCancel', () => {
});
it('should throw an error if user is not group leader', async () => {
let nonLeader = await createNonLeaderGroupMember(group);
const nonLeader = await createNonLeaderGroupMember(group);
await expect(paypalPayments.subscribeCancel({user: nonLeader, groupId: group._id}))
await expect(paypalPayments.subscribeCancel({ user: nonLeader, groupId: group._id }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
@@ -87,7 +89,7 @@ describe('subscribeCancel', () => {
});
it('should cancel a user subscription', async () => {
await paypalPayments.subscribeCancel({user});
await paypalPayments.subscribeCancel({ user });
expect(paypalBillingAgreementGetStub).to.be.calledOnce;
expect(paypalBillingAgreementGetStub).to.be.calledWith(customerId);
@@ -105,7 +107,7 @@ describe('subscribeCancel', () => {
});
it('should cancel a group subscription', async () => {
await paypalPayments.subscribeCancel({user, groupId: group._id});
await paypalPayments.subscribeCancel({ user, groupId: group._id });
expect(paypalBillingAgreementGetStub).to.be.calledOnce;
expect(paypalBillingAgreementGetStub).to.be.calledWith(groupCustomerId);

View File

@@ -3,14 +3,16 @@ import paypalPayments from '../../../../../../website/server/libs/payments/paypa
import payments from '../../../../../../website/server/libs/payments/payments';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper.js';
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import common from '../../../../../../website/common';
describe('subscribeSuccess', () => {
const subKey = 'basic_3mo';
let user, group, block, groupId, token, headers, customerId;
let paypalBillingAgreementExecuteStub, paymentsCreateSubscritionStub;
let user; let group; let block; let groupId; let token; let headers; let
customerId;
let paypalBillingAgreementExecuteStub; let
paymentsCreateSubscritionStub;
beforeEach(async () => {
user = new User();
@@ -40,7 +42,9 @@ describe('subscribeSuccess', () => {
});
it('creates a user subscription', async () => {
await paypalPayments.subscribeSuccess({user, block, groupId, token, headers});
await paypalPayments.subscribeSuccess({
user, block, groupId, token, headers,
});
expect(paypalBillingAgreementExecuteStub).to.be.calledOnce;
expect(paypalBillingAgreementExecuteStub).to.be.calledWith(token, {});
@@ -59,7 +63,9 @@ describe('subscribeSuccess', () => {
it('create a group subscription', async () => {
groupId = group._id;
await paypalPayments.subscribeSuccess({user, block, groupId, token, headers});
await paypalPayments.subscribeSuccess({
user, block, groupId, token, headers,
});
expect(paypalBillingAgreementExecuteStub).to.be.calledOnce;
expect(paypalBillingAgreementExecuteStub).to.be.calledWith(token, {});

View File

@@ -6,16 +6,17 @@ import paypalPayments from '../../../../../../website/server/libs/payments/paypa
import { model as Coupon } from '../../../../../../website/server/models/coupon';
import common from '../../../../../../website/common';
const i18n = common.i18n;
const { i18n } = common;
describe('subscribe', () => {
const subKey = 'basic_3mo';
let coupon, sub, approvalHerf;
let coupon; let sub; let
approvalHerf;
let paypalBillingAgreementCreateStub;
beforeEach(() => {
approvalHerf = 'approvalHerf-test';
sub = Object.assign({}, common.content.subscriptionBlocks[subKey]);
sub = { ...common.content.subscriptionBlocks[subKey] };
paypalBillingAgreementCreateStub = sinon.stub(paypalPayments, 'paypalBillingAgreementCreate')
.resolves({
@@ -30,7 +31,7 @@ describe('subscribe', () => {
it('should throw an error when coupon code is missing', async () => {
sub.discount = 40;
await expect(paypalPayments.subscribe({sub, coupon}))
await expect(paypalPayments.subscribe({ sub, coupon }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
@@ -43,13 +44,13 @@ describe('subscribe', () => {
sub.key = 'google_6mo';
coupon = 'example-coupon';
let couponModel = new Coupon();
const couponModel = new Coupon();
couponModel.event = 'google_6mo';
await couponModel.save();
sinon.stub(cc, 'validate').returns('invalid');
await expect(paypalPayments.subscribe({sub, coupon}))
await expect(paypalPayments.subscribe({ sub, coupon }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
@@ -63,17 +64,17 @@ describe('subscribe', () => {
sub.key = 'google_6mo';
coupon = 'example-coupon';
let couponModel = new Coupon();
const couponModel = new Coupon();
couponModel.event = 'google_6mo';
let updatedCouponModel = await couponModel.save();
const updatedCouponModel = await couponModel.save();
sinon.stub(cc, 'validate').returns(updatedCouponModel._id);
let link = await paypalPayments.subscribe({sub, coupon});
const link = await paypalPayments.subscribe({ sub, coupon });
expect(link).to.eql(approvalHerf);
expect(paypalBillingAgreementCreateStub).to.be.calledOnce;
let billingPlanTitle = `Habitica Subscription ($${sub.price} every ${sub.months} months, recurring)`;
const billingPlanTitle = `Habitica Subscription ($${sub.price} every ${sub.months} months, recurring)`;
expect(paypalBillingAgreementCreateStub).to.be.calledWith({
name: billingPlanTitle,
description: billingPlanTitle,
@@ -92,11 +93,11 @@ describe('subscribe', () => {
it('creates a link for a subscription', async () => {
delete sub.discount;
let link = await paypalPayments.subscribe({sub, coupon});
const link = await paypalPayments.subscribe({ sub, coupon });
expect(link).to.eql(approvalHerf);
expect(paypalBillingAgreementCreateStub).to.be.calledOnce;
let billingPlanTitle = `Habitica Subscription ($${sub.price} every ${sub.months} months, recurring)`;
const billingPlanTitle = `Habitica Subscription ($${sub.price} every ${sub.months} months, recurring)`;
expect(paypalBillingAgreementCreateStub).to.be.calledWith({
name: billingPlanTitle,
description: billingPlanTitle,

View File

@@ -2,18 +2,19 @@ import stripeModule from 'stripe';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper.js';
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
const i18n = common.i18n;
const { i18n } = common;
describe('cancel subscription', () => {
const subKey = 'basic_3mo';
const stripe = stripeModule('test');
let user, groupId, group;
let user; let groupId; let
group;
beforeEach(async () => {
user = new User();
@@ -62,7 +63,7 @@ describe('cancel subscription', () => {
});
it('throws an error if user is not the group leader', async () => {
let nonLeader = new User();
const nonLeader = new User();
nonLeader.guilds.push(groupId);
await nonLeader.save();
@@ -78,7 +79,9 @@ describe('cancel subscription', () => {
});
describe('success', () => {
let stripeDeleteCustomerStub, paymentsCancelSubStub, stripeRetrieveStub, subscriptionId, currentPeriodEndTimeStamp;
let stripeDeleteCustomerStub; let paymentsCancelSubStub;
let stripeRetrieveStub; let subscriptionId; let
currentPeriodEndTimeStamp;
beforeEach(() => {
subscriptionId = 'subId';
@@ -89,7 +92,10 @@ describe('cancel subscription', () => {
stripeRetrieveStub = sinon.stub(stripe.customers, 'retrieve')
.resolves({
subscriptions: {
data: [{id: subscriptionId, current_period_end: currentPeriodEndTimeStamp}], // eslint-disable-line camelcase
data: [{
id: subscriptionId,
current_period_end: currentPeriodEndTimeStamp,
}], // eslint-disable-line camelcase
},
});
});

View File

@@ -3,19 +3,22 @@ import cc from 'coupon-code';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper.js';
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import { model as Coupon } from '../../../../../../website/server/models/coupon';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
const i18n = common.i18n;
const { i18n } = common;
describe('checkout with subscription', () => {
const subKey = 'basic_3mo';
const stripe = stripeModule('test');
let user, group, data, gift, sub, groupId, email, headers, coupon, customerIdResponse, subscriptionId, token;
let user; let group; let data; let gift; let sub;
let groupId; let email; let headers; let coupon;
let customerIdResponse; let subscriptionId; let
token;
let spy;
let stripeCreateCustomerSpy;
let stripePaymentsCreateSubSpy;
@@ -57,10 +60,10 @@ describe('checkout with subscription', () => {
spy.resolves;
stripeCreateCustomerSpy = sinon.stub(stripe.customers, 'create');
let stripCustomerResponse = {
const stripCustomerResponse = {
id: customerIdResponse,
subscriptions: {
data: [{id: subscriptionId}],
data: [{ id: subscriptionId }],
},
};
stripeCreateCustomerSpy.resolves(stripCustomerResponse);
@@ -72,7 +75,7 @@ describe('checkout with subscription', () => {
data.sub.quantity = 3;
});
afterEach(function () {
afterEach(() => {
stripe.subscriptions.update.restore();
stripe.customers.create.restore();
payments.createSubscription.restore();
@@ -120,7 +123,7 @@ describe('checkout with subscription', () => {
sub.key = 'google_6mo';
coupon = 'example-coupon';
let couponModel = new Coupon();
const couponModel = new Coupon();
couponModel.event = 'google_6mo';
await couponModel.save();
@@ -149,9 +152,9 @@ describe('checkout with subscription', () => {
sub.key = 'google_6mo';
coupon = 'example-coupon';
let couponModel = new Coupon();
const couponModel = new Coupon();
couponModel.event = 'google_6mo';
let updatedCouponModel = await couponModel.save();
const updatedCouponModel = await couponModel.save();
sinon.stub(cc, 'validate').returns(updatedCouponModel._id);

View File

@@ -5,13 +5,15 @@ import stripePayments from '../../../../../../website/server/libs/payments/strip
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
const i18n = common.i18n;
const { i18n } = common;
describe('checkout', () => {
const subKey = 'basic_3mo';
const stripe = stripeModule('test');
let stripeChargeStub, paymentBuyGemsStub, paymentCreateSubscritionStub;
let user, gift, groupId, email, headers, coupon, customerIdResponse, token;
let stripeChargeStub; let paymentBuyGemsStub; let
paymentCreateSubscritionStub;
let user; let gift; let groupId; let email; let headers; let coupon; let customerIdResponse; let
token;
beforeEach(() => {
user = new User();
@@ -23,7 +25,7 @@ describe('checkout', () => {
token = 'test-token';
customerIdResponse = 'example-customerIdResponse';
let stripCustomerResponse = {
const stripCustomerResponse = {
id: customerIdResponse,
};
stripeChargeStub = sinon.stub(stripe.charges, 'create').resolves(stripCustomerResponse);
@@ -54,7 +56,7 @@ describe('checkout', () => {
});
it('should error if gem amount is too low', async () => {
let receivingUser = new User();
const receivingUser = new User();
receivingUser.save();
gift = {
type: 'gems',
@@ -132,7 +134,7 @@ describe('checkout', () => {
});
it('should gift gems', async () => {
let receivingUser = new User();
const receivingUser = new User();
await receivingUser.save();
gift = {
type: 'gems',
@@ -169,7 +171,7 @@ describe('checkout', () => {
});
it('should gift a subscription', async () => {
let receivingUser = new User();
const receivingUser = new User();
receivingUser.save();
gift = {
type: 'subscription',

View File

@@ -2,17 +2,18 @@ import stripeModule from 'stripe';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper.js';
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import common from '../../../../../../website/common';
const i18n = common.i18n;
const { i18n } = common;
describe('edit subscription', () => {
const subKey = 'basic_3mo';
const stripe = stripeModule('test');
let user, groupId, group, token;
let user; let groupId; let group; let
token;
beforeEach(async () => {
user = new User();
@@ -76,7 +77,7 @@ describe('edit subscription', () => {
});
it('throws an error if user is not the group leader', async () => {
let nonLeader = new User();
const nonLeader = new User();
nonLeader.guilds.push(groupId);
await nonLeader.save();
@@ -93,13 +94,14 @@ describe('edit subscription', () => {
});
describe('success', () => {
let stripeListSubscriptionStub, stripeUpdateSubscriptionStub, subscriptionId;
let stripeListSubscriptionStub; let stripeUpdateSubscriptionStub; let
subscriptionId;
beforeEach(() => {
subscriptionId = 'subId';
stripeListSubscriptionStub = sinon.stub(stripe.subscriptions, 'list')
.resolves({
data: [{id: subscriptionId}],
data: [{ id: subscriptionId }],
});
stripeUpdateSubscriptionStub = sinon.stub(stripe.subscriptions, 'update').resolves({});
@@ -118,11 +120,13 @@ describe('edit subscription', () => {
}, stripe);
expect(stripeListSubscriptionStub).to.be.calledOnce;
expect(stripeListSubscriptionStub).to.be.calledWith({customer: user.purchased.plan.customerId});
expect(stripeListSubscriptionStub).to.be.calledWith({
customer: user.purchased.plan.customerId,
});
expect(stripeUpdateSubscriptionStub).to.be.calledOnce;
expect(stripeUpdateSubscriptionStub).to.be.calledWith(
subscriptionId,
{ card: token }
{ card: token },
);
});
@@ -134,11 +138,13 @@ describe('edit subscription', () => {
}, stripe);
expect(stripeListSubscriptionStub).to.be.calledOnce;
expect(stripeListSubscriptionStub).to.be.calledWith({customer: group.purchased.plan.customerId});
expect(stripeListSubscriptionStub).to.be.calledWith({
customer: group.purchased.plan.customerId,
});
expect(stripeUpdateSubscriptionStub).to.be.calledOnce;
expect(stripeUpdateSubscriptionStub).to.be.calledWith(
subscriptionId,
{ card: token }
{ card: token },
);
});
});

View File

@@ -1,25 +1,25 @@
import stripeModule from 'stripe';
import { v4 as uuid } from 'uuid';
import moment from 'moment';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper.js';
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
import logger from '../../../../../../website/server/libs/logger';
import { v4 as uuid } from 'uuid';
import moment from 'moment';
const i18n = common.i18n;
const { i18n } = common;
describe('Stripe - Webhooks', () => {
const stripe = stripeModule('test');
describe('all events', () => {
const eventType = 'account.updated';
const event = {id: 123};
const eventRetrieved = {type: eventType};
const event = { id: 123 };
const eventRetrieved = { type: eventType };
beforeEach(() => {
sinon.stub(stripe.events, 'retrieve').resolves(eventRetrieved);
@@ -33,7 +33,7 @@ describe('Stripe - Webhooks', () => {
it('logs an error if an unsupported webhook event is passed', async () => {
const error = new Error(`Missing handler for Stripe webhook ${eventType}`);
await stripePayments.handleWebhooks({requestBody: event}, stripe);
await stripePayments.handleWebhooks({ requestBody: event }, stripe);
expect(logger.error).to.have.been.calledOnce;
const calledWith = logger.error.getCall(0).args;
@@ -42,7 +42,7 @@ describe('Stripe - Webhooks', () => {
});
it('retrieves and validates the event from Stripe', async () => {
await stripePayments.handleWebhooks({requestBody: event}, stripe);
await stripePayments.handleWebhooks({ requestBody: event }, stripe);
expect(stripe.events.retrieve).to.have.been.calledOnce;
expect(stripe.events.retrieve).to.have.been.calledWith(event.id);
});
@@ -68,7 +68,7 @@ describe('Stripe - Webhooks', () => {
request: 123,
});
await stripePayments.handleWebhooks({requestBody: {}}, stripe);
await stripePayments.handleWebhooks({ requestBody: {} }, stripe);
expect(stripe.events.retrieve).to.have.been.calledOnce;
expect(stripe.customers.del).to.not.have.been.called;
@@ -93,11 +93,12 @@ describe('Stripe - Webhooks', () => {
request: null,
});
await expect(stripePayments.handleWebhooks({requestBody: {}}, stripe)).to.eventually.be.rejectedWith({
message: i18n.t('userNotFound'),
httpCode: 404,
name: 'NotFound',
});
await expect(stripePayments.handleWebhooks({ requestBody: {} }, stripe))
.to.eventually.be.rejectedWith({
message: i18n.t('userNotFound'),
httpCode: 404,
name: 'NotFound',
});
expect(stripe.customers.del).to.not.have.been.called;
expect(payments.cancelSubscription).to.not.have.been.called;
@@ -108,7 +109,7 @@ describe('Stripe - Webhooks', () => {
it('deletes the customer on Stripe and calls payments.cancelSubscription', async () => {
const customerId = '456';
let subscriber = new User();
const subscriber = new User();
subscriber.purchased.plan.customerId = customerId;
subscriber.purchased.plan.paymentMethod = 'Stripe';
await subscriber.save();
@@ -127,13 +128,13 @@ describe('Stripe - Webhooks', () => {
request: null,
});
await stripePayments.handleWebhooks({requestBody: {}}, stripe);
await stripePayments.handleWebhooks({ requestBody: {} }, stripe);
expect(stripe.customers.del).to.have.been.calledOnce;
expect(stripe.customers.del).to.have.been.calledWith(customerId);
expect(payments.cancelSubscription).to.have.been.calledOnce;
let cancelSubscriptionOpts = payments.cancelSubscription.lastCall.args[0];
const cancelSubscriptionOpts = payments.cancelSubscription.lastCall.args[0];
expect(cancelSubscriptionOpts.user._id).to.equal(subscriber._id);
expect(cancelSubscriptionOpts.paymentMethod).to.equal('Stripe');
expect(Math.round(moment(cancelSubscriptionOpts.nextBill).diff(new Date(), 'days', true))).to.equal(3);
@@ -160,11 +161,12 @@ describe('Stripe - Webhooks', () => {
request: null,
});
await expect(stripePayments.handleWebhooks({requestBody: {}}, stripe)).to.eventually.be.rejectedWith({
message: i18n.t('groupNotFound'),
httpCode: 404,
name: 'NotFound',
});
await expect(stripePayments.handleWebhooks({ requestBody: {} }, stripe))
.to.eventually.be.rejectedWith({
message: i18n.t('groupNotFound'),
httpCode: 404,
name: 'NotFound',
});
expect(stripe.customers.del).to.not.have.been.called;
expect(payments.cancelSubscription).to.not.have.been.called;
@@ -175,7 +177,7 @@ describe('Stripe - Webhooks', () => {
it('throws an error if the group leader is not found', async () => {
const customerId = 456;
let subscriber = generateGroup({
const subscriber = generateGroup({
name: 'test group',
type: 'guild',
privacy: 'public',
@@ -199,11 +201,12 @@ describe('Stripe - Webhooks', () => {
request: null,
});
await expect(stripePayments.handleWebhooks({requestBody: {}}, stripe)).to.eventually.be.rejectedWith({
message: i18n.t('userNotFound'),
httpCode: 404,
name: 'NotFound',
});
await expect(stripePayments.handleWebhooks({ requestBody: {} }, stripe))
.to.eventually.be.rejectedWith({
message: i18n.t('userNotFound'),
httpCode: 404,
name: 'NotFound',
});
expect(stripe.customers.del).to.not.have.been.called;
expect(payments.cancelSubscription).to.not.have.been.called;
@@ -214,10 +217,10 @@ describe('Stripe - Webhooks', () => {
it('deletes the customer on Stripe and calls payments.cancelSubscription', async () => {
const customerId = '456';
let leader = new User();
const leader = new User();
await leader.save();
let subscriber = generateGroup({
const subscriber = generateGroup({
name: 'test group',
type: 'guild',
privacy: 'public',
@@ -241,13 +244,13 @@ describe('Stripe - Webhooks', () => {
request: null,
});
await stripePayments.handleWebhooks({requestBody: {}}, stripe);
await stripePayments.handleWebhooks({ requestBody: {} }, stripe);
expect(stripe.customers.del).to.have.been.calledOnce;
expect(stripe.customers.del).to.have.been.calledWith(customerId);
expect(payments.cancelSubscription).to.have.been.calledOnce;
let cancelSubscriptionOpts = payments.cancelSubscription.lastCall.args[0];
const cancelSubscriptionOpts = payments.cancelSubscription.lastCall.args[0];
expect(cancelSubscriptionOpts.user._id).to.equal(leader._id);
expect(cancelSubscriptionOpts.paymentMethod).to.equal('Stripe');
expect(Math.round(moment(cancelSubscriptionOpts.nextBill).diff(new Date(), 'days', true))).to.equal(3);

View File

@@ -2,7 +2,7 @@ import stripeModule from 'stripe';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper.js';
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import { model as Group } from '../../../../../../website/server/models/group';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
@@ -10,9 +10,10 @@ import payments from '../../../../../../website/server/libs/payments/payments';
describe('Stripe - Upgrade Group Plan', () => {
const stripe = stripeModule('test');
let spy, data, user, group;
let spy; let data; let user; let
group;
beforeEach(async function () {
beforeEach(async () => {
user = new User();
user.profile.name = 'sender';
@@ -44,7 +45,7 @@ describe('Stripe - Upgrade Group Plan', () => {
stripePayments.setStripeApi(stripe);
});
afterEach(function () {
afterEach(() => {
stripe.subscriptions.update.restore();
});
@@ -52,7 +53,7 @@ describe('Stripe - Upgrade Group Plan', () => {
data.paymentMethod = 'Stripe';
await payments.createSubscription(data);
let updatedGroup = await Group.findById(group._id).exec();
const updatedGroup = await Group.findById(group._id).exec();
expect(updatedGroup.purchased.plan.quantity).to.eql(3);
updatedGroup.memberCount += 1;

View File

@@ -1,7 +1,7 @@
import { preenHistory } from '../../../../website/server/libs/preening';
import moment from 'moment';
import sinon from 'sinon'; // eslint-disable-line no-shadow
import { generateHistory } from '../../../helpers/api-unit.helper.js';
import { preenHistory } from '../../../../website/server/libs/preening';
import { generateHistory } from '../../../helpers/api-unit.helper';
describe('preenHistory', () => {
let clock;
@@ -13,47 +13,47 @@ describe('preenHistory', () => {
toFake: ['Date'],
});
});
afterEach(() => {
return clock.restore();
});
afterEach(() => clock.restore());
it('does not modify history if all entries are more recent than cutoff (free users)', () => {
let h = generateHistory(60);
const h = generateHistory(60);
expect(preenHistory(_.cloneDeep(h), false, 0)).to.eql(h);
});
it('does not modify history if all entries are more recent than cutoff (subscribers)', () => {
let h = generateHistory(365);
const h = generateHistory(365);
expect(preenHistory(_.cloneDeep(h), true, 0)).to.eql(h);
});
it('does aggregate data in monthly entries before cutoff (free users)', () => {
let h = generateHistory(81); // Jumps to July
let preened = preenHistory(_.cloneDeep(h), false, 0);
const h = generateHistory(81); // Jumps to July
const preened = preenHistory(_.cloneDeep(h), false, 0);
expect(preened.length).to.eql(62); // Keeps 60 days + 2 entries per august and july
});
it('does aggregate data in monthly entries before cutoff (subscribers)', () => {
let h = generateHistory(396); // Jumps to September 2012
let preened = preenHistory(_.cloneDeep(h), true, 0);
const h = generateHistory(396); // Jumps to September 2012
const preened = preenHistory(_.cloneDeep(h), true, 0);
expect(preened.length).to.eql(367); // Keeps 365 days + 2 entries per october and september
});
it('does aggregate data in monthly and yearly entries before cutoff (free users)', () => {
let h = generateHistory(731); // Jumps to October 21 2012
let preened = preenHistory(_.cloneDeep(h), false, 0);
expect(preened.length).to.eql(73); // Keeps 60 days + 11 montly entries and 2 yearly entry for 2011 and 2012
const h = generateHistory(731); // Jumps to October 21 2012
const preened = preenHistory(_.cloneDeep(h), false, 0);
// Keeps 60 days + 11 montly entries and 2 yearly entry for 2011 and 2012
expect(preened.length).to.eql(73);
});
it('does aggregate data in monthly and yearly entries before cutoff (subscribers)', () => {
let h = generateHistory(1031); // Jumps to October 21 2012
let preened = preenHistory(_.cloneDeep(h), true, 0);
expect(preened.length).to.eql(380); // Keeps 365 days + 13 montly entries and 2 yearly entries for 2011 and 2010
const h = generateHistory(1031); // Jumps to October 21 2012
const preened = preenHistory(_.cloneDeep(h), true, 0);
// Keeps 365 days + 13 montly entries and 2 yearly entries for 2011 and 2010
expect(preened.length).to.eql(380);
});
it('correctly aggregates values', () => {
let h = generateHistory(63); // Compress last 3 days
let preened = preenHistory(_.cloneDeep(h), false, 0);
const h = generateHistory(63); // Compress last 3 days
const preened = preenHistory(_.cloneDeep(h), false, 0);
expect(preened[0].value).to.eql((61 + 62 + 63) / 3);
});
});

View File

@@ -1,19 +1,19 @@
import { model as User } from '../../../../website/server/models/user';
import requireAgain from 'require-again';
import apn from 'apn/mock';
import nconf from 'nconf';
import gcmLib from 'node-gcm'; // works with FCM notifications too
import { model as User } from '../../../../website/server/models/user';
describe('pushNotifications', () => {
let user;
let sendPushNotification;
let pathToPushNotifications = '../../../../website/server/libs/pushNotifications';
const pathToPushNotifications = '../../../../website/server/libs/pushNotifications';
let fcmSendSpy;
let apnSendSpy;
let identifier = 'identifier';
let title = 'title';
let message = 'message';
const identifier = 'identifier';
const title = 'title';
const message = 'message';
beforeEach(() => {
user = new User();
@@ -93,7 +93,7 @@ describe('pushNotifications', () => {
regId: '123',
});
let details = {
const details = {
identifier,
title,
message,

View File

@@ -1,7 +1,7 @@
import setupNconf from '../../../../website/server/libs/setupNconf';
import path from 'path';
import nconf from 'nconf';
import setupNconf from '../../../../website/server/libs/setupNconf';
describe('setupNconf', () => {
beforeEach(() => {
@@ -21,7 +21,7 @@ describe('setupNconf', () => {
expect(nconf.env).to.be.calledOnce;
expect(nconf.file).to.be.calledOnce;
let regexString = `\\${path.sep}config.json$`;
const regexString = `\\${path.sep}config.json$`;
expect(nconf.file).to.be.calledWithMatch('user', new RegExp(regexString));
});

View File

@@ -1,11 +1,11 @@
/* eslint-disable camelcase */
import { IncomingWebhook } from '@slack/client';
import requireAgain from 'require-again';
import nconf from 'nconf';
import moment from 'moment';
import * as slack from '../../../../website/server/libs/slack';
import logger from '../../../../website/server/libs/logger';
import { TAVERN_ID } from '../../../../website/server/models/group';
import nconf from 'nconf';
import moment from 'moment';
describe('slack', () => {
describe('sendFlagNotification', () => {
@@ -113,7 +113,7 @@ describe('slack', () => {
it('noops if no flagging url is provided', () => {
sandbox.stub(nconf, 'get').withArgs('SLACK_FLAGGING_URL').returns('');
sandbox.stub(logger, 'error');
let reRequiredSlack = requireAgain('../../../../website/server/libs/slack');
const reRequiredSlack = requireAgain('../../../../website/server/libs/slack');
expect(logger.error).to.be.calledOnce;

View File

@@ -9,11 +9,12 @@ import {
generateUser,
generateGroup,
generateChallenge,
} from '../../../helpers/api-unit.helper.js';
} from '../../../helpers/api-unit.helper';
describe('taskManager', () => {
let user, group, challenge;
let testHabit = {
let user; let group; let
challenge;
const testHabit = {
text: 'test habit',
type: 'habit',
up: false,
@@ -47,8 +48,8 @@ describe('taskManager', () => {
req.body = testHabit;
res.t = i18n.t;
let newTasks = await createTasks(req, res, {user});
let newTask = newTasks[0];
const newTasks = await createTasks(req, res, { user });
const newTask = newTasks[0];
expect(newTask.text).to.equal(testHabit.text);
expect(newTask.type).to.equal(testHabit.type);
@@ -61,15 +62,15 @@ describe('taskManager', () => {
req.body = testHabit;
res.t = i18n.t;
await createTasks(req, res, {user});
await createTasks(req, res, { user });
req.body = {};
req.query = {
type: 'habits',
};
let tasks = await getTasks(req, res, {user});
let task = tasks[0];
const tasks = await getTasks(req, res, { user });
const task = tasks[0];
expect(task.text).to.equal(testHabit.text);
expect(task.type).to.equal(testHabit.type);
@@ -82,8 +83,8 @@ describe('taskManager', () => {
req.body = testHabit;
res.t = i18n.t;
let newTasks = await createTasks(req, res, {user, group});
let newTask = newTasks[0];
const newTasks = await createTasks(req, res, { user, group });
const newTask = newTasks[0];
expect(newTask.text).to.equal(testHabit.text);
expect(newTask.type).to.equal(testHabit.type);
@@ -97,15 +98,15 @@ describe('taskManager', () => {
req.body = testHabit;
res.t = i18n.t;
await createTasks(req, res, {user, group});
await createTasks(req, res, { user, group });
req.body = {};
req.query = {
type: 'habits',
};
let tasks = await getTasks(req, res, {user, group});
let task = tasks[0];
const tasks = await getTasks(req, res, { user, group });
const task = tasks[0];
expect(task.text).to.equal(testHabit.text);
expect(task.type).to.equal(testHabit.type);
@@ -119,8 +120,8 @@ describe('taskManager', () => {
req.body = testHabit;
res.t = i18n.t;
let newTasks = await createTasks(req, res, {user, challenge});
let newTask = newTasks[0];
const newTasks = await createTasks(req, res, { user, challenge });
const newTask = newTasks[0];
expect(newTask.text).to.equal(testHabit.text);
expect(newTask.type).to.equal(testHabit.type);
@@ -134,15 +135,15 @@ describe('taskManager', () => {
req.body = testHabit;
res.t = i18n.t;
await createTasks(req, res, {user, challenge});
await createTasks(req, res, { user, challenge });
req.body = {};
req.query = {
type: 'habits',
};
let tasks = await getTasks(req, res, {user, challenge});
let task = tasks[0];
const tasks = await getTasks(req, res, { user, challenge });
const task = tasks[0];
expect(task.text).to.equal(testHabit.text);
expect(task.type).to.equal(testHabit.type);
@@ -156,9 +157,9 @@ describe('taskManager', () => {
req.body = testHabit;
res.t = i18n.t;
let tasks = await createTasks(req, res, {user, challenge});
const tasks = await createTasks(req, res, { user, challenge });
let syncableTask = syncableAttrs(tasks[0]);
const syncableTask = syncableAttrs(tasks[0]);
expect(syncableTask._id).to.not.exist;
expect(syncableTask.userId).to.not.exist;
@@ -172,7 +173,7 @@ describe('taskManager', () => {
});
it('moves tasks to a specified position', async () => {
let order = ['task-id-1', 'task-id-2'];
const order = ['task-id-1', 'task-id-2'];
moveTask(order, 'task-id-2', 0);
@@ -180,7 +181,7 @@ describe('taskManager', () => {
});
it('moves tasks to a specified position out of length', async () => {
let order = ['task-id-1'];
const order = ['task-id-1'];
moveTask(order, 'task-id-2', 2);

View File

@@ -12,11 +12,13 @@ import {
} from '../../../../website/server/models/user';
import {
generateUser,
} from '../../../helpers/api-unit.helper.js';
import { defer } from '../../../helpers/api-unit.helper';
defer,
} from '../../../helpers/api-unit.helper';
describe('webhooks', () => {
let webhooks, user;
let webhooks; let
user;
beforeEach(() => {
sandbox.stub(got, 'post').returns(defer().promise);
@@ -72,7 +74,7 @@ describe('webhooks', () => {
describe('WebhookSender', () => {
it('creates a new WebhookSender object', () => {
let sendWebhook = new WebhookSender({
const sendWebhook = new WebhookSender({
type: 'custom',
});
@@ -82,13 +84,15 @@ describe('webhooks', () => {
it('provides default function for data transformation', () => {
sandbox.spy(WebhookSender, 'defaultTransformData');
let sendWebhook = new WebhookSender({
const sendWebhook = new WebhookSender({
type: 'custom',
});
let body = { foo: 'bar' };
const body = { foo: 'bar' };
user.webhooks = [{id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom'}];
user.webhooks = [{
id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom',
}];
sendWebhook.send(user, body);
expect(WebhookSender.defaultTransformData).to.be.calledOnce;
@@ -100,14 +104,16 @@ describe('webhooks', () => {
});
it('adds default data (user and webhookType) to the body', () => {
let sendWebhook = new WebhookSender({
const sendWebhook = new WebhookSender({
type: 'custom',
});
sandbox.spy(sendWebhook, 'attachDefaultData');
let body = { foo: 'bar' };
const body = { foo: 'bar' };
user.webhooks = [{id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom'}];
user.webhooks = [{
id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom',
}];
sendWebhook.send(user, body);
expect(sendWebhook.attachDefaultData).to.be.calledOnce;
@@ -118,25 +124,27 @@ describe('webhooks', () => {
expect(body).to.eql({
foo: 'bar',
user: {_id: user._id},
user: { _id: user._id },
webhookType: 'custom',
});
});
it('can pass in a data transformation function', () => {
sandbox.spy(WebhookSender, 'defaultTransformData');
let sendWebhook = new WebhookSender({
const sendWebhook = new WebhookSender({
type: 'custom',
transformData (data) {
let dataToSend = Object.assign({baz: 'biz'}, data);
const dataToSend = { baz: 'biz', ...data };
return dataToSend;
},
});
let body = { foo: 'bar' };
const body = { foo: 'bar' };
user.webhooks = [{id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom'}];
user.webhooks = [{
id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom',
}];
sendWebhook.send(user, body);
expect(WebhookSender.defaultTransformData).to.not.be.called;
@@ -152,13 +160,15 @@ describe('webhooks', () => {
it('provides a default filter function', () => {
sandbox.spy(WebhookSender, 'defaultWebhookFilter');
let sendWebhook = new WebhookSender({
const sendWebhook = new WebhookSender({
type: 'custom',
});
let body = { foo: 'bar' };
const body = { foo: 'bar' };
user.webhooks = [{id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom'}];
user.webhooks = [{
id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom',
}];
sendWebhook.send(user, body);
expect(WebhookSender.defaultWebhookFilter).to.be.calledOnce;
@@ -166,16 +176,18 @@ describe('webhooks', () => {
it('can pass in a webhook filter function', () => {
sandbox.spy(WebhookSender, 'defaultWebhookFilter');
let sendWebhook = new WebhookSender({
const sendWebhook = new WebhookSender({
type: 'custom',
webhookFilter (hook) {
return hook.url !== 'http://custom-url.com';
},
});
let body = { foo: 'bar' };
const body = { foo: 'bar' };
user.webhooks = [{id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom'}];
user.webhooks = [{
id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom',
}];
sendWebhook.send(user, body);
expect(WebhookSender.defaultWebhookFilter).to.not.be.called;
@@ -184,18 +196,22 @@ describe('webhooks', () => {
it('can pass in a webhook filter function that filters on data', () => {
sandbox.spy(WebhookSender, 'defaultWebhookFilter');
let sendWebhook = new WebhookSender({
const sendWebhook = new WebhookSender({
type: 'custom',
webhookFilter (hook, data) {
return hook.options.foo === data.foo;
},
});
let body = { foo: 'bar' };
const body = { foo: 'bar' };
user.webhooks = [
{ id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom', options: { foo: 'bar' }},
{ id: 'other-custom-webhook', url: 'http://other-custom-url.com', enabled: true, type: 'custom', options: { foo: 'foo' }},
{
id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom', options: { foo: 'bar' },
},
{
id: 'other-custom-webhook', url: 'http://other-custom-url.com', enabled: true, type: 'custom', options: { foo: 'foo' },
},
];
sendWebhook.send(user, body);
@@ -204,41 +220,49 @@ describe('webhooks', () => {
});
it('ignores disabled webhooks', () => {
let sendWebhook = new WebhookSender({
const sendWebhook = new WebhookSender({
type: 'custom',
});
let body = { foo: 'bar' };
const body = { foo: 'bar' };
user.webhooks = [{id: 'custom-webhook', url: 'http://custom-url.com', enabled: false, type: 'custom'}];
user.webhooks = [{
id: 'custom-webhook', url: 'http://custom-url.com', enabled: false, type: 'custom',
}];
sendWebhook.send(user, body);
expect(got.post).to.not.be.called;
});
it('ignores webhooks with invalid urls', () => {
let sendWebhook = new WebhookSender({
const sendWebhook = new WebhookSender({
type: 'custom',
});
let body = { foo: 'bar' };
const body = { foo: 'bar' };
user.webhooks = [{id: 'custom-webhook', url: 'httxp://custom-url!!!', enabled: true, type: 'custom'}];
user.webhooks = [{
id: 'custom-webhook', url: 'httxp://custom-url!!!', enabled: true, type: 'custom',
}];
sendWebhook.send(user, body);
expect(got.post).to.not.be.called;
});
it('ignores webhooks of other types', () => {
let sendWebhook = new WebhookSender({
const sendWebhook = new WebhookSender({
type: 'custom',
});
let body = { foo: 'bar' };
const body = { foo: 'bar' };
user.webhooks = [
{ id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom'},
{ id: 'other-webhook', url: 'http://other-url.com', enabled: true, type: 'other'},
{
id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom',
},
{
id: 'other-webhook', url: 'http://other-url.com', enabled: true, type: 'other',
},
];
sendWebhook.send(user, body);
@@ -250,14 +274,16 @@ describe('webhooks', () => {
});
it('sends every type of activity to global webhooks', () => {
let sendWebhook = new WebhookSender({
const sendWebhook = new WebhookSender({
type: 'custom',
});
let body = { foo: 'bar' };
const body = { foo: 'bar' };
user.webhooks = [
{ id: 'global-webhook', url: 'http://custom-url.com', enabled: true, type: 'globalActivity'},
{
id: 'global-webhook', url: 'http://custom-url.com', enabled: true, type: 'globalActivity',
},
];
sendWebhook.send(user, body);
@@ -269,15 +295,19 @@ describe('webhooks', () => {
});
it('sends multiple webhooks of the same type', () => {
let sendWebhook = new WebhookSender({
const sendWebhook = new WebhookSender({
type: 'custom',
});
let body = { foo: 'bar' };
const body = { foo: 'bar' };
user.webhooks = [
{ id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom'},
{ id: 'other-custom-webhook', url: 'http://other-url.com', enabled: true, type: 'custom'},
{
id: 'custom-webhook', url: 'http://custom-url.com', enabled: true, type: 'custom',
},
{
id: 'other-custom-webhook', url: 'http://other-url.com', enabled: true, type: 'custom',
},
];
sendWebhook.send(user, body);
@@ -299,7 +329,7 @@ describe('webhooks', () => {
beforeEach(() => {
data = {
user: {
_tmp: {foo: 'bar'},
_tmp: { foo: 'bar' },
stats: {
lvl: 5,
int: 10,
@@ -317,11 +347,12 @@ describe('webhooks', () => {
delta: 176,
};
let mockStats = Object.assign({
const mockStats = {
maxHealth: 50,
maxMP: 103,
toNextLevel: 40,
}, data.user.stats);
...data.user.stats,
};
delete mockStats.toJSON;
sandbox.stub(User, 'addComputedStatsToJSONObj').returns(mockStats);
@@ -338,7 +369,7 @@ describe('webhooks', () => {
webhookType: 'taskActivity',
user: {
_id: user._id,
_tmp: {foo: 'bar'},
_tmp: { foo: 'bar' },
stats: {
lvl: 5,
int: 10,
@@ -376,7 +407,7 @@ describe('webhooks', () => {
webhookType: 'taskActivity',
user: {
_id: user._id,
_tmp: {foo: 'bar'},
_tmp: { foo: 'bar' },
stats: {
lvl: 5,
int: 10,
@@ -416,7 +447,7 @@ describe('webhooks', () => {
};
});
['created', 'updated', 'deleted'].forEach((type) => {
['created', 'updated', 'deleted'].forEach(type => {
it(`sends ${type} tasks`, () => {
data.type = type;
@@ -498,7 +529,7 @@ describe('webhooks', () => {
};
});
['petHatched', 'mountRaised', 'leveledUp'].forEach((type) => {
['petHatched', 'mountRaised', 'leveledUp'].forEach(type => {
it(`sends ${type} webhooks`, () => {
data.type = type;
@@ -545,7 +576,7 @@ describe('webhooks', () => {
};
});
['questStarted', 'questFinised'].forEach((type) => {
['questStarted', 'questFinised'].forEach(type => {
it(`sends ${type} webhooks`, () => {
data.type = type;
@@ -584,7 +615,7 @@ describe('webhooks', () => {
describe('groupChatReceivedWebhook', () => {
it('sends chat data', () => {
let data = {
const data = {
group: {
id: 'group-id',
name: 'some group',
@@ -619,7 +650,7 @@ describe('webhooks', () => {
});
it('does not send chat data for group if not selected', () => {
let data = {
const data = {
group: {
id: 'not-group-id',
name: 'some group',

View File

@@ -1,16 +1,17 @@
/* eslint-disable global-require */
import nconf from 'nconf';
import requireAgain from 'require-again';
import {
generateRes,
generateReq,
generateNext,
} from '../../../helpers/api-unit.helper';
import * as analyticsService from '../../../../website/server/libs/analyticsService';
import nconf from 'nconf';
import requireAgain from 'require-again';
describe('analytics middleware', () => {
let res, req, next;
let pathToAnalyticsMiddleware = '../../../../website/server/middlewares/analytics';
let res; let req; let
next;
const pathToAnalyticsMiddleware = '../../../../website/server/middlewares/analytics';
beforeEach(() => {
res = generateRes();
@@ -19,7 +20,7 @@ describe('analytics middleware', () => {
});
it('attaches analytics object res.locals', () => {
let attachAnalytics = requireAgain(pathToAnalyticsMiddleware).default;
const attachAnalytics = requireAgain(pathToAnalyticsMiddleware).default;
attachAnalytics(req, res, next);
@@ -28,7 +29,7 @@ describe('analytics middleware', () => {
it('attaches stubbed methods for non-prod environments', () => {
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(false);
let attachAnalytics = requireAgain(pathToAnalyticsMiddleware).default;
const attachAnalytics = requireAgain(pathToAnalyticsMiddleware).default;
attachAnalytics(req, res, next);
@@ -39,7 +40,7 @@ describe('analytics middleware', () => {
it('attaches real methods for prod environments', () => {
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(true);
let attachAnalytics = requireAgain(pathToAnalyticsMiddleware).default;
const attachAnalytics = requireAgain(pathToAnalyticsMiddleware).default;
attachAnalytics(req, res, next);

View File

@@ -5,7 +5,8 @@ import {
import { authWithHeaders as authWithHeadersFactory } from '../../../../website/server/middlewares/auth';
describe('auth middleware', () => {
let res, req, user;
let res; let req; let
user;
beforeEach(async () => {
res = generateRes();
@@ -14,7 +15,7 @@ describe('auth middleware', () => {
});
describe('auth with headers', () => {
it('allows to specify a list of user field that we do not want to load', (done) => {
it('allows to specify a list of user field that we do not want to load', done => {
const authWithHeaders = authWithHeadersFactory({
userFieldsToExclude: ['items'],
});
@@ -22,18 +23,18 @@ describe('auth middleware', () => {
req.headers['x-api-user'] = user._id;
req.headers['x-api-key'] = user.apiToken;
authWithHeaders(req, res, (err) => {
authWithHeaders(req, res, err => {
if (err) return done(err);
const userToJSON = res.locals.user.toJSON();
expect(userToJSON.items).to.not.exist;
expect(userToJSON.auth).to.exist;
done();
return done();
});
});
it('makes sure some fields are always included', (done) => {
it('makes sure some fields are always included', done => {
const authWithHeaders = authWithHeadersFactory({
userFieldsToExclude: [
'items', 'auth.timestamps',
@@ -44,7 +45,7 @@ describe('auth middleware', () => {
req.headers['x-api-user'] = user._id;
req.headers['x-api-key'] = user.apiToken;
authWithHeaders(req, res, (err) => {
authWithHeaders(req, res, err => {
if (err) return done(err);
const userToJSON = res.locals.user.toJSON();
@@ -56,7 +57,7 @@ describe('auth middleware', () => {
expect(userToJSON._id).to.exist;
expect(userToJSON.flags).to.exist;
done();
return done();
});
});
});

View File

@@ -7,7 +7,8 @@ import {
import cors from '../../../../website/server/middlewares/cors';
describe('cors middleware', () => {
let res, req, next;
let res; let req; let
next;
beforeEach(() => {
req = generateReq();

View File

@@ -1,3 +1,5 @@
import moment from 'moment';
import { v4 as generateUUID } from 'uuid';
import {
generateRes,
generateReq,
@@ -5,22 +7,21 @@ import {
generateDaily,
} from '../../../helpers/api-unit.helper';
import cronMiddleware from '../../../../website/server/middlewares/cron';
import moment from 'moment';
import { model as User } from '../../../../website/server/models/user';
import { model as Group } from '../../../../website/server/models/group';
import * as Tasks from '../../../../website/server/models/task';
import * as analyticsService from '../../../../website/server/libs/analyticsService';
import * as cronLib from '../../../../website/server/libs/cron';
import { v4 as generateUUID } from 'uuid';
const CRON_TIMEOUT_WAIT = new Date(60 * 60 * 1000).getTime();
const CRON_TIMEOUT_UNIT = new Date(60 * 1000).getTime();
describe('cron middleware', () => {
let res, req;
let res; let
req;
let user;
beforeEach((done) => {
beforeEach(done => {
res = generateRes();
req = generateReq();
user = new User({
@@ -48,33 +49,35 @@ describe('cron middleware', () => {
sandbox.restore();
});
it('calls next when user is not attached', (done) => {
it('calls next when user is not attached', done => {
res.locals.user = null;
cronMiddleware(req, res, done);
});
it('calls next when days have not been missed', (done) => {
it('calls next when days have not been missed', done => {
cronMiddleware(req, res, done);
});
it('should clear todos older than 30 days for free users', async () => {
user.lastCron = moment(new Date()).subtract({days: 2});
let task = generateTodo(user);
task.dateCompleted = moment(new Date()).subtract({days: 31});
user.lastCron = moment(new Date()).subtract({ days: 2 });
const task = generateTodo(user);
task.dateCompleted = moment(new Date()).subtract({ days: 31 });
task.completed = true;
await task.save();
await user.save();
await new Promise((resolve, reject) => {
cronMiddleware(req, res, (err) => {
cronMiddleware(req, res, err => {
if (err) return reject(err);
Tasks.Task.findOne({_id: task}, function (secondErr, taskFound) {
Tasks.Task.findOne({ _id: task }, (secondErr, taskFound) => {
if (secondErr) return reject(err);
expect(secondErr).to.not.exist;
expect(taskFound).to.not.exist;
resolve();
return resolve();
});
return null;
});
});
});
@@ -82,22 +85,23 @@ describe('cron middleware', () => {
it('should not clear todos older than 30 days for subscribed users', async () => {
user.purchased.plan.customerId = 'subscribedId';
user.purchased.plan.dateUpdated = moment('012013', 'MMYYYY');
user.lastCron = moment(new Date()).subtract({days: 2});
let task = generateTodo(user);
task.dateCompleted = moment(new Date()).subtract({days: 31});
user.lastCron = moment(new Date()).subtract({ days: 2 });
const task = generateTodo(user);
task.dateCompleted = moment(new Date()).subtract({ days: 31 });
task.completed = true;
await task.save();
await user.save();
await new Promise((resolve, reject) => {
cronMiddleware(req, res, (err) => {
cronMiddleware(req, res, err => {
if (err) return reject(err);
Tasks.Task.findOne({_id: task}, function (secondErr, taskFound) {
Tasks.Task.findOne({ _id: task }, (secondErr, taskFound) => {
if (secondErr) return reject(secondErr);
expect(secondErr).to.not.exist;
expect(taskFound).to.exist;
resolve();
return resolve();
});
return null;
});
});
});
@@ -105,105 +109,106 @@ describe('cron middleware', () => {
it('should clear todos older than 90 days for subscribed users', async () => {
user.purchased.plan.customerId = 'subscribedId';
user.purchased.plan.dateUpdated = moment('012013', 'MMYYYY');
user.lastCron = moment(new Date()).subtract({days: 2});
user.lastCron = moment(new Date()).subtract({ days: 2 });
let task = generateTodo(user);
task.dateCompleted = moment(new Date()).subtract({days: 91});
const task = generateTodo(user);
task.dateCompleted = moment(new Date()).subtract({ days: 91 });
task.completed = true;
await task.save();
await user.save();
await new Promise((resolve, reject) => {
cronMiddleware(req, res, (err) => {
cronMiddleware(req, res, err => {
if (err) return reject(err);
Tasks.Task.findOne({_id: task}, function (secondErr, taskFound) {
Tasks.Task.findOne({ _id: task }, (secondErr, taskFound) => {
if (secondErr) return reject(secondErr);
expect(secondErr).to.not.exist;
expect(taskFound).to.not.exist;
resolve();
return resolve();
});
return null;
});
});
});
it('should call next if user was not modified after cron', async () => {
let hpBefore = user.stats.hp;
user.lastCron = moment(new Date()).subtract({days: 2});
const hpBefore = user.stats.hp;
user.lastCron = moment(new Date()).subtract({ days: 2 });
await user.save();
await new Promise((resolve, reject) => {
cronMiddleware(req, res, (err) => {
cronMiddleware(req, res, err => {
if (err) return reject(err);
expect(hpBefore).to.equal(user.stats.hp);
resolve();
return resolve();
});
});
});
it('updates user.auth.timestamps.loggedin and lastCron', async () => {
user.lastCron = moment(new Date()).subtract({days: 2});
let now = new Date();
user.lastCron = moment(new Date()).subtract({ days: 2 });
const now = new Date();
await user.save();
await new Promise((resolve, reject) => {
cronMiddleware(req, res, (err) => {
cronMiddleware(req, res, err => {
if (err) return reject(err);
expect(moment(now).isSame(user.lastCron, 'day'));
expect(moment(now).isSame(user.auth.timestamps.loggedin, 'day'));
resolve();
return resolve();
});
});
});
it('does damage for missing dailies', async () => {
let hpBefore = user.stats.hp;
user.lastCron = moment(new Date()).subtract({days: 2});
let daily = generateDaily(user);
daily.startDate = moment(new Date()).subtract({days: 2});
const hpBefore = user.stats.hp;
user.lastCron = moment(new Date()).subtract({ days: 2 });
const daily = generateDaily(user);
daily.startDate = moment(new Date()).subtract({ days: 2 });
await daily.save();
await user.save();
await new Promise((resolve, reject) => {
cronMiddleware(req, res, (err) => {
cronMiddleware(req, res, err => {
if (err) return reject(err);
User.findOne({_id: user._id}, function (secondErr, updatedUser) {
return User.findOne({ _id: user._id }, (secondErr, updatedUser) => {
if (secondErr) return reject(secondErr);
expect(updatedUser.stats.hp).to.be.lessThan(hpBefore);
resolve();
return resolve();
});
});
});
});
it('updates tasks', async () => {
user.lastCron = moment(new Date()).subtract({days: 2});
let todo = generateTodo(user);
let todoValueBefore = todo.value;
user.lastCron = moment(new Date()).subtract({ days: 2 });
const todo = generateTodo(user);
const todoValueBefore = todo.value;
await Promise.all([todo.save(), user.save()]);
await new Promise((resolve, reject) => {
cronMiddleware(req, res, (err) => {
cronMiddleware(req, res, err => {
if (err) return reject(err);
Tasks.Task.findOne({_id: todo._id}, function (secondErr, todoFound) {
return Tasks.Task.findOne({ _id: todo._id }, (secondErr, todoFound) => {
if (secondErr) return reject(secondErr);
expect(todoFound.value).to.be.lessThan(todoValueBefore);
resolve();
return resolve();
});
});
});
});
it('applies quest progress', async () => {
let hpBefore = user.stats.hp;
user.lastCron = moment(new Date()).subtract({days: 2});
let daily = generateDaily(user);
daily.startDate = moment(new Date()).subtract({days: 2});
const hpBefore = user.stats.hp;
user.lastCron = moment(new Date()).subtract({ days: 2 });
const daily = generateDaily(user);
daily.startDate = moment(new Date()).subtract({ days: 2 });
await daily.save();
let questKey = 'dilatory';
const questKey = 'dilatory';
user.party.quest.key = questKey;
let party = new Group({
const party = new Group({
type: 'party',
name: generateUUID(),
leader: user._id,
@@ -218,22 +223,22 @@ describe('cron middleware', () => {
party.startQuest(user);
await new Promise((resolve, reject) => {
cronMiddleware(req, res, (err) => {
cronMiddleware(req, res, err => {
if (err) return reject(err);
User.findOne({_id: user._id}, function (secondErr, updatedUser) {
return User.findOne({ _id: user._id }, (secondErr, updatedUser) => {
if (secondErr) return reject(secondErr);
expect(updatedUser.stats.hp).to.be.lessThan(hpBefore);
resolve();
return resolve();
});
});
});
});
it('recovers from failed cron and does not error when user is already cronning', async () => {
user.lastCron = moment(new Date()).subtract({days: 2});
user.lastCron = moment(new Date()).subtract({ days: 2 });
await user.save();
let updatedUser = user.toObject();
const updatedUser = user.toObject();
updatedUser.nMatched = 0;
sandbox.spy(cronLib, 'recoverCron');
@@ -242,8 +247,8 @@ describe('cron middleware', () => {
.withArgs({
_id: user._id,
$or: [
{_cronSignature: 'NOT_RUNNING'},
{_cronSignature: {$lt: sinon.match.number}},
{ _cronSignature: 'NOT_RUNNING' },
{ _cronSignature: { $lt: sinon.match.number } },
],
})
.returns({
@@ -253,18 +258,18 @@ describe('cron middleware', () => {
});
await new Promise((resolve, reject) => {
cronMiddleware(req, res, (err) => {
cronMiddleware(req, res, err => {
if (err) return reject(err);
expect(cronLib.recoverCron).to.be.calledOnce;
resolve();
return resolve();
});
});
});
it('cronSignature less than an hour ago should error', async () => {
user.lastCron = moment(new Date()).subtract({days: 2});
let now = new Date();
user.lastCron = moment(new Date()).subtract({ days: 2 });
const now = new Date();
await User.update({
_id: user._id,
}, {
@@ -273,20 +278,20 @@ describe('cron middleware', () => {
},
}).exec();
await user.save();
let expectedErrMessage = `Impossible to recover from cron for user ${user._id}.`;
const expectedErrMessage = `Impossible to recover from cron for user ${user._id}.`;
await new Promise((resolve, reject) => {
cronMiddleware(req, res, (err) => {
cronMiddleware(req, res, err => {
if (!err) return reject(new Error('Cron should have failed.'));
expect(err.message).to.be.equal(expectedErrMessage);
resolve();
return resolve();
});
});
});
it('cronSignature longer than an hour ago should allow cron', async () => {
user.lastCron = moment(new Date()).subtract({days: 2});
let now = new Date();
user.lastCron = moment(new Date()).subtract({ days: 2 });
const now = new Date();
await User.update({
_id: user._id,
}, {
@@ -297,11 +302,11 @@ describe('cron middleware', () => {
await user.save();
await new Promise((resolve, reject) => {
cronMiddleware(req, res, (err) => {
cronMiddleware(req, res, err => {
if (err) return reject(err);
expect(moment(now).isSame(user.auth.timestamps.loggedin, 'day'));
expect(user._cronSignature).to.be.equal('NOT_RUNNING');
resolve();
return resolve();
});
});
});

View File

@@ -10,7 +10,8 @@ import { NotAuthorized } from '../../../../website/server/libs/errors';
import apiError from '../../../../website/server/libs/apiError';
describe('ensure access middlewares', () => {
let res, req, next;
let res; let req; let
next;
beforeEach(() => {
res = generateRes();
@@ -20,7 +21,7 @@ describe('ensure access middlewares', () => {
context('ensure admin', () => {
it('returns not authorized when user is not an admin', () => {
res.locals = {user: {contributor: {admin: false}}};
res.locals = { user: { contributor: { admin: false } } };
ensureAdmin(req, res, next);
@@ -30,7 +31,7 @@ describe('ensure access middlewares', () => {
});
it('passes when user is an admin', () => {
res.locals = {user: {contributor: {admin: true}}};
res.locals = { user: { contributor: { admin: true } } };
ensureAdmin(req, res, next);
@@ -41,7 +42,7 @@ describe('ensure access middlewares', () => {
context('ensure sudo', () => {
it('returns not authorized when user is not a sudo user', () => {
res.locals = {user: {contributor: {sudo: false}}};
res.locals = { user: { contributor: { sudo: false } } };
ensureSudo(req, res, next);
@@ -51,7 +52,7 @@ describe('ensure access middlewares', () => {
});
it('passes when user is a sudo user', () => {
res.locals = {user: {contributor: {sudo: true}}};
res.locals = { user: { contributor: { sudo: true } } };
ensureSudo(req, res, next);

View File

@@ -1,4 +1,5 @@
/* eslint-disable global-require */
import nconf from 'nconf';
import {
generateRes,
generateReq,
@@ -6,10 +7,10 @@ import {
} from '../../../helpers/api-unit.helper';
import ensureDevelpmentMode from '../../../../website/server/middlewares/ensureDevelpmentMode';
import { NotFound } from '../../../../website/server/libs/errors';
import nconf from 'nconf';
describe('developmentMode middleware', () => {
let res, req, next;
let res; let req; let
next;
beforeEach(() => {
res = generateRes();

View File

@@ -15,7 +15,8 @@ import { BadRequest } from '../../../../website/server/libs/errors';
import logger from '../../../../website/server/libs/logger';
describe('errorHandler', () => {
let res, req, next;
let res; let req; let
next;
beforeEach(() => {
res = generateRes();
@@ -29,7 +30,7 @@ describe('errorHandler', () => {
});
it('sends internal server error if error is not a CustomError and is not identified', () => {
let error = new Error();
const error = new Error();
errorHandler(error, req, res, next);
@@ -45,7 +46,7 @@ describe('errorHandler', () => {
});
it('identifies errors with statusCode property and format them correctly', () => {
let error = new Error('Error message');
const error = new Error('Error message');
error.statusCode = 400;
errorHandler(error, req, res, next);
@@ -62,7 +63,7 @@ describe('errorHandler', () => {
});
it('doesn\'t leak info about 500 errors', () => {
let error = new Error('Some secret error message');
const error = new Error('Some secret error message');
error.statusCode = 500;
errorHandler(error, req, res, next);
@@ -79,7 +80,7 @@ describe('errorHandler', () => {
});
it('sends CustomError', () => {
let error = new BadRequest();
const error = new BadRequest();
errorHandler(error, req, res, next);
@@ -95,7 +96,7 @@ describe('errorHandler', () => {
});
it('handle http-errors errors', () => {
let error = new Error('custom message');
const error = new Error('custom message');
error.statusCode = 422;
errorHandler(error, req, res, next);
@@ -112,7 +113,7 @@ describe('errorHandler', () => {
});
it('handle express-validator errors', () => {
let error = [{param: 'param', msg: 'invalid param', value: 123}];
const error = [{ param: 'param', msg: 'invalid param', value: 123 }];
errorHandler(error, req, res, next);
@@ -131,7 +132,7 @@ describe('errorHandler', () => {
});
it('handle Mongoose Validation errors', () => {
let error = new Error('User validation failed');
const error = new Error('User validation failed');
error.name = 'ValidationError';
error.errors = {
@@ -159,7 +160,7 @@ describe('errorHandler', () => {
});
it('logs error', () => {
let error = new BadRequest();
const error = new BadRequest();
errorHandler(error, req, res, next);

View File

@@ -10,11 +10,12 @@ import {
import common from '../../../../website/common';
import { model as User } from '../../../../website/server/models/user';
const i18n = common.i18n;
const { i18n } = common;
describe('language middleware', () => {
describe('res.t', () => {
let res, req, next;
let res; let req; let
next;
beforeEach(() => {
res = generateRes();
@@ -46,9 +47,10 @@ describe('language middleware', () => {
});
describe('getUserLanguage', () => {
let res, req, next;
let res; let req; let
next;
let checkResT = (resToCheck) => {
const checkResT = resToCheck => {
expect(resToCheck.t).to.be.a('function');
expect(resToCheck.t('help')).to.equal(i18n.t('help', req.language));
};
@@ -119,7 +121,7 @@ describe('language middleware', () => {
checkResT(res);
});
it('falls back to english if the user preferred language is not avalaible', (done) => {
it('falls back to english if the user preferred language is not avalaible', done => {
req.locals = {
user: {
preferences: {
@@ -155,7 +157,7 @@ describe('language middleware', () => {
});
context('request with session', () => {
it('uses the user preferred language if avalaible', (done) => {
it('uses the user preferred language if avalaible', done => {
sandbox.stub(User, 'findOne').returns({
lean () {
return this;
@@ -182,7 +184,7 @@ describe('language middleware', () => {
});
context('browser fallback', () => {
it('uses browser specificed language', (done) => {
it('uses browser specificed language', done => {
req.headers['accept-language'] = 'pt';
getUserLanguage(req, res, () => {
@@ -192,7 +194,7 @@ describe('language middleware', () => {
});
});
it('uses first language in series if browser specifies multiple', (done) => {
it('uses first language in series if browser specifies multiple', done => {
req.headers['accept-language'] = 'he, pt, it';
getUserLanguage(req, res, () => {
@@ -202,7 +204,7 @@ describe('language middleware', () => {
});
});
it('skips invalid lanaguages and uses first language in series if browser specifies multiple', (done) => {
it('skips invalid lanaguages and uses first language in series if browser specifies multiple', done => {
req.headers['accept-language'] = 'blah, he, pt, it';
getUserLanguage(req, res, () => {
@@ -212,7 +214,7 @@ describe('language middleware', () => {
});
});
it('uses normal version of language if specialized locale is passed in', (done) => {
it('uses normal version of language if specialized locale is passed in', done => {
req.headers['accept-language'] = 'fr-CA';
getUserLanguage(req, res, () => {
@@ -222,7 +224,7 @@ describe('language middleware', () => {
});
});
it('uses normal version of language if specialized locale is passed in', (done) => {
it('uses normal version of language if specialized locale is passed in', done => {
req.headers['accept-language'] = 'fr-CA';
getUserLanguage(req, res, () => {
@@ -232,7 +234,7 @@ describe('language middleware', () => {
});
});
it('uses es if es is passed in', (done) => {
it('uses es if es is passed in', done => {
req.headers['accept-language'] = 'es';
getUserLanguage(req, res, () => {
@@ -242,7 +244,7 @@ describe('language middleware', () => {
});
});
it('uses es_419 if applicable es-languages are passed in', (done) => {
it('uses es_419 if applicable es-languages are passed in', done => {
req.headers['accept-language'] = 'es-mx';
getUserLanguage(req, res, () => {
@@ -252,7 +254,7 @@ describe('language middleware', () => {
});
});
it('uses es_419 if multiple es languages are passed in', (done) => {
it('uses es_419 if multiple es languages are passed in', done => {
req.headers['accept-language'] = 'es-GT, es-MX, es-CR';
getUserLanguage(req, res, () => {
@@ -262,7 +264,7 @@ describe('language middleware', () => {
});
});
it('zh', (done) => {
it('zh', done => {
req.headers['accept-language'] = 'zh-TW';
getUserLanguage(req, res, () => {
@@ -272,7 +274,7 @@ describe('language middleware', () => {
});
});
it('uses english if browser specified language is not compatible', (done) => {
it('uses english if browser specified language is not compatible', done => {
req.headers['accept-language'] = 'blah';
getUserLanguage(req, res, () => {
@@ -282,7 +284,7 @@ describe('language middleware', () => {
});
});
it('uses english if browser does not specify', (done) => {
it('uses english if browser does not specify', done => {
req.headers['accept-language'] = '';
getUserLanguage(req, res, () => {
@@ -292,7 +294,7 @@ describe('language middleware', () => {
});
});
it('uses english if browser does not supply an accept-language header', (done) => {
it('uses english if browser does not supply an accept-language header', done => {
delete req.headers['accept-language'];
getUserLanguage(req, res, () => {

View File

@@ -1,14 +1,15 @@
import nconf from 'nconf';
import requireAgain from 'require-again';
import {
generateRes,
generateReq,
generateNext,
} from '../../../helpers/api-unit.helper';
import nconf from 'nconf';
import requireAgain from 'require-again';
describe('maintenance mode middleware', () => {
let res, req, next;
let pathToMaintenanceModeMiddleware = '../../../../website/server/middlewares/maintenanceMode';
let res; let req; let
next;
const pathToMaintenanceModeMiddleware = '../../../../website/server/middlewares/maintenanceMode';
beforeEach(() => {
res = generateRes();
@@ -18,7 +19,7 @@ describe('maintenance mode middleware', () => {
it('does not return 503 error when maintenance mode is off', () => {
req = generateReq();
sandbox.stub(nconf, 'get').withArgs('MAINTENANCE_MODE').returns('false');
let attachMaintenanceMode = requireAgain(pathToMaintenanceModeMiddleware).default;
const attachMaintenanceMode = requireAgain(pathToMaintenanceModeMiddleware).default;
attachMaintenanceMode(req, res, next);
@@ -29,7 +30,7 @@ describe('maintenance mode middleware', () => {
it('returns 503 error when maintenance mode is on', () => {
req = generateReq();
sandbox.stub(nconf, 'get').withArgs('MAINTENANCE_MODE').returns('true');
let attachMaintenanceMode = requireAgain(pathToMaintenanceModeMiddleware).default;
const attachMaintenanceMode = requireAgain(pathToMaintenanceModeMiddleware).default;
attachMaintenanceMode(req, res, next);
@@ -39,18 +40,18 @@ describe('maintenance mode middleware', () => {
});
it('renders maintenance page when request type is HTML', () => {
req = generateReq({headers: {accept: 'text/html'}});
req = generateReq({ headers: { accept: 'text/html' } });
sandbox.stub(nconf, 'get').withArgs('MAINTENANCE_MODE').returns('true');
let attachMaintenanceMode = requireAgain(pathToMaintenanceModeMiddleware).default;
const attachMaintenanceMode = requireAgain(pathToMaintenanceModeMiddleware).default;
attachMaintenanceMode(req, res, next);
expect(res.render).to.have.been.calledOnce;
});
it('sends error message when request type is JSON', () => {
req = generateReq({headers: {accept: 'application/json'}});
req = generateReq({ headers: { accept: 'application/json' } });
sandbox.stub(nconf, 'get').withArgs('MAINTENANCE_MODE').returns('true');
let attachMaintenanceMode = requireAgain(pathToMaintenanceModeMiddleware).default;
const attachMaintenanceMode = requireAgain(pathToMaintenanceModeMiddleware).default;
attachMaintenanceMode(req, res, next);
expect(res.send).to.have.been.calledOnce;

View File

@@ -1,14 +1,15 @@
import nconf from 'nconf';
import requireAgain from 'require-again';
import {
generateRes,
generateReq,
generateNext,
} from '../../../helpers/api-unit.helper';
import nconf from 'nconf';
import requireAgain from 'require-again';
describe('redirects middleware', () => {
let res, req, next;
let pathToRedirectsMiddleware = '../../../../website/server/middlewares/redirects';
let res; let req; let
next;
const pathToRedirectsMiddleware = '../../../../website/server/middlewares/redirects';
beforeEach(() => {
res = generateRes();
@@ -18,13 +19,13 @@ describe('redirects middleware', () => {
context('forceSSL', () => {
it('sends http requests to https', () => {
let nconfStub = sandbox.stub(nconf, 'get');
const nconfStub = sandbox.stub(nconf, 'get');
nconfStub.withArgs('BASE_URL').returns('https://habitica.com');
nconfStub.withArgs('IS_PROD').returns(true);
req.header = sandbox.stub().withArgs('x-forwarded-proto').returns('http');
req.originalUrl = '/static/front';
let attachRedirects = requireAgain(pathToRedirectsMiddleware);
const attachRedirects = requireAgain(pathToRedirectsMiddleware);
attachRedirects.forceSSL(req, res, next);
@@ -33,13 +34,13 @@ describe('redirects middleware', () => {
});
it('does not redirect https forwarded requests', () => {
let nconfStub = sandbox.stub(nconf, 'get');
const nconfStub = sandbox.stub(nconf, 'get');
nconfStub.withArgs('BASE_URL').returns('https://habitica.com');
nconfStub.withArgs('IS_PROD').returns(true);
req.header = sandbox.stub().withArgs('x-forwarded-proto').returns('https');
req.originalUrl = '/static/front';
let attachRedirects = requireAgain(pathToRedirectsMiddleware);
const attachRedirects = requireAgain(pathToRedirectsMiddleware);
attachRedirects.forceSSL(req, res, next);
@@ -47,13 +48,13 @@ describe('redirects middleware', () => {
});
it('does not redirect outside of production environments', () => {
let nconfStub = sandbox.stub(nconf, 'get');
const nconfStub = sandbox.stub(nconf, 'get');
nconfStub.withArgs('BASE_URL').returns('https://habitica.com');
nconfStub.withArgs('IS_PROD').returns(false);
req.header = sandbox.stub().withArgs('x-forwarded-proto').returns('http');
req.originalUrl = '/static/front';
let attachRedirects = requireAgain(pathToRedirectsMiddleware);
const attachRedirects = requireAgain(pathToRedirectsMiddleware);
attachRedirects.forceSSL(req, res, next);
@@ -61,13 +62,13 @@ describe('redirects middleware', () => {
});
it('does not redirect if base URL is not https', () => {
let nconfStub = sandbox.stub(nconf, 'get');
const nconfStub = sandbox.stub(nconf, 'get');
nconfStub.withArgs('BASE_URL').returns('http://habitica.com');
nconfStub.withArgs('IS_PROD').returns(true);
req.header = sandbox.stub().withArgs('x-forwarded-proto').returns('http');
req.originalUrl = '/static/front';
let attachRedirects = requireAgain(pathToRedirectsMiddleware);
const attachRedirects = requireAgain(pathToRedirectsMiddleware);
attachRedirects.forceSSL(req, res, next);
@@ -75,7 +76,7 @@ describe('redirects middleware', () => {
});
it('does not redirect if passed skip ssl request param is passed with corrrect key', () => {
let nconfStub = sandbox.stub(nconf, 'get');
const nconfStub = sandbox.stub(nconf, 'get');
nconfStub.withArgs('BASE_URL').returns('https://habitica.com');
nconfStub.withArgs('IS_PROD').returns(true);
nconfStub.withArgs('SKIP_SSL_CHECK_KEY').returns('test-key');
@@ -91,7 +92,7 @@ describe('redirects middleware', () => {
});
it('does redirect if skip ssl request param is passed with incorrrect key', () => {
let nconfStub = sandbox.stub(nconf, 'get');
const nconfStub = sandbox.stub(nconf, 'get');
nconfStub.withArgs('BASE_URL').returns('https://habitica.com');
nconfStub.withArgs('IS_PROD').returns(true);
nconfStub.withArgs('SKIP_SSL_CHECK_KEY').returns('test-key');
@@ -108,7 +109,7 @@ describe('redirects middleware', () => {
});
it('does redirect if skip ssl check key is not set', () => {
let nconfStub = sandbox.stub(nconf, 'get');
const nconfStub = sandbox.stub(nconf, 'get');
nconfStub.withArgs('BASE_URL').returns('https://habitica.com');
nconfStub.withArgs('IS_PROD').returns(true);
nconfStub.withArgs('SKIP_SSL_CHECK_KEY').returns(null);
@@ -127,7 +128,7 @@ describe('redirects middleware', () => {
context('forceHabitica', () => {
it('sends requests with differing hostname to base URL host', () => {
let nconfStub = sandbox.stub(nconf, 'get');
const nconfStub = sandbox.stub(nconf, 'get');
nconfStub.withArgs('BASE_URL').returns('https://habitica.com');
nconfStub.withArgs('IGNORE_REDIRECT').returns('false');
nconfStub.withArgs('IS_PROD').returns(true);
@@ -136,7 +137,7 @@ describe('redirects middleware', () => {
req.originalUrl = '/static/front';
req.url = '/static/front';
let attachRedirects = requireAgain(pathToRedirectsMiddleware);
const attachRedirects = requireAgain(pathToRedirectsMiddleware);
attachRedirects.forceHabitica(req, res, next);
@@ -145,7 +146,7 @@ describe('redirects middleware', () => {
});
it('does not redirect outside of production environments', () => {
let nconfStub = sandbox.stub(nconf, 'get');
const nconfStub = sandbox.stub(nconf, 'get');
nconfStub.withArgs('BASE_URL').returns('https://habitica.com');
nconfStub.withArgs('IGNORE_REDIRECT').returns('false');
nconfStub.withArgs('IS_PROD').returns(false);
@@ -154,7 +155,7 @@ describe('redirects middleware', () => {
req.originalUrl = '/static/front';
req.url = '/static/front';
let attachRedirects = requireAgain(pathToRedirectsMiddleware);
const attachRedirects = requireAgain(pathToRedirectsMiddleware);
attachRedirects.forceHabitica(req, res, next);
@@ -162,7 +163,7 @@ describe('redirects middleware', () => {
});
it('does not redirect if env is set to ignore redirection', () => {
let nconfStub = sandbox.stub(nconf, 'get');
const nconfStub = sandbox.stub(nconf, 'get');
nconfStub.withArgs('BASE_URL').returns('https://habitica.com');
nconfStub.withArgs('IGNORE_REDIRECT').returns('true');
nconfStub.withArgs('IS_PROD').returns(true);
@@ -171,7 +172,7 @@ describe('redirects middleware', () => {
req.originalUrl = '/static/front';
req.url = '/static/front';
let attachRedirects = requireAgain(pathToRedirectsMiddleware);
const attachRedirects = requireAgain(pathToRedirectsMiddleware);
attachRedirects.forceHabitica(req, res, next);
@@ -179,7 +180,7 @@ describe('redirects middleware', () => {
});
it('does not redirect if request hostname matches base URL host', () => {
let nconfStub = sandbox.stub(nconf, 'get');
const nconfStub = sandbox.stub(nconf, 'get');
nconfStub.withArgs('BASE_URL').returns('https://habitica.com');
nconfStub.withArgs('IGNORE_REDIRECT').returns('false');
nconfStub.withArgs('IS_PROD').returns(true);
@@ -188,7 +189,7 @@ describe('redirects middleware', () => {
req.originalUrl = '/static/front';
req.url = '/static/front';
let attachRedirects = requireAgain(pathToRedirectsMiddleware);
const attachRedirects = requireAgain(pathToRedirectsMiddleware);
attachRedirects.forceHabitica(req, res, next);
@@ -196,7 +197,7 @@ describe('redirects middleware', () => {
});
it('does not redirect if request is an API URL', () => {
let nconfStub = sandbox.stub(nconf, 'get');
const nconfStub = sandbox.stub(nconf, 'get');
nconfStub.withArgs('BASE_URL').returns('https://habitica.com');
nconfStub.withArgs('IGNORE_REDIRECT').returns('false');
nconfStub.withArgs('IS_PROD').returns(true);
@@ -205,7 +206,7 @@ describe('redirects middleware', () => {
req.originalUrl = '/api/v3/challenges';
req.url = '/api/v3/challenges';
let attachRedirects = requireAgain(pathToRedirectsMiddleware);
const attachRedirects = requireAgain(pathToRedirectsMiddleware);
attachRedirects.forceHabitica(req, res, next);
@@ -213,7 +214,7 @@ describe('redirects middleware', () => {
});
it('does not redirect if request method is not GET', () => {
let nconfStub = sandbox.stub(nconf, 'get');
const nconfStub = sandbox.stub(nconf, 'get');
nconfStub.withArgs('BASE_URL').returns('https://habitica.com');
nconfStub.withArgs('IGNORE_REDIRECT').returns('false');
nconfStub.withArgs('IS_PROD').returns(true);
@@ -222,7 +223,7 @@ describe('redirects middleware', () => {
req.originalUrl = '/static/front';
req.url = '/static/front';
let attachRedirects = requireAgain(pathToRedirectsMiddleware);
const attachRedirects = requireAgain(pathToRedirectsMiddleware);
attachRedirects.forceHabitica(req, res, next);

View File

@@ -7,7 +7,8 @@ import responseMiddleware from '../../../../website/server/middlewares/response'
import packageInfo from '../../../../package.json';
describe('response middleware', () => {
let res, req, next;
let res; let req; let
next;
beforeEach(() => {
res = generateRes();
@@ -24,7 +25,7 @@ describe('response middleware', () => {
it('can be used to respond to requests', () => {
responseMiddleware(req, res, next);
res.respond(200, {field: 1});
res.respond(200, { field: 1 });
expect(res.status).to.be.calledOnce;
expect(res.json).to.be.calledOnce;
@@ -32,7 +33,7 @@ describe('response middleware', () => {
expect(res.status).to.be.calledWith(200);
expect(res.json).to.be.calledWith({
success: true,
data: {field: 1},
data: { field: 1 },
notifications: [],
userV: res.locals.user._v,
appVersion: packageInfo.version,
@@ -41,7 +42,7 @@ describe('response middleware', () => {
it('can be passed a third parameter to be used as optional message', () => {
responseMiddleware(req, res, next);
res.respond(200, {field: 1}, 'hello');
res.respond(200, { field: 1 }, 'hello');
expect(res.status).to.be.calledOnce;
expect(res.json).to.be.calledOnce;
@@ -49,7 +50,7 @@ describe('response middleware', () => {
expect(res.status).to.be.calledWith(200);
expect(res.json).to.be.calledWith({
success: true,
data: {field: 1},
data: { field: 1 },
message: 'hello',
notifications: [],
userV: res.locals.user._v,
@@ -59,7 +60,7 @@ describe('response middleware', () => {
it('treats status >= 400 as failures', () => {
responseMiddleware(req, res, next);
res.respond(403, {field: 1});
res.respond(403, { field: 1 });
expect(res.status).to.be.calledOnce;
expect(res.json).to.be.calledOnce;
@@ -67,7 +68,7 @@ describe('response middleware', () => {
expect(res.status).to.be.calledWith(403);
expect(res.json).to.be.calledWith({
success: false,
data: {field: 1},
data: { field: 1 },
notifications: [],
userV: res.locals.user._v,
appVersion: packageInfo.version,
@@ -76,13 +77,13 @@ describe('response middleware', () => {
it('returns userV if a user is authenticated', () => {
responseMiddleware(req, res, next);
res.respond(200, {field: 1});
res.respond(200, { field: 1 });
expect(res.json).to.be.calledOnce;
expect(res.json).to.be.calledWith({
success: true,
data: {field: 1},
data: { field: 1 },
notifications: [],
userV: 0,
appVersion: packageInfo.version,
@@ -90,24 +91,25 @@ describe('response middleware', () => {
});
it('returns notifications if a user is authenticated', () => {
const user = res.locals.user;
const { user } = res.locals;
user.notifications = [
null, // invalid, not an object
{seen: true}, // invalid, no type or id
{id: 123}, // invalid, no type
// {type: 'ABC'}, // invalid, no id, not included here because the id would be added automatically
{type: 'ABC', id: '123'}, // valid
{ 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});
res.respond(200, { field: 1 });
expect(res.json).to.be.calledOnce;
expect(res.json).to.be.calledWith({
success: true,
data: {field: 1},
data: { field: 1 },
notifications: [
{
type: 'ABC',

View File

@@ -1,13 +1,14 @@
import { each, find } from 'lodash';
import { model as Challenge } from '../../../../website/server/models/challenge';
import { model as Group } from '../../../../website/server/models/group';
import { model as User } from '../../../../website/server/models/user';
import * as Tasks from '../../../../website/server/models/task';
import common from '../../../../website/common/';
import { each, find } from 'lodash';
import common from '../../../../website/common';
describe('Challenge Model', () => {
let guild, leader, challenge, task;
let tasksToTest = {
let guild; let leader; let challenge; let
task;
const tasksToTest = {
habit: {
text: 'test habit',
type: 'habit',
@@ -74,11 +75,15 @@ describe('Challenge Model', () => {
it('adds tasks to challenge and challenge members', async () => {
await challenge.addTasks([task]);
const updatedLeader = await User.findOne({_id: leader._id});
const updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
const syncedTask = find(updatedLeadersTasks, function findNewTask (updatedLeadersTask) {
return updatedLeadersTask.type === taskValue.type && updatedLeadersTask.text === taskValue.text;
});
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
const syncedTask = find(
updatedLeadersTasks,
updatedLeadersTask => (
updatedLeadersTask.type === taskValue.type
&& updatedLeadersTask.text === taskValue.text
),
);
expect(syncedTask).to.exist;
expect(syncedTask.notes).to.eql(task.notes);
@@ -88,18 +93,22 @@ describe('Challenge Model', () => {
it('syncs a challenge to a user', async () => {
await challenge.addTasks([task]);
let newMember = new User({
const newMember = new User({
guilds: [guild._id],
});
await newMember.save();
await challenge.syncToUser(newMember);
let updatedNewMember = await User.findById(newMember._id);
let updatedNewMemberTasks = await Tasks.Task.find({_id: { $in: updatedNewMember.tasksOrder[`${taskType}s`]}});
let syncedTask = find(updatedNewMemberTasks, function findNewTask (updatedNewMemberTask) {
return updatedNewMemberTask.type === taskValue.type && updatedNewMemberTask.text === taskValue.text;
});
const updatedNewMember = await User.findById(newMember._id);
const updatedNewMemberTasks = await Tasks.Task.find({ _id: { $in: updatedNewMember.tasksOrder[`${taskType}s`] } });
const syncedTask = find(
updatedNewMemberTasks,
updatedNewMemberTask => (
updatedNewMemberTask.type === taskValue.type
&& updatedNewMemberTask.text === taskValue.text
),
);
expect(updatedNewMember.challenges).to.contain(challenge._id);
expect(updatedNewMember.tags[7].id).to.equal(challenge._id);
@@ -111,30 +120,32 @@ describe('Challenge Model', () => {
it('syncs a challenge to a user with the existing task', async () => {
await challenge.addTasks([task]);
let updatedLeader = await User.findOne({_id: leader._id});
let updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
let syncedTask = find(updatedLeadersTasks, function findNewTask (updatedLeadersTask) {
return updatedLeadersTask.challenge.taskId === task._id;
});
let updatedLeader = await User.findOne({ _id: leader._id });
let updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
let syncedTask = find(
updatedLeadersTasks,
updatedLeadersTask => updatedLeadersTask.challenge.taskId === task._id,
);
let createdAtBefore = syncedTask.createdAt;
let attributeBefore = syncedTask.attribute;
const createdAtBefore = syncedTask.createdAt;
const attributeBefore = syncedTask.attribute;
let newTitle = 'newName';
const newTitle = 'newName';
task.text = newTitle;
task.attribute = 'int';
await task.save();
await challenge.syncToUser(leader);
updatedLeader = await User.findOne({_id: leader._id});
updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
updatedLeader = await User.findOne({ _id: leader._id });
updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
syncedTask = find(updatedLeadersTasks, function findNewTask (updatedLeadersTask) {
return updatedLeadersTask.challenge.taskId === task._id;
});
syncedTask = find(
updatedLeadersTasks,
updatedLeadersTask => updatedLeadersTask.challenge.taskId === task._id,
);
let createdAtAfter = syncedTask.createdAt;
let attributeAfter = syncedTask.attribute;
const createdAtAfter = syncedTask.createdAt;
const attributeAfter = syncedTask.attribute;
expect(createdAtBefore).to.eql(createdAtAfter);
expect(attributeBefore).to.eql(attributeAfter);
@@ -142,10 +153,10 @@ describe('Challenge Model', () => {
});
it('updates tasks to challenge and challenge members', async () => {
let updatedTaskName = 'Updated Test Habit';
const updatedTaskName = 'Updated Test Habit';
await challenge.addTasks([task]);
let req = {
const req = {
body: { text: updatedTaskName },
};
@@ -154,8 +165,8 @@ describe('Challenge Model', () => {
await challenge.updateTask(task);
let updatedLeader = await User.findOne({_id: leader._id});
let updatedUserTask = await Tasks.Task.findById(updatedLeader.tasksOrder[`${taskType}s`][0]);
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedUserTask = await Tasks.Task.findById(updatedLeader.tasksOrder[`${taskType}s`][0]);
expect(updatedUserTask.text).to.equal(updatedTaskName);
});
@@ -164,8 +175,8 @@ describe('Challenge Model', () => {
await challenge.addTasks([task]);
await challenge.removeTask(task);
let updatedLeader = await User.findOne({_id: leader._id});
let updatedUserTask = await Tasks.Task.findOne({_id: updatedLeader.tasksOrder[`${taskType}s`][0]}).exec();
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedUserTask = await Tasks.Task.findOne({ _id: updatedLeader.tasksOrder[`${taskType}s`][0] }).exec();
expect(updatedUserTask.challenge.broken).to.equal('TASK_DELETED');
});
@@ -174,11 +185,15 @@ describe('Challenge Model', () => {
await challenge.addTasks([task]);
await challenge.unlinkTasks(leader, 'remove-all');
let updatedLeader = await User.findOne({_id: leader._id});
let updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
let syncedTask = find(updatedLeadersTasks, function findNewTask (updatedLeadersTask) {
return updatedLeadersTask.type === taskValue.type && updatedLeadersTask.text === taskValue.text;
});
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
const syncedTask = find(
updatedLeadersTasks,
updatedLeadersTask => (
updatedLeadersTask.type === taskValue.type
&& updatedLeadersTask.text === taskValue.text
),
);
expect(syncedTask).to.not.exist;
});
@@ -187,11 +202,15 @@ describe('Challenge Model', () => {
await challenge.addTasks([task]);
await challenge.unlinkTasks(leader, 'keep-all');
let updatedLeader = await User.findOne({_id: leader._id});
let updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
let syncedTask = find(updatedLeadersTasks, function findNewTask (updatedLeadersTask) {
return updatedLeadersTask.type === taskValue.type && updatedLeadersTask.text === taskValue.text;
});
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
const syncedTask = find(
updatedLeadersTasks,
updatedLeadersTask => (
updatedLeadersTask.type === taskValue.type
&& updatedLeadersTask.text === taskValue.text
),
);
expect(syncedTask).to.exist;
expect(syncedTask.challenge._id).to.be.undefined;
@@ -212,8 +231,8 @@ describe('Challenge Model', () => {
await challenge.updateTask(task);
let updatedLeader = await User.findOne({_id: leader._id});
let updatedUserTask = await Tasks.Task.findById(updatedLeader.tasksOrder.habits[0]);
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedUserTask = await Tasks.Task.findById(updatedLeader.tasksOrder.habits[0]);
expect(updatedUserTask.up).to.equal(true);
expect(updatedUserTask.down).to.equal(false);
@@ -229,8 +248,8 @@ describe('Challenge Model', () => {
task.date = new Date();
await challenge.updateTask(task);
let updatedLeader = await User.findOne({_id: leader._id});
let updatedUserTask = await Tasks.Task.findById(updatedLeader.tasksOrder.todos[0]);
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedUserTask = await Tasks.Task.findById(updatedLeader.tasksOrder.todos[0]);
expect(updatedUserTask.date).to.exist;
});
@@ -247,8 +266,8 @@ describe('Challenge Model', () => {
});
await challenge.updateTask(task);
let updatedLeader = await User.findOne({_id: leader._id});
let updatedUserTask = await Tasks.Task.findById(updatedLeader.tasksOrder.todos[0]);
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedUserTask = await Tasks.Task.findById(updatedLeader.tasksOrder.todos[0]);
expect(updatedUserTask.checklist.toObject()).to.deep.equal([]);
});
@@ -263,8 +282,8 @@ describe('Challenge Model', () => {
task.everyX = 2;
await challenge.updateTask(task);
let updatedLeader = await User.findOne({_id: leader._id});
let updatedUserTask = await Tasks.Task.findById(updatedLeader.tasksOrder.dailys[0]);
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedUserTask = await Tasks.Task.findById(updatedLeader.tasksOrder.dailys[0]);
expect(updatedUserTask.everyX).to.eql(2);
});

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,13 @@
import { each, find, findIndex } from 'lodash';
import { model as Challenge } from '../../../../website/server/models/challenge';
import { model as Group } from '../../../../website/server/models/group';
import { model as User } from '../../../../website/server/models/user';
import * as Tasks from '../../../../website/server/models/task';
import { each, find, findIndex } from 'lodash';
describe('Group Task Methods', () => {
let guild, leader, challenge, task;
let tasksToTest = {
let guild; let leader; let challenge; let
task;
const tasksToTest = {
habit: {
text: 'test habit',
type: 'habit',
@@ -79,9 +80,9 @@ describe('Group Task Methods', () => {
it('syncs an assigned task to a user', async () => {
await guild.syncTask(task, leader);
let updatedLeader = await User.findOne({_id: leader._id});
let tagIndex = findIndex(updatedLeader.tags, {id: guild._id});
let newTag = updatedLeader.tags[tagIndex];
const updatedLeader = await User.findOne({ _id: leader._id });
const tagIndex = findIndex(updatedLeader.tags, { id: guild._id });
const newTag = updatedLeader.tags[tagIndex];
expect(newTag.id).to.equal(guild._id);
expect(newTag.name).to.equal(guild.name);
@@ -91,9 +92,9 @@ describe('Group Task Methods', () => {
it('create tags for a user when task is synced', async () => {
await guild.syncTask(task, leader);
let updatedLeader = await User.findOne({_id: leader._id});
let updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
let syncedTask = find(updatedLeadersTasks, findLinkedTask);
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
const syncedTask = find(updatedLeadersTasks, findLinkedTask);
expect(task.group.assignedUsers).to.contain(leader._id);
expect(syncedTask).to.exist;
@@ -101,13 +102,13 @@ describe('Group Task Methods', () => {
it('syncs updated info for assigned task to a user', async () => {
await guild.syncTask(task, leader);
let updatedTaskName = 'Update Task name';
const updatedTaskName = 'Update Task name';
task.text = updatedTaskName;
await guild.syncTask(task, leader);
let updatedLeader = await User.findOne({_id: leader._id});
let updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
let syncedTask = find(updatedLeadersTasks, findLinkedTask);
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
const syncedTask = find(updatedLeadersTasks, findLinkedTask);
expect(task.group.assignedUsers).to.contain(leader._id);
expect(syncedTask).to.exist;
@@ -117,9 +118,9 @@ describe('Group Task Methods', () => {
it('syncs checklist items to an assigned user', async () => {
await guild.syncTask(task, leader);
let updatedLeader = await User.findOne({_id: leader._id});
let updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
let syncedTask = find(updatedLeadersTasks, findLinkedTask);
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
const syncedTask = find(updatedLeadersTasks, findLinkedTask);
if (task.type !== 'daily' && task.type !== 'todo') return;
@@ -141,19 +142,19 @@ describe('Group Task Methods', () => {
});
it('syncs updated info for assigned task to all users', async () => {
let updatedTaskName = 'Update Task name';
const updatedTaskName = 'Update Task name';
task.text = updatedTaskName;
task.group.approval.required = true;
await guild.updateTask(task);
let updatedLeader = await User.findOne({_id: leader._id});
let updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
let syncedTask = find(updatedLeadersTasks, findLinkedTask);
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
const syncedTask = find(updatedLeadersTasks, findLinkedTask);
let updatedMember = await User.findOne({_id: newMember._id});
let updatedMemberTasks = await Tasks.Task.find({_id: { $in: updatedMember.tasksOrder[`${taskType}s`]}});
let syncedMemberTask = find(updatedMemberTasks, findLinkedTask);
const updatedMember = await User.findOne({ _id: newMember._id });
const updatedMemberTasks = await Tasks.Task.find({ _id: { $in: updatedMember.tasksOrder[`${taskType}s`] } });
const syncedMemberTask = find(updatedMemberTasks, findLinkedTask);
expect(task.group.assignedUsers).to.contain(leader._id);
expect(syncedTask).to.exist;
@@ -169,22 +170,22 @@ describe('Group Task Methods', () => {
it('syncs a new checklist item to all assigned users', async () => {
if (task.type !== 'daily' && task.type !== 'todo') return;
let newCheckListItem = {
const newCheckListItem = {
text: 'Checklist Item 1',
completed: false,
};
task.checklist.push(newCheckListItem);
await guild.updateTask(task, {newCheckListItem});
await guild.updateTask(task, { newCheckListItem });
let updatedLeader = await User.findOne({_id: leader._id});
let updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
let syncedTask = find(updatedLeadersTasks, findLinkedTask);
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
const syncedTask = find(updatedLeadersTasks, findLinkedTask);
let updatedMember = await User.findOne({_id: newMember._id});
let updatedMemberTasks = await Tasks.Task.find({_id: { $in: updatedMember.tasksOrder[`${taskType}s`]}});
let syncedMemberTask = find(updatedMemberTasks, findLinkedTask);
const updatedMember = await User.findOne({ _id: newMember._id });
const updatedMemberTasks = await Tasks.Task.find({ _id: { $in: updatedMember.tasksOrder[`${taskType}s`] } });
const syncedMemberTask = find(updatedMemberTasks, findLinkedTask);
expect(syncedTask.checklist.length).to.equal(task.checklist.length);
expect(syncedTask.checklist[1].text).to.equal(task.checklist[1].text);
@@ -195,20 +196,20 @@ describe('Group Task Methods', () => {
it('syncs updated info for checklist in assigned task to all users when flag is passed', async () => {
if (task.type !== 'daily' && task.type !== 'todo') return;
let updateCheckListText = 'Updated checklist item';
const updateCheckListText = 'Updated checklist item';
if (task.checklist) {
task.checklist[0].text = updateCheckListText;
}
await guild.updateTask(task, {updateCheckListItems: [task.checklist[0]]});
await guild.updateTask(task, { updateCheckListItems: [task.checklist[0]] });
let updatedLeader = await User.findOne({_id: leader._id});
let updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
let syncedTask = find(updatedLeadersTasks, findLinkedTask);
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
const syncedTask = find(updatedLeadersTasks, findLinkedTask);
let updatedMember = await User.findOne({_id: newMember._id});
let updatedMemberTasks = await Tasks.Task.find({_id: { $in: updatedMember.tasksOrder[`${taskType}s`]}});
let syncedMemberTask = find(updatedMemberTasks, findLinkedTask);
const updatedMember = await User.findOne({ _id: newMember._id });
const updatedMemberTasks = await Tasks.Task.find({ _id: { $in: updatedMember.tasksOrder[`${taskType}s`] } });
const syncedMemberTask = find(updatedMemberTasks, findLinkedTask);
expect(syncedTask.checklist.length).to.equal(task.checklist.length);
expect(syncedTask.checklist[0].text).to.equal(updateCheckListText);
@@ -219,15 +220,15 @@ describe('Group Task Methods', () => {
it('removes a checklist item in assigned task to all users when flag is passed with checklist id', async () => {
if (task.type !== 'daily' && task.type !== 'todo') return;
await guild.updateTask(task, {removedCheckListItemId: task.checklist[0].id});
await guild.updateTask(task, { removedCheckListItemId: task.checklist[0].id });
let updatedLeader = await User.findOne({_id: leader._id});
let updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
let syncedTask = find(updatedLeadersTasks, findLinkedTask);
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
const syncedTask = find(updatedLeadersTasks, findLinkedTask);
let updatedMember = await User.findOne({_id: newMember._id});
let updatedMemberTasks = await Tasks.Task.find({_id: { $in: updatedMember.tasksOrder[`${taskType}s`]}});
let syncedMemberTask = find(updatedMemberTasks, findLinkedTask);
const updatedMember = await User.findOne({ _id: newMember._id });
const updatedMemberTasks = await Tasks.Task.find({ _id: { $in: updatedMember.tasksOrder[`${taskType}s`] } });
const syncedMemberTask = find(updatedMemberTasks, findLinkedTask);
expect(syncedTask.checklist.length).to.equal(0);
expect(syncedMemberTask.checklist.length).to.equal(0);
@@ -238,9 +239,9 @@ describe('Group Task Methods', () => {
await guild.syncTask(task, leader);
await guild.removeTask(task);
let updatedLeader = await User.findOne({_id: leader._id});
let updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
let syncedTask = find(updatedLeadersTasks, findLinkedTask);
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
const syncedTask = find(updatedLeadersTasks, findLinkedTask);
expect(syncedTask.group.broken).to.equal('TASK_DELETED');
});
@@ -249,9 +250,9 @@ describe('Group Task Methods', () => {
await guild.syncTask(task, leader);
await guild.unlinkTask(task, leader, 'remove-all');
let updatedLeader = await User.findOne({_id: leader._id});
let updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
let syncedTask = find(updatedLeadersTasks, findLinkedTask);
const updatedLeader = await User.findOne({ _id: leader._id });
const updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
const syncedTask = find(updatedLeadersTasks, findLinkedTask);
expect(task.group.assignedUsers).to.not.contain(leader._id);
expect(syncedTask).to.not.exist;
@@ -260,17 +261,18 @@ describe('Group Task Methods', () => {
it('unlinks and keeps group tasks for a user when keep-all is specified', async () => {
await guild.syncTask(task, leader);
let updatedLeader = await User.findOne({_id: leader._id});
let updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
let syncedTask = find(updatedLeadersTasks, findLinkedTask);
let updatedLeader = await User.findOne({ _id: leader._id });
let updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
const syncedTask = find(updatedLeadersTasks, findLinkedTask);
await guild.unlinkTask(task, leader, 'keep-all');
updatedLeader = await User.findOne({_id: leader._id});
updatedLeadersTasks = await Tasks.Task.find({_id: { $in: updatedLeader.tasksOrder[`${taskType}s`]}});
let updatedSyncedTask = find(updatedLeadersTasks, function findUpdatedLinkedTask (updatedLeadersTask) {
return updatedLeadersTask._id === syncedTask._id;
});
updatedLeader = await User.findOne({ _id: leader._id });
updatedLeadersTasks = await Tasks.Task.find({ _id: { $in: updatedLeader.tasksOrder[`${taskType}s`] } });
const updatedSyncedTask = find(
updatedLeadersTasks,
updatedLeadersTask => updatedLeadersTask._id === syncedTask._id,
);
expect(task.group.assignedUsers).to.not.contain(leader._id);
expect(updatedSyncedTask).to.exist;

View File

@@ -1,14 +1,15 @@
import { each } from 'lodash';
import { model as Challenge } from '../../../../website/server/models/challenge';
import { model as Group } from '../../../../website/server/models/group';
import { model as User } from '../../../../website/server/models/user';
import * as Tasks from '../../../../website/server/models/task';
import { InternalServerError } from '../../../../website/server/libs/errors';
import { each } from 'lodash';
import { generateHistory } from '../../../helpers/api-unit.helper.js';
import { generateHistory } from '../../../helpers/api-unit.helper';
describe('Task Model', () => {
let guild, leader, challenge, task;
let tasksToTest = {
let guild; let leader; let challenge; let
task;
const tasksToTest = {
habit: {
text: 'test habit',
type: 'habit',
@@ -62,11 +63,11 @@ describe('Task Model', () => {
});
it('preens challenge tasks history when scored', async () => {
let historyLengthBeforePreen = task.history.length;
const historyLengthBeforePreen = task.history.length;
await task.scoreChallengeTask(1.2);
let updatedTask = await Tasks.Task.findOne({_id: task._id});
const updatedTask = await Tasks.Task.findOne({ _id: task._id });
expect(historyLengthBeforePreen).to.be.greaterThan(updatedTask.history.length);
});
@@ -75,7 +76,8 @@ describe('Task Model', () => {
describe('Static Methods', () => {
describe('findByIdOrAlias', () => {
let taskWithAlias, user;
let taskWithAlias; let
user;
beforeEach(async () => {
user = new User();
@@ -112,13 +114,13 @@ describe('Task Model', () => {
});
it('returns task by id', async () => {
let foundTodo = await Tasks.Task.findByIdOrAlias(taskWithAlias._id, user._id);
const foundTodo = await Tasks.Task.findByIdOrAlias(taskWithAlias._id, user._id);
expect(foundTodo.text).to.eql(taskWithAlias.text);
});
it('returns task by alias', async () => {
let foundTodo = await Tasks.Task.findByIdOrAlias(taskWithAlias.alias, user._id);
const foundTodo = await Tasks.Task.findByIdOrAlias(taskWithAlias.alias, user._id);
expect(foundTodo.text).to.eql(taskWithAlias.text);
});
@@ -134,7 +136,7 @@ describe('Task Model', () => {
});
it('returns null if task cannot be found', async () => {
let foundTask = await Tasks.Task.findByIdOrAlias('not-found', user._id);
const foundTask = await Tasks.Task.findByIdOrAlias('not-found', user._id);
expect(foundTask).to.eql(null);
});

View File

@@ -5,7 +5,7 @@ import common from '../../../../website/common';
describe('User Model', () => {
it('keeps user._tmp when calling .toJSON', () => {
let user = new User({
const user = new User({
auth: {
local: {
username: 'username',
@@ -17,26 +17,26 @@ describe('User Model', () => {
},
});
user._tmp = {ok: true};
user._nonTmp = {ok: true};
user._tmp = { ok: true };
user._nonTmp = { ok: true };
expect(user._tmp).to.eql({ok: true});
expect(user._nonTmp).to.eql({ok: true});
expect(user._tmp).to.eql({ ok: true });
expect(user._nonTmp).to.eql({ ok: true });
let toObject = user.toObject();
let toJSON = user.toJSON();
const toObject = user.toObject();
const toJSON = user.toJSON();
expect(toObject).to.not.have.keys('_tmp');
expect(toObject).to.not.have.keys('_nonTmp');
expect(toJSON).to.have.any.key('_tmp');
expect(toJSON._tmp).to.eql({ok: true});
expect(toJSON._tmp).to.eql({ ok: true });
expect(toJSON).to.not.have.keys('_nonTmp');
});
it('can add computed stats to a JSONified user object', () => {
let user = new User();
let userToJSON = user.toJSON();
const user = new User();
const userToJSON = user.toJSON();
expect(userToJSON.stats.maxMP).to.not.exist;
expect(userToJSON.stats.maxHealth).to.not.exist;
@@ -50,9 +50,9 @@ describe('User Model', () => {
});
it('can transform user object without mongoose helpers', async () => {
let user = new User();
const user = new User();
await user.save();
let userToJSON = await User.findById(user._id).lean().exec();
const userToJSON = await User.findById(user._id).lean().exec();
expect(userToJSON.stats.maxMP).to.not.exist;
expect(userToJSON.stats.maxHealth).to.not.exist;
@@ -68,9 +68,9 @@ describe('User Model', () => {
});
it('can transform user object without mongoose helpers (including computed stats)', async () => {
let user = new User();
const user = new User();
await user.save();
let userToJSON = await User.findById(user._id).lean().exec();
const userToJSON = await User.findById(user._id).lean().exec();
expect(userToJSON.stats.maxMP).to.not.exist;
expect(userToJSON.stats.maxHealth).to.not.exist;
@@ -86,11 +86,11 @@ describe('User Model', () => {
context('notifications', () => {
it('can add notifications without data', () => {
let user = new User();
const user = new User();
user.addNotification('CRON');
let userToJSON = user.toJSON();
const userToJSON = user.toJSON();
expect(user.notifications.length).to.equal(1);
expect(userToJSON.notifications[0]).to.have.all.keys(['data', 'id', 'type', 'seen']);
expect(userToJSON.notifications[0].type).to.equal('CRON');
@@ -99,14 +99,15 @@ describe('User Model', () => {
});
it('removes invalid notifications when calling toJSON', () => {
let user = new User();
const user = new User();
user.notifications = [
null, // invalid, not an object
{seen: true}, // invalid, no type or id
{id: 123}, // invalid, no type
// {type: 'ABC'}, // invalid, no id, not included here because the id would be added automatically
{type: 'ABC', id: '123'}, // valid
{ 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();
@@ -118,15 +119,15 @@ describe('User Model', () => {
});
it('can add notifications with data and already marked as seen', () => {
let user = new User();
const user = new User();
user.addNotification('CRON', {field: 1}, true);
user.addNotification('CRON', { field: 1 }, true);
let userToJSON = user.toJSON();
const userToJSON = user.toJSON();
expect(user.notifications.length).to.equal(1);
expect(userToJSON.notifications[0]).to.have.all.keys(['data', 'id', 'type', 'seen']);
expect(userToJSON.notifications[0].type).to.equal('CRON');
expect(userToJSON.notifications[0].data).to.eql({field: 1});
expect(userToJSON.notifications[0].data).to.eql({ field: 1 });
expect(userToJSON.notifications[0].seen).to.eql(true);
});
@@ -135,11 +136,11 @@ describe('User Model', () => {
let user = new User();
await user.save();
await User.pushNotification({_id: user._id}, 'CRON');
await User.pushNotification({ _id: user._id }, 'CRON');
user = await User.findOne({_id: user._id}).exec();
user = await User.findOne({ _id: user._id }).exec();
let userToJSON = user.toJSON();
const userToJSON = user.toJSON();
expect(user.notifications.length).to.equal(1);
expect(userToJSON.notifications[0]).to.have.all.keys(['data', 'id', 'type', 'seen']);
expect(userToJSON.notifications[0].type).to.equal('CRON');
@@ -147,21 +148,21 @@ describe('User Model', () => {
});
it('validates notifications via static method', async () => {
let user = new User();
const user = new User();
await user.save();
expect(User.pushNotification({_id: user._id}, 'BAD_TYPE')).to.eventually.be.rejected;
expect(User.pushNotification({_id: user._id}, 'CRON', null, 'INVALID_SEEN')).to.eventually.be.rejected;
expect(User.pushNotification({ _id: user._id }, 'BAD_TYPE')).to.eventually.be.rejected;
expect(User.pushNotification({ _id: user._id }, 'CRON', null, 'INVALID_SEEN')).to.eventually.be.rejected;
});
it('adds notifications without data for all given users via static method', async () => {
let user = new User();
let otherUser = new User();
const otherUser = new User();
await Promise.all([user.save(), otherUser.save()]);
await User.pushNotification({_id: {$in: [user._id, otherUser._id]}}, 'CRON');
await User.pushNotification({ _id: { $in: [user._id, otherUser._id] } }, 'CRON');
user = await User.findOne({_id: user._id}).exec();
user = await User.findOne({ _id: user._id }).exec();
let userToJSON = user.toJSON();
expect(user.notifications.length).to.equal(1);
@@ -170,7 +171,7 @@ describe('User Model', () => {
expect(userToJSON.notifications[0].data).to.eql({});
expect(userToJSON.notifications[0].seen).to.eql(false);
user = await User.findOne({_id: otherUser._id}).exec();
user = await User.findOne({ _id: otherUser._id }).exec();
userToJSON = user.toJSON();
expect(user.notifications.length).to.equal(1);
@@ -182,27 +183,27 @@ describe('User Model', () => {
it('adds notifications with data and seen status for all given users via static method', async () => {
let user = new User();
let otherUser = new User();
const otherUser = new User();
await Promise.all([user.save(), otherUser.save()]);
await User.pushNotification({_id: {$in: [user._id, otherUser._id]}}, 'CRON', {field: 1}, true);
await User.pushNotification({ _id: { $in: [user._id, otherUser._id] } }, 'CRON', { field: 1 }, true);
user = await User.findOne({_id: user._id}).exec();
user = await User.findOne({ _id: user._id }).exec();
let userToJSON = user.toJSON();
expect(user.notifications.length).to.equal(1);
expect(userToJSON.notifications[0]).to.have.all.keys(['data', 'id', 'type', 'seen']);
expect(userToJSON.notifications[0].type).to.equal('CRON');
expect(userToJSON.notifications[0].data).to.eql({field: 1});
expect(userToJSON.notifications[0].data).to.eql({ field: 1 });
expect(userToJSON.notifications[0].seen).to.eql(true);
user = await User.findOne({_id: otherUser._id}).exec();
user = await User.findOne({ _id: otherUser._id }).exec();
userToJSON = user.toJSON();
expect(user.notifications.length).to.equal(1);
expect(userToJSON.notifications[0]).to.have.all.keys(['data', 'id', 'type', 'seen']);
expect(userToJSON.notifications[0].type).to.equal('CRON');
expect(userToJSON.notifications[0].data).to.eql({field: 1});
expect(userToJSON.notifications[0].data).to.eql({ field: 1 });
expect(userToJSON.notifications[0].seen).to.eql(true);
});
});
@@ -245,7 +246,7 @@ describe('User Model', () => {
let group;
beforeEach(() => {
user = new User();
let leader = new User();
const leader = new User();
group = new Group({
name: 'test',
type: 'guild',
@@ -379,7 +380,8 @@ describe('User Model', () => {
// Create conditions for the Beast Master achievement to be awarded
user.achievements.beastMasterCount = 3;
expect(user.achievements.beastMaster).to.not.equal(true); // verify that it was not awarded initially
// verify that it was not awarded initially
expect(user.achievements.beastMaster).to.not.equal(true);
user = await user.save();
// verify that it's been awarded
@@ -397,7 +399,8 @@ describe('User Model', () => {
user = await User.findById(user._id).select('-items').exec();
expect(user.isSelected('items')).to.equal(false);
// create the conditions for the beast master achievement but this time it should not be awarded
// create the conditions for the beast master achievement
// but this time it should not be awarded
user.achievements.beastMasterCount = 3;
user = await user.save();
expect(user.achievements.beastMaster).to.equal(false);
@@ -536,11 +539,9 @@ describe('User Model', () => {
const today = moment('2017-12-06T00:00:00.000-06:00'); // 11 pm on 4 Texas
const req = {};
req.header = () => {
return timezoneOffset + 60;
};
req.header = () => timezoneOffset + 60;
const {daysMissed} = user.daysUserHasMissed(today, req);
const { daysMissed } = user.daysUserHasMissed(today, req);
expect(daysMissed).to.eql(0);
});
@@ -554,11 +555,9 @@ describe('User Model', () => {
const today = moment('2017-12-06T02:00:00.000-08:00');
const req = {};
req.header = () => {
return timezoneOffset + 60;
};
req.header = () => timezoneOffset + 60;
const {daysMissed} = user.daysUserHasMissed(today, req);
const { daysMissed } = user.daysUserHasMissed(today, req);
expect(daysMissed).to.eql(0);
});

View File

@@ -5,10 +5,10 @@ describe('UserNotification Model', () => {
it('converts an array of notifications to a safe version', () => {
const notifications = [
null, // invalid, not an object
{seen: true}, // invalid, no type or id
{id: 123}, // invalid, no type
{type: 'ABC'}, // invalid, no id
new UserNotification({type: 'ABC', id: 123}), // valid
{ seen: true }, // invalid, no type or id
{ id: 123 }, // invalid, no type
{ type: 'ABC' }, // invalid, no id
new UserNotification({ type: 'ABC', id: 123 }), // valid
];
const notificationsToJSON = UserNotification.convertNotificationsToSafeJson(notifications);

View File

@@ -1,6 +1,6 @@
import { v4 as generateUUID } from 'uuid';
import { model as Webhook } from '../../../../website/server/models/webhook';
import { BadRequest } from '../../../../website/server/libs/errors';
import { v4 as generateUUID } from 'uuid';
import apiError from '../../../../website/server/libs/apiError';
describe('Webhook Model', () => {
@@ -33,7 +33,7 @@ describe('Webhook Model', () => {
it('it provides default values for options', () => {
delete config.options;
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);
@@ -49,7 +49,7 @@ describe('Webhook Model', () => {
it('provides missing task options', () => {
delete config.options.created;
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);
@@ -65,7 +65,7 @@ describe('Webhook Model', () => {
it('discards additional options', () => {
config.options.foo = 'another option';
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);
@@ -79,12 +79,12 @@ describe('Webhook Model', () => {
});
});
['created', 'updated', 'deleted', 'scored', 'checklistScored'].forEach((option) => {
it(`validates that ${option} is a boolean`, (done) => {
['created', 'updated', 'deleted', 'scored', 'checklistScored'].forEach(option => {
it(`validates that ${option} is a boolean`, done => {
config.options[option] = 'not a boolean';
try {
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);
} catch (err) {
@@ -115,7 +115,7 @@ describe('Webhook Model', () => {
it('it provides default values for options', () => {
delete config.options;
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);
@@ -129,7 +129,7 @@ describe('Webhook Model', () => {
it('provides missing user options', () => {
delete config.options.petHatched;
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);
@@ -143,7 +143,7 @@ describe('Webhook Model', () => {
it('discards additional options', () => {
config.options.foo = 'another option';
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);
@@ -155,12 +155,12 @@ describe('Webhook Model', () => {
});
});
['petHatched', 'petHatched', 'leveledUp'].forEach((option) => {
it(`validates that ${option} is a boolean`, (done) => {
['petHatched', 'petHatched', 'leveledUp'].forEach(option => {
it(`validates that ${option} is a boolean`, done => {
config.options[option] = 'not a boolean';
try {
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);
} catch (err) {
@@ -190,7 +190,7 @@ describe('Webhook Model', () => {
it('it provides default values for options', () => {
delete config.options;
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);
@@ -203,7 +203,7 @@ describe('Webhook Model', () => {
it('provides missing user options', () => {
delete config.options.questStarted;
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);
@@ -216,7 +216,7 @@ describe('Webhook Model', () => {
it('discards additional options', () => {
config.options.foo = 'another option';
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);
@@ -227,12 +227,12 @@ describe('Webhook Model', () => {
});
});
['questStarted', 'questFinished'].forEach((option) => {
it(`validates that ${option} is a boolean`, (done) => {
['questStarted', 'questFinished'].forEach(option => {
it(`validates that ${option} is a boolean`, done => {
config.options[option] = 'not a boolean';
try {
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);
} catch (err) {
@@ -259,7 +259,7 @@ describe('Webhook Model', () => {
});
it('creates options', () => {
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);
@@ -269,7 +269,7 @@ describe('Webhook Model', () => {
it('discards additional objects', () => {
config.options.foo = 'another thing';
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);
@@ -279,11 +279,11 @@ describe('Webhook Model', () => {
});
});
it('requires groupId option to be a uuid', (done) => {
it('requires groupId option to be a uuid', done => {
config.options.groupId = 'not a uuid';
try {
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);
} catch (err) {
@@ -310,7 +310,7 @@ describe('Webhook Model', () => {
it('discards additional objects', () => {
config.options.foo = 'another thing';
let wh = new Webhook(config);
const wh = new Webhook(config);
wh.formatOptions(res);