From 05640f513ea64bad28ba3ef3871b09b59010019f Mon Sep 17 00:00:00 2001 From: Keith Holliday Date: Thu, 14 Dec 2017 09:09:11 -0600 Subject: [PATCH] Added test to recreate early cron issue (#9668) * Added test to recreate early cron issue * Gave user extra time based on reverse timezone change --- test/api/v3/unit/models/user.test.js | 44 +++++++++++++++++++++++++++ website/common/script/cron.js | 1 - website/server/models/user/methods.js | 7 ++++- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/test/api/v3/unit/models/user.test.js b/test/api/v3/unit/models/user.test.js index 98abc11a4c..6be822fc8d 100644 --- a/test/api/v3/unit/models/user.test.js +++ b/test/api/v3/unit/models/user.test.js @@ -323,4 +323,48 @@ describe('User Model', () => { expect(user.achievements.beastMaster).to.not.equal(true); }); }); + + context('days missed', () => { + // http://forbrains.co.uk/international_tools/earth_timezones + let user; + + beforeEach(() => { + user = new User(); + }); + + it('should not cron early when going back a timezone', () => { + const yesterday = moment('2017-12-05T00:00:00.000-06:00'); // 11 pm on 4 Texas + const timezoneOffset = moment().zone('-06:00').zone(); + user.lastCron = yesterday; + user.preferences.timezoneOffset = timezoneOffset; + + const today = moment('2017-12-06T00:00:00.000-06:00'); // 11 pm on 4 Texas + const req = {}; + req.header = () => { + return timezoneOffset + 60; + }; + + const {daysMissed} = user.daysUserHasMissed(today, req); + + expect(daysMissed).to.eql(0); + }); + + it('should not cron early when going back a timezone with a custom day start', () => { + const yesterday = moment('2017-12-05T02:00:00.000-08:00'); + const timezoneOffset = moment().zone('-08:00').zone(); + user.lastCron = yesterday; + user.preferences.timezoneOffset = timezoneOffset; + user.preferences.dayStart = 2; + + const today = moment('2017-12-06T02:00:00.000-08:00'); + const req = {}; + req.header = () => { + return timezoneOffset + 60; + }; + + const {daysMissed} = user.daysUserHasMissed(today, req); + + expect(daysMissed).to.eql(0); + }); + }); }); diff --git a/website/common/script/cron.js b/website/common/script/cron.js index 3f38aba433..b93df4b80e 100644 --- a/website/common/script/cron.js +++ b/website/common/script/cron.js @@ -47,7 +47,6 @@ function sanitizeOptions (o) { } let now = o.now ? moment(o.now).zone(timezoneOffset) : moment().zone(timezoneOffset); - // return a new object, we don't want to add "now" to user object return { dayStart, diff --git a/website/server/models/user/methods.js b/website/server/models/user/methods.js index 4f1495168d..909f57d83f 100644 --- a/website/server/models/user/methods.js +++ b/website/server/models/user/methods.js @@ -18,7 +18,6 @@ import paypalPayments from '../../libs/paypalPayments'; const daysSince = common.daysSince; - schema.methods.isSubscribed = function isSubscribed () { let now = new Date(); let plan = this.purchased.plan; @@ -215,6 +214,12 @@ schema.methods.daysUserHasMissed = function daysUserHasMissed (now, req = {}) { let daysMissed = daysSince(this.lastCron, defaults({now}, this.preferences)); if (timezoneOffsetAtLastCron !== timezoneOffsetFromUserPrefs) { + // Give the user extra time based on the difference in timezones + if (timezoneOffsetAtLastCron < timezoneOffsetFromUserPrefs) { + const differenceBetweenTimezonesInMinutes = timezoneOffsetFromUserPrefs - timezoneOffsetAtLastCron; + now = moment(now).subtract(differenceBetweenTimezonesInMinutes, 'minutes'); + } + // Since cron last ran, the user's timezone has changed. // How many days have we missed using the old timezone: let daysMissedNewZone = daysMissed;