mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 06:37:23 +01:00
Remove localstorage and add notifications (#7588)
* move remaining files frm /common/script/public to website/public * remove localstorage * add back noscript template and put all javascript in the footer * fixes client side tests * remove double quotes where possible * simplify jade code and add tests for buildManifest * loading page with logo and spinner * better loading screen in landscape mode * icon on top of text logo * wip: user.notifications * notifications: simpler and working code * finish implementing notifications * correct loading screen css and re-inline images * add tests for user notifications * split User model in multiple files * remove old comment about missing .catch() * correctly setup hooks and methods for User model. Cleanup localstorage * include UserNotificationsService in static page js and split loading-screen css in its own file * add cron notification and misc fixes * remove console.log * fix tests * fix multiple notifications
This commit is contained in:
@@ -100,6 +100,8 @@ describe('POST /challenges/:challengeId/winner/:winnerId', () => {
|
||||
await sleep(0.5);
|
||||
|
||||
await expect(winningUser.sync()).to.eventually.have.deep.property('achievements.challenges').to.include(challenge.name);
|
||||
expect(winningUser.notifications.length).to.equal(1);
|
||||
expect(winningUser.notifications[0].type).to.equal('WON_CHALLENGE');
|
||||
});
|
||||
|
||||
it('gives winner gems as reward', async () => {
|
||||
|
||||
@@ -17,16 +17,19 @@ describe('GET /export/history.csv', () => {
|
||||
]);
|
||||
|
||||
// score all the tasks twice
|
||||
await Promise.all(tasks.map(task => {
|
||||
return user.post(`/tasks/${task._id}/score/up`);
|
||||
}));
|
||||
await Promise.all(tasks.map(task => {
|
||||
return user.post(`/tasks/${task._id}/score/up`);
|
||||
}));
|
||||
await user.post(`/tasks/${tasks[0]._id}/score/up`);
|
||||
await user.post(`/tasks/${tasks[1]._id}/score/up`);
|
||||
await user.post(`/tasks/${tasks[2]._id}/score/up`);
|
||||
await user.post(`/tasks/${tasks[3]._id}/score/up`);
|
||||
|
||||
await user.post(`/tasks/${tasks[0]._id}/score/up`);
|
||||
await user.post(`/tasks/${tasks[1]._id}/score/up`);
|
||||
await user.post(`/tasks/${tasks[2]._id}/score/up`);
|
||||
await user.post(`/tasks/${tasks[3]._id}/score/up`);
|
||||
|
||||
// adding an history entry to daily 1 manually because cron didn't run yet
|
||||
await updateDocument('tasks', tasks[1], {
|
||||
history: {value: 3.2, date: Number(new Date())},
|
||||
history: [{value: 3.2, date: Number(new Date())}],
|
||||
});
|
||||
|
||||
// get updated tasks
|
||||
|
||||
@@ -68,6 +68,8 @@ describe('PUT /heroes/:heroId', () => {
|
||||
expect(hero.contributor.level).to.equal(1);
|
||||
expect(hero.purchased.ads).to.equal(true);
|
||||
expect(hero.auth.blocked).to.equal(true);
|
||||
expect(hero.notifications.length).to.equal(1);
|
||||
expect(hero.notifications[0].type).to.equal('NEW_CONTRIBUTOR_LEVEL');
|
||||
});
|
||||
|
||||
it('updates contributor level', async () => {
|
||||
|
||||
@@ -46,6 +46,9 @@ describe('POST /user/rebirth', () => {
|
||||
let response = await user.post('/user/rebirth');
|
||||
await user.sync();
|
||||
|
||||
expect(user.notifications.length).to.equal(1);
|
||||
expect(user.notifications[0].type).to.equal('REBIRTH_ACHIEVEMENT');
|
||||
|
||||
let updatedDaily = await user.get(`/tasks/${daily._id}`);
|
||||
let updatedReward = await user.get(`/tasks/${reward._id}`);
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ describe('PUT /user', () => {
|
||||
backer: {'backer.tier': 10, 'backer.npc': 'Bilbo'},
|
||||
subscriptions: {'purchased.plan.extraMonths': 500, 'purchased.plan.consecutive.trinkets': 1000},
|
||||
'customization gem purchases': {'purchased.background.tavern': true, 'purchased.skin.bear': true},
|
||||
notifications: [{type: 123}],
|
||||
};
|
||||
|
||||
each(protectedOperations, (data, testName) => {
|
||||
|
||||
@@ -10,6 +10,18 @@ describe('Build Manifest', () => {
|
||||
expect(htmlCode.startsWith('<script') || htmlCode.startsWith('<link')).to.be.true;
|
||||
});
|
||||
|
||||
it('can return only js files', () => {
|
||||
let htmlCode = getManifestFiles('app', 'js');
|
||||
|
||||
expect(htmlCode.indexOf('<link') === -1).to.be.true;
|
||||
});
|
||||
|
||||
it('can return only css files', () => {
|
||||
let htmlCode = getManifestFiles('app', 'css');
|
||||
|
||||
expect(htmlCode.indexOf('<script') === -1).to.be.true;
|
||||
});
|
||||
|
||||
it('throws an error in case the page does not exist', () => {
|
||||
expect(() => {
|
||||
getManifestFiles('strange name here');
|
||||
|
||||
@@ -517,6 +517,60 @@ describe('cron', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('notifications', () => {
|
||||
it('adds a user notification', () => {
|
||||
let mpBefore = user.stats.mp;
|
||||
tasksByType.dailys[0].completed = true;
|
||||
user._statsComputed.maxMP = 100;
|
||||
|
||||
daysMissed = 1;
|
||||
let hpBefore = user.stats.hp;
|
||||
tasksByType.dailys[0].startDate = moment(new Date()).subtract({days: 1});
|
||||
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
|
||||
expect(user.notifications.length).to.equal(1);
|
||||
expect(user.notifications[0].type).to.equal('CRON');
|
||||
expect(user.notifications[0].data).to.eql({
|
||||
hp: user.stats.hp - hpBefore,
|
||||
mp: user.stats.mp - mpBefore,
|
||||
});
|
||||
});
|
||||
|
||||
it('condenses multiple notifications into one', () => {
|
||||
let mpBefore1 = user.stats.mp;
|
||||
tasksByType.dailys[0].completed = true;
|
||||
user._statsComputed.maxMP = 100;
|
||||
|
||||
daysMissed = 1;
|
||||
let hpBefore1 = user.stats.hp;
|
||||
tasksByType.dailys[0].startDate = moment(new Date()).subtract({days: 1});
|
||||
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
|
||||
expect(user.notifications.length).to.equal(1);
|
||||
expect(user.notifications[0].type).to.equal('CRON');
|
||||
expect(user.notifications[0].data).to.eql({
|
||||
hp: user.stats.hp - hpBefore1,
|
||||
mp: user.stats.mp - mpBefore1,
|
||||
});
|
||||
|
||||
let hpBefore2 = user.stats.hp;
|
||||
let mpBefore2 = user.stats.mp;
|
||||
|
||||
user.lastCron = moment(new Date()).subtract({days: 2});
|
||||
|
||||
cron({user, tasksByType, daysMissed, analytics});
|
||||
|
||||
expect(user.notifications.length).to.equal(1);
|
||||
expect(user.notifications[0].type).to.equal('CRON');
|
||||
expect(user.notifications[0].data).to.eql({
|
||||
hp: user.stats.hp - hpBefore2 - (hpBefore2 - hpBefore1),
|
||||
mp: user.stats.mp - mpBefore2 - (mpBefore2 - mpBefore1),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('private messages', () => {
|
||||
let lastMessageId;
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ describe('response middleware', () => {
|
||||
expect(res.json).to.be.calledWith({
|
||||
success: true,
|
||||
data: {field: 1},
|
||||
notifications: [],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -47,6 +48,7 @@ describe('response middleware', () => {
|
||||
success: true,
|
||||
data: {field: 1},
|
||||
message: 'hello',
|
||||
notifications: [],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -61,6 +63,45 @@ describe('response middleware', () => {
|
||||
expect(res.json).to.be.calledWith({
|
||||
success: false,
|
||||
data: {field: 1},
|
||||
notifications: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('returns userV if a user is authenticated req.query.userV is passed', () => {
|
||||
responseMiddleware(req, res, next);
|
||||
req.query.userV = 3;
|
||||
res.respond(200, {field: 1});
|
||||
|
||||
expect(res.json).to.be.calledOnce;
|
||||
|
||||
expect(res.json).to.be.calledWith({
|
||||
success: true,
|
||||
data: {field: 1},
|
||||
notifications: [],
|
||||
userV: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns notifications if a user is authenticated', () => {
|
||||
res.locals.user.notifications.push({type: 'NEW_CONTRIBUTOR_LEVEL'});
|
||||
let notification = res.locals.user.notifications[0].toJSON();
|
||||
|
||||
responseMiddleware(req, res, next);
|
||||
res.respond(200, {field: 1});
|
||||
|
||||
expect(res.json).to.be.calledOnce;
|
||||
|
||||
expect(res.json).to.be.calledWith({
|
||||
success: true,
|
||||
data: {field: 1},
|
||||
notifications: [
|
||||
{
|
||||
type: notification.type,
|
||||
id: notification.id,
|
||||
createdAt: notification.createdAt,
|
||||
data: {},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -30,4 +30,30 @@ describe('User Model', () => {
|
||||
expect(toJSON._tmp).to.eql({ok: true});
|
||||
expect(toJSON).to.not.have.keys('_nonTmp');
|
||||
});
|
||||
|
||||
context('notifications', () => {
|
||||
it('can add notifications with data', () => {
|
||||
let user = new User();
|
||||
|
||||
user.addNotification('CRON');
|
||||
|
||||
let userToJSON = user.toJSON();
|
||||
expect(user.notifications.length).to.equal(1);
|
||||
expect(userToJSON.notifications[0]).to.have.all.keys(['data', 'id', 'type', 'createdAt']);
|
||||
expect(userToJSON.notifications[0].type).to.equal('CRON');
|
||||
expect(userToJSON.notifications[0].data).to.eql({});
|
||||
});
|
||||
|
||||
it('can add notifications without data', () => {
|
||||
let user = new User();
|
||||
|
||||
user.addNotification('CRON', {field: 1});
|
||||
|
||||
let userToJSON = user.toJSON();
|
||||
expect(user.notifications.length).to.equal(1);
|
||||
expect(userToJSON.notifications[0]).to.have.all.keys(['data', 'id', 'type', 'createdAt']);
|
||||
expect(userToJSON.notifications[0].type).to.equal('CRON');
|
||||
expect(userToJSON.notifications[0].data).to.eql({field: 1});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user