haifa-reminder/node_modules/cron/tests/crontime.test.js

648 lines
23 KiB
JavaScript
Executable file

/* eslint-disable no-new */
const sinon = require('sinon');
const luxon = require('luxon');
const cron = require('../lib/cron');
describe('crontime', () => {
it('should test stars (* * * * * *)', () => {
expect(() => {
new cron.CronTime('* * * * * *');
}).not.toThrow();
});
it('should test digit (0 * * * * *)', () => {
expect(() => {
new cron.CronTime('0 * * * * *');
}).not.toThrow();
});
it('should test multi digits (08 * * * * *)', () => {
expect(() => {
new cron.CronTime('08 * * * * *');
}).not.toThrow();
});
it('should test all digits (08 8 8 8 8 5)', () => {
expect(() => {
new cron.CronTime('08 * * * * *');
}).not.toThrow();
});
it('should test too many digits (08 8 8 8 8 5)', () => {
expect(() => {
new cron.CronTime('08 * * * * *');
}).not.toThrow();
});
it('should test standard cron format (* * * * *)', () => {
expect(() => {
new cron.CronTime('* * * * *');
}).not.toThrow();
});
it('should test standard cron format (8 8 8 8 5)', () => {
const standard = new cron.CronTime('8 8 8 8 5');
const extended = new cron.CronTime('0 8 8 8 8 5');
expect(standard.dayOfWeek).toEqual(extended.dayOfWeek);
expect(standard.month).toEqual(extended.month);
expect(standard.dayOfMonth).toEqual(extended.dayOfMonth);
expect(standard.hour).toEqual(extended.hour);
expect(standard.minute).toEqual(extended.minute);
expect(standard.second).toEqual(extended.second);
});
it('should test hyphen (0-10 * * * * *)', () => {
expect(() => {
new cron.CronTime('0-10 * * * * *');
}).not.toThrow();
});
it('should test multi hyphens (0-10 0-10 * * * *)', () => {
expect(() => {
new cron.CronTime('0-10 0-10 * * * *');
}).not.toThrow();
});
it('should test all hyphens (0-10 0-10 1-10 1-10 0-6 0-1)', () => {
expect(() => {
new cron.CronTime('0-10 0-10 1-10 1-10 0-6 0-1');
}).not.toThrow();
});
it('should test comma (0,10 * * * * *)', () => {
expect(() => {
new cron.CronTime('0,10 * * * * *');
}).not.toThrow();
});
it('should test multi commas (0,10 0,10 * * * *)', () => {
expect(() => {
new cron.CronTime('0,10 0,10 * * * *');
}).not.toThrow();
});
it('should test all commas (0,10 0,10 1,10 1,10 0,6 0,1)', () => {
expect(() => {
new cron.CronTime('0,10 0,10 1,10 1,10 0,6 0,1');
}).not.toThrow();
});
it('should test alias (* * * * jan *)', () => {
expect(() => {
new cron.CronTime('* * * * jan *');
}).not.toThrow();
});
it('should test multi aliases (* * * * jan,feb *)', () => {
expect(() => {
new cron.CronTime('* * * * jan,feb *');
}).not.toThrow();
});
it('should test all aliases (* * * * jan,feb mon,tue)', () => {
expect(() => {
new cron.CronTime('* * * * jan,feb mon,tue');
}).not.toThrow();
});
it('should test unknown alias (* * * * jar *)', () => {
expect(() => {
new cron.CronTime('* * * * jar *');
}).toThrow();
});
it('should test unknown alias - short (* * * * j *)', () => {
expect(() => {
new cron.CronTime('* * * * j *');
}).toThrow();
});
it('should test too few fields', () => {
expect(() => {
new cron.CronTime('* * * *', null, null);
}).toThrow();
});
it('should test too many fields', () => {
expect(() => {
new cron.CronTime('* * * * * * *', null, null);
}).toThrow();
});
it('should test out of range values', () => {
expect(() => {
new cron.CronTime('* * * * 1234', null, null);
}).toThrow();
});
it('should test invalid wildcard expression', () => {
expect(() => {
new cron.CronTime('* * * * 0*');
}).toThrow();
});
it('should test invalid step', () => {
expect(() => {
new cron.CronTime('* * * 1/0 *');
}).toThrow();
});
it('should test invalid range', () => {
expect(() => {
new cron.CronTime('* 2-1 * * *');
}).toThrow();
});
it('should test Date', () => {
const d = new Date();
const ct = new cron.CronTime(d);
expect(ct.source.toMillis()).toEqual(d.getTime());
});
it('should test day roll-over', () => {
const numHours = 24;
const ct = new cron.CronTime('0 0 17 * * *');
for (let hr = 0; hr < numHours; hr++) {
const start = new Date(2012, 3, 16, hr, 30, 30);
const next = ct._getNextDateFrom(start);
expect(next - start).toBeLessThan(24 * 60 * 60 * 1000);
expect(next.toMillis()).toBeGreaterThan(start.getTime());
}
});
it('should test illegal repetition syntax', () => {
expect(() => {
new cron.CronTime('* * /4 * * *');
}).toThrow();
});
it('should test next date', () => {
const ct = new cron.CronTime('0 0 */4 * * *');
const nextDate = new Date();
nextDate.setHours(23);
const nextdt = ct._getNextDateFrom(nextDate);
expect(nextdt.toMillis()).toBeGreaterThan(nextDate.getTime());
expect(nextdt.hour % 4).toEqual(0);
});
it('should throw an exception because next date is invalid', () => {
const ct = new cron.CronTime('0 0 * * * *');
const nextDate = new Date('My invalid date string');
try {
ct._getNextDateFrom(nextDate);
} catch (e) {
expect(e.message).toEqual('ERROR: You specified an invalid date.');
}
});
it('should test next real date', () => {
const initialDate = new Date();
initialDate.setDate(initialDate.getDate() + 1); // In other case date will be in the past
const ct = new cron.CronTime(initialDate);
const nextDate = new Date();
nextDate.setMonth(nextDate.getMonth() + 1);
expect(nextDate.getTime()).toBeGreaterThan(ct.source.toMillis());
const nextdt = ct.sendAt(0);
// there shouldn't be a "next date" when using a real date.
// execution happens once
// so the return should be the date passed in unless explicitly reset
expect(nextdt < nextDate).toBeTruthy();
expect(nextdt.toMillis()).toEqual(initialDate.getTime());
});
describe('presets', () => {
it('should parse @secondly', () => {
const cronTime = new cron.CronTime('@secondly');
expect(cronTime.toString()).toEqual('* * * * * *');
});
it('should parse @minutely', () => {
const cronTime = new cron.CronTime('@minutely');
expect(cronTime.toString()).toEqual('0 * * * * *');
});
it('should parse @hourly', () => {
const cronTime = new cron.CronTime('@hourly');
expect(cronTime.toString()).toEqual('0 0 * * * *');
});
it('should parse @daily', () => {
const cronTime = new cron.CronTime('@daily');
expect(cronTime.toString()).toEqual('0 0 0 * * *');
});
it('should parse @weekly', () => {
const cronTime = new cron.CronTime('@weekly');
expect(cronTime.toString()).toEqual('0 0 0 * * 0');
});
it('should parse @weekdays', () => {
const cronTime = new cron.CronTime('@weekdays');
expect(cronTime.toString()).toEqual('0 0 0 * * 1,2,3,4,5');
});
it('should parse @weekends', () => {
const cronTime = new cron.CronTime('@weekends');
expect(cronTime.toString()).toEqual('0 0 0 * * 0,6');
});
it('should parse @monthly', () => {
const cronTime = new cron.CronTime('@monthly');
expect(cronTime.toString()).toEqual('0 0 0 1 * *');
});
it('should parse @yearly', () => {
const cronTime = new cron.CronTime('@yearly');
expect(cronTime.toString()).toEqual('0 0 0 1 0 *');
});
});
describe('should throw an exception because `L` not supported', () => {
it('(* * * L * *)', () => {
expect(() => {
new cron.CronTime('* * * L * *');
}).toThrow();
});
it('(* * * * * L)', () => {
expect(() => {
new cron.CronTime('* * * * * L');
}).toThrow();
});
});
it('should strip off millisecond', () => {
const cronTime = new cron.CronTime('0 */10 * * * *');
const x = cronTime._getNextDateFrom(new Date('2018-08-10T02:20:00.999Z'));
expect(x.toMillis()).toEqual(
new Date('2018-08-10T02:30:00.000Z').getTime()
);
});
it('should strip off millisecond (2)', () => {
const cronTime = new cron.CronTime('0 */10 * * * *');
const x = cronTime._getNextDateFrom(new Date('2018-08-10T02:19:59.999Z'));
expect(x.toMillis()).toEqual(
new Date('2018-08-10T02:20:00.000Z').getTime()
);
});
it('should expose _getNextDateFrom as a public function', () => {
const cronTime = new cron.CronTime('0 */10 * * * *');
cronTime._getNextDateFrom = jest.fn();
const testDate = new Date('2018-08-10T02:19:59.999Z');
const testTimezone = 'Asia/Amman';
cronTime.getNextDateFrom(testDate, testTimezone);
expect(cronTime._getNextDateFrom).toHaveBeenCalledWith(
testDate,
testTimezone
);
});
it('should generate the right next days when cron is set to every minute', () => {
const cronTime = new cron.CronTime('* * * * *');
const min = 60000;
let previousDate = new Date(Date.UTC(2018, 5, 3, 0, 0));
for (let i = 0; i < 25; i++) {
const nextDate = cronTime._getNextDateFrom(previousDate);
expect(nextDate.valueOf()).toEqual(previousDate.valueOf() + min);
previousDate = nextDate;
}
});
it('should generate the right next days when cron is set to every 15 min', () => {
const cronTime = new cron.CronTime('*/15 * * * *');
const min = 60000 * 15;
let previousDate = new Date(Date.UTC(2016, 6, 3, 0, 0));
for (let i = 0; i < 25; i++) {
const nextDate = cronTime._getNextDateFrom(previousDate);
expect(nextDate.valueOf()).toEqual(previousDate.valueOf() + min);
previousDate = nextDate;
}
});
it('should work around time zone changes that shifts time back (1)', () => {
const d = new Date('10-7-2018');
// America/Sao_Paulo has a time zone change around NOV 3 2018.
const cronTime = new cron.CronTime('0 0 9 4 * *');
const nextDate = cronTime._getNextDateFrom(d, 'America/Sao_Paulo');
expect(nextDate.valueOf()).toEqual(
luxon.DateTime.fromISO('2018-11-04T09:00:00.000-02:00').valueOf()
);
});
it('should work around time zone changes that shifts time back (2)', () => {
// Asia/Amman DST ends in 26 - OCT-2018 (-1 to hours)
const currentDate = luxon.DateTime.fromISO('2018-10-25T23:00', {
zone: 'Asia/Amman'
});
const cronTime = new cron.CronTime('0 0 * * *');
const nextDate = cronTime._getNextDateFrom(currentDate, 'Asia/Amman');
const expectedDate = luxon.DateTime.fromISO('2018-10-26T00:00+03:00', {
zone: 'Asia/Amman'
});
expect(nextDate - expectedDate).toEqual(0);
});
it('should work around time zone changes that shifts time forward', () => {
// Asia/Amman DST starts in 30-March-2018 (+1 to hours)
let currentDate = luxon.DateTime.fromISO('2018-03-29T23:00', {
zone: 'Asia/Amman'
});
const cronTime = new cron.CronTime('* * * * *');
for (let i = 0; i < 100; i++) {
const nextDate = cronTime._getNextDateFrom(currentDate, 'Asia/Amman');
expect(nextDate - currentDate).toEqual(1000 * 60);
currentDate = nextDate;
}
});
it('Should schedule jobs inside time zone changes that shifts time forward to the end of the shift, for weekly jobs', () => {
let currentDate = luxon.DateTime.fromISO('2018-03-29T23:15', {
zone: 'Asia/Amman'
});
const cronTime = new cron.CronTime('30 0 * * 5'); // the next 0:30 is March 30th, but it will jump from 0:00 to 1:00.
let nextDate = cronTime._getNextDateFrom(currentDate, 'Asia/Amman');
expect(nextDate - currentDate).toEqual(1000 * 60 * 45); // 45 minutes is 30T00:00, which jumps to 1:00 which is past the trigger of 0:30.
// the next one should just be at 0:30 again. i.e. a week minus 30 minutes.
currentDate = nextDate;
nextDate = cronTime._getNextDateFrom(currentDate);
expect(nextDate - currentDate).toEqual(3600000 * 24 * 7 - 60000 * 30);
// the next one is again at 0:30, but now we're 'back to normal' with weekly offsets.
currentDate = nextDate;
nextDate = cronTime._getNextDateFrom(currentDate);
expect(nextDate - currentDate).toEqual(1000 * 3600 * 24 * 7);
});
it('Should schedule jobs inside time zone changes that shifts the time forward to the end of the shift, for daily jobs', () => {
let currentDate = luxon.DateTime.fromISO('2018-03-29T23:45', {
zone: 'Asia/Amman'
});
const cronTime = new cron.CronTime('30 0 * * *'); // the next 0:30 is March 30th, but it will jump from 0:00 to 1:00.
let nextDate = cronTime._getNextDateFrom(currentDate, 'Asia/Amman');
expect(nextDate - currentDate).toEqual(1000 * 60 * 15); // 15 minutes is 30T00:00, which jumps to 1:00 which is past the trigger of 0:30.
// the next one is tomorrow at 0:30, so 23h30m.
currentDate = nextDate;
nextDate = cronTime._getNextDateFrom(currentDate);
expect(nextDate - currentDate).toEqual(1000 * 3600 * 24 - 1000 * 60 * 30);
// back to normal.
currentDate = nextDate;
nextDate = cronTime._getNextDateFrom(currentDate);
expect(nextDate - currentDate).toEqual(1000 * 3600 * 24);
});
it('Should schedule jobs inside time zone changes that shifts the time forward to the end of the shift, for hourly jobs', () => {
let currentDate = luxon.DateTime.fromISO('2018-03-29T23:45', {
zone: 'Asia/Amman'
});
const cronTime = new cron.CronTime('30 * * * *'); // the next 0:30 is March 30th, but it will jump from 0:00 to 1:00.
let nextDate = cronTime._getNextDateFrom(currentDate, 'Asia/Amman');
expect(nextDate - currentDate).toEqual(1000 * 60 * 15); // 15 minutes is 30T00:00, which jumps to 1:00 which is past the trigger of 0:30.
// the next one is at 1:30, so 30m.
currentDate = nextDate;
nextDate = cronTime._getNextDateFrom(currentDate);
expect(nextDate - currentDate).toEqual(1000 * 60 * 30);
// back to normal.
currentDate = nextDate;
nextDate = cronTime._getNextDateFrom(currentDate);
expect(nextDate - currentDate).toEqual(1000 * 3600);
});
it('Should schedule jobs inside time zone changes that shifts the time forward to the end of the shift, for minutely jobs', () => {
let currentDate = luxon.DateTime.fromISO('2018-03-29T23:59', {
zone: 'Asia/Amman'
});
const cronTime = new cron.CronTime('* * * * *'); // the next minute is 0:00 is March 30th, but it will jump from 0:00 to 1:00.
let nextDate = cronTime._getNextDateFrom(currentDate, 'Asia/Amman');
expect(nextDate - currentDate).toEqual(1000 * 60);
// the next one is at 1:01:00, this should still be 60 seconds in the future.
currentDate = nextDate;
nextDate = cronTime._getNextDateFrom(currentDate);
expect(nextDate - currentDate).toEqual(1000 * 60);
});
// Do not think a similar test for secondly job is necessary, the minutely one already ensured no double hits in the overlap zone.
it('Should throw when dates that are not within 24 hours of DST jumps are checked for past DST jumps', () => {
const cronTime = new cron.CronTime('* * * * *');
const tryFindPastDST = isoTime => () => {
const maybeBadDate = luxon.DateTime.fromISO(isoTime, {
zone: 'Asia/Amman'
});
expect(maybeBadDate.invalid).toEqual(null);
cronTime._findPreviousDSTJump(maybeBadDate);
};
// This timezone jumps from 0:00 to 1:00 on March 30th, so the cutoff is March 31st 1:00:00
expect(tryFindPastDST('2018-03-31T00:59:00')).not.toThrow();
expect(tryFindPastDST('2018-03-31T01:00:00')).toThrow();
});
// The following few DST related tests do not need specific dates that are actually DST,
// the functions they are calling assume the given parameters encapsulate a DST jump,
// and use the raw hour and minute data to check it from there.
it('Should correctly scan time periods as if they are DST jumps, half hour jumps', () => {
let endDate = luxon.DateTime.fromISO('2023-01-01T16:00:00.000', {
zone: 'Europe/Amsterdam'
});
let startDate = endDate.minus({ minute: 30, second: 1 });
const cronTime = new cron.CronTime('5 16 * * *'); // at 16:05:00.
let jobInRange = cronTime._checkTimeInSkippedRange(startDate, endDate);
expect(jobInRange).toEqual(false);
endDate = endDate.plus({ minute: 30 }); // 16:30:00
startDate = endDate.minus({ minute: 30, second: 1 }); // 15:59:59
jobInRange = cronTime._checkTimeInSkippedRange(startDate, endDate);
expect(jobInRange).toEqual(true);
});
it('Should not include seconds in the minute after the DST jump as part of the jump scan', () => {
const endDate = luxon.DateTime.fromISO('2023-01-01T16:00:00.000', {
zone: 'Europe/Amsterdam'
});
// 1 hour jump case
let startDate = endDate.minus({ hour: 1, second: 1 });
const cronTime = new cron.CronTime('1 5 16 * * *'); // at 16:00:01.
let jobInRange = cronTime._checkTimeInSkippedRange(startDate, endDate);
expect(jobInRange).toEqual(false);
// 'quirky' jump case
startDate = endDate.minus({ hour: 1, minute: 45, second: 1 });
jobInRange = cronTime._checkTimeInSkippedRange(startDate, endDate);
expect(jobInRange).toEqual(false);
});
it('Should correctly scan time periods as if they are DST jumps, full hour jumps', () => {
let endDate = luxon.DateTime.fromISO('2023-01-01T16:00:00.000', {
zone: 'Europe/Amsterdam'
});
let startDate = endDate.minus({ hour: 1, second: 1 });
const cronTime = new cron.CronTime('5 16 * * *'); // at 16:05:00.
let jobInRange = cronTime._checkTimeInSkippedRange(startDate, endDate);
expect(jobInRange).toEqual(false);
endDate = endDate.plus({ hour: 1 }); // 17:00:00
startDate = endDate.minus({ hour: 1, second: 1 }); // 15:59:59
jobInRange = cronTime._checkTimeInSkippedRange(startDate, endDate);
expect(jobInRange).toEqual(true);
});
// A 'quirky' DST jump is one that should not break the implementation, but does not exist in real life (yet)
it('Should correctly scan time periods as if they are DST jumps, quirky jumps (1)', () => {
// Testing a jump that is less than an hour long, but wraps around an hour.
let endDate = luxon.DateTime.fromISO('2023-01-01T16:15:00.000', {
zone: 'Europe/Amsterdam'
});
let startDate = endDate.minus({ minute: 45, second: 1 }); // 15:29:59
const cronTime = new cron.CronTime('30 16 * * *'); // at 16:30:00.
let jobInRange = cronTime._checkTimeInSkippedRange(startDate, endDate);
expect(jobInRange).toEqual(false);
endDate = endDate.plus({ minute: 30 }); // 16:45:00
startDate = endDate.minus({ minute: 50, second: 1 }); // 15:54:59
jobInRange = cronTime._checkTimeInSkippedRange(startDate, endDate);
expect(jobInRange).toEqual(true);
});
it('Should correctly scan time periods as if they are DST jumps, quirky jumps (2)', () => {
// Testing a jump that is over an hour long.
let endDate = luxon.DateTime.fromISO('2023-01-01T16:15:00.000', {
zone: 'Europe/Amsterdam'
});
let startDate = endDate.minus({ hour: 3, minute: 45, second: 1 }); // 12:29:59
const cronTime = new cron.CronTime('30 16 * * *'); // at 16:30:00.
let jobInRange = cronTime._checkTimeInSkippedRange(startDate, endDate);
expect(jobInRange).toEqual(false);
endDate = endDate.plus({ minute: 30 }); // 16:45:00
startDate = endDate.minus({ hour: 3, minute: 45, second: 1 }); // 12:59:59
jobInRange = cronTime._checkTimeInSkippedRange(startDate, endDate);
expect(jobInRange).toEqual(true);
});
it('Enforces the hour difference assumption for handling multi-hour DST jumps', () => {
const cronTime = new cron.CronTime('30 16 * * *');
expect(() => {
cronTime._checkTimeInSkippedRangeMultiHour(15, 0, 15, 30);
}).toThrow();
});
it('should generate the right N next days for * * * * *', () => {
const cronTime = new cron.CronTime('* * * * *');
let currentDate = luxon.DateTime.local().set({ second: 0, millisecond: 0 });
for (let i = 0; i < 100; i++) {
const nextDate = cronTime._getNextDateFrom(currentDate);
expect(nextDate - currentDate).toEqual(1000 * 60);
currentDate = nextDate;
}
});
it('should generate the right N next days for 0 0 9 * * *', () => {
const cronTime = new cron.CronTime('0 0 9 * * *');
let currentDate = luxon.DateTime.local()
.setZone('utc')
.set({ hour: 9, minute: 0, second: 0, millisecond: 0 });
for (let i = 0; i < 100; i++) {
const nextDate = cronTime._getNextDateFrom(currentDate);
expect(nextDate - currentDate).toEqual(1000 * 60 * 60 * 24);
currentDate = nextDate;
}
});
it('should generate the right N next days for 0 0 * * * with a time zone', () => {
const cronTime = new cron.CronTime('0 * * * *');
let currentDate = luxon.DateTime.fromISO('2018-11-02T23:00', {
zone: 'America/Sao_Paulo'
}).set({ second: 0, millisecond: 0 });
for (let i = 0; i < 25; i++) {
const nextDate = cronTime._getNextDateFrom(
currentDate,
'America/Sao_Paulo'
);
expect(nextDate - currentDate).toEqual(1000 * 60 * 60);
currentDate = nextDate;
}
});
it('should generate the right N next days for */3 * * * * with a time zone', () => {
const cronTime = new cron.CronTime('*/3 * * * *');
let currentDate = luxon.DateTime.fromISO('2018-11-02T23:00', {
zone: 'America/Sao_Paulo'
}).set({ second: 0, millisecond: 0 });
for (let i = 0; i < 25; i++) {
const nextDate = cronTime._getNextDateFrom(
currentDate,
'America/Sao_Paulo'
);
expect(nextDate - currentDate).toEqual(1000 * 60 * 3);
currentDate = nextDate;
}
});
it('should generate the right next day when cron is set to every 15 min in Feb', () => {
const cronTime = new cron.CronTime('*/15 * * FEB *');
const previousDate = new Date(Date.UTC(2018, 3, 0, 0, 0));
const nextDate = cronTime._getNextDateFrom(previousDate, 'UTC');
expect(nextDate.valueOf()).toEqual(
new Date(Date.UTC(2019, 1, 1, 0, 0)).valueOf()
);
});
it('should generate the right next day when cron is set to both day of the month and day of the week (1)', () => {
const cronTime = new cron.CronTime('0 8 1 * 4');
const previousDate = new Date(Date.UTC(2019, 3, 21, 0, 0));
const nextDate = cronTime._getNextDateFrom(previousDate, 'UTC');
expect(nextDate.toMillis()).toEqual(
new Date(Date.UTC(2019, 3, 25, 8, 0)).getTime()
);
});
it('should generate the right next day when cron is set to both day of the month and day of the week (2)', () => {
const cronTime = new cron.CronTime('0 8 1 * 4');
const previousDate = new Date(Date.UTC(2019, 3, 26, 0, 0));
const nextDate = cronTime._getNextDateFrom(previousDate, 'UTC');
expect(nextDate.toMillis()).toEqual(
new Date(Date.UTC(2019, 4, 1, 8, 0)).getTime()
);
});
it('should generate the right next day when cron is set to both day of the month and day of the week (3)', () => {
const cronTime = new cron.CronTime('0 8 1 * 4');
const previousDate = new Date(Date.UTC(2019, 7, 1, 7, 59));
const nextDate = cronTime._getNextDateFrom(previousDate, 'UTC');
expect(nextDate.valueOf()).toEqual(
new Date(Date.UTC(2019, 7, 1, 8, 0)).valueOf()
);
});
it('should accept 0 as a valid UTC offset', () => {
const clock = sinon.useFakeTimers();
const cronTime = new cron.CronTime('0 11 * * *', null, 0);
const expected = luxon.DateTime.local().plus({ hours: 11 }).toSeconds();
const actual = cronTime.sendAt().toSeconds();
expect(actual).toEqual(expected);
clock.restore();
});
it('should accept -120 as a valid UTC offset', () => {
const clock = sinon.useFakeTimers();
const cronTime = new cron.CronTime('0 11 * * *', null, -120);
const expected = luxon.DateTime.local().plus({ hours: 13 }).toSeconds();
const actual = cronTime.sendAt().toSeconds();
expect(actual).toEqual(expected);
clock.restore();
});
it('should accept 4 as a valid UTC offset', () => {
const clock = sinon.useFakeTimers();
const cronTime = new cron.CronTime('0 11 * * *', null, 5);
const expected = luxon.DateTime.local().plus({ hours: 6 }).toSeconds();
const actual = cronTime.sendAt().toSeconds();
expect(actual).toEqual(expected);
clock.restore();
});
it('should detect real date in the past', () => {
const clock = sinon.useFakeTimers();
const d = new Date();
clock.tick(1000);
const time = new cron.CronTime(d);
expect(() => {
time.sendAt();
}).toThrow();
clock.restore();
});
});