Skip to content

Commit

Permalink
Add test for updateScheduledNotifs to test if notifs successfully get…
Browse files Browse the repository at this point in the history
… scheduled

- There were many places where I used to/fromMillis instead of to/fromJSDate, causing a type difference that was causing errors
- Added a i18n mock because not having a language code return was messing with the debugScheduledNotifs log outputs
- Added a funcitonality for mockNotifs in the test, so that it can be adjusted, cleared, added to, etc. so that we can test with getScheduledNotifs if it successfully scheduled the notifs
  • Loading branch information
sebastianbarry committed Dec 15, 2023
1 parent d3750c3 commit ec9729d
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 38 deletions.
82 changes: 50 additions & 32 deletions www/__tests__/notifScheduler.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { mockReminders } from '../__mocks__/cordovaMocks';
import { mockLogger } from '../__mocks__/globalMocks';
import i18next from 'i18next';
import { logDebug } from '../js/plugin/logger';
import { DateTime } from 'luxon';
import { getUser, updateUser } from '../js/services/commHelper';
Expand Down Expand Up @@ -62,6 +63,10 @@ const exampleReminderSchemes = {
mockLogger();
mockReminders();

jest.mock('i18next', () => ({
resolvedLanguage: 'en',
}));

jest.mock('../js/services/commHelper', () => ({
getUser: jest.fn(),
updateUser: jest.fn(),
Expand Down Expand Up @@ -98,12 +103,12 @@ describe('getScheduledNotifs', () => {
const isScheduling = false;
const scheduledPromise = Promise.resolve();
// create the mock notifs from cordova plugin
const mockNotifs = [{ trigger: { at: DateTime.now().toMillis() } }];
const mockNotifs = [{ trigger: { at: DateTime.now().toJSDate() } }];
// create the expected result
const expectedResult = [
{
key: DateTime.fromMillis(mockNotifs[0].trigger.at).toFormat('DDD'),
val: DateTime.fromMillis(mockNotifs[0].trigger.at).toFormat('t'),
key: DateTime.fromJSDate(mockNotifs[0].trigger.at).toFormat('DDD'),
val: DateTime.fromJSDate(mockNotifs[0].trigger.at).toFormat('t'),
},
];

Expand All @@ -122,12 +127,12 @@ describe('getScheduledNotifs', () => {
const isScheduling = true;
const scheduledPromise = Promise.resolve();
// create the mock notifs from cordova plugin
const mockNotifs = [{ trigger: { at: DateTime.now().toMillis() } }];
const mockNotifs = [{ trigger: { at: DateTime.now().toJSDate() } }];
// create the expected result
const expectedResult = [
{
key: DateTime.fromMillis(mockNotifs[0].trigger.at).toFormat('DDD'),
val: DateTime.fromMillis(mockNotifs[0].trigger.at).toFormat('t'),
key: DateTime.fromJSDate(mockNotifs[0].trigger.at).toFormat('DDD'),
val: DateTime.fromJSDate(mockNotifs[0].trigger.at).toFormat('t'),
},
];

Expand Down Expand Up @@ -166,36 +171,36 @@ describe('getScheduledNotifs', () => {
const scheduledPromise = Promise.resolve();
// create the mock notifs from cordova plugin (greater than 5 notifications)
const mockNotifs = [
{ trigger: { at: DateTime.now().toMillis() } },
{ trigger: { at: DateTime.now().plus({ weeks: 1 }).toMillis() } },
{ trigger: { at: DateTime.now().plus({ weeks: 2 }).toMillis() } },
{ trigger: { at: DateTime.now().plus({ weeks: 3 }).toMillis() } },
{ trigger: { at: DateTime.now().plus({ weeks: 4 }).toMillis() } },
{ trigger: { at: DateTime.now().plus({ weeks: 5 }).toMillis() } },
{ trigger: { at: DateTime.now().plus({ weeks: 6 }).toMillis() } },
{ trigger: { at: DateTime.now().plus({ weeks: 7 }).toMillis() } },
{ trigger: { at: DateTime.now().toJSDate() } },
{ trigger: { at: DateTime.now().plus({ weeks: 1 }).toJSDate() } },
{ trigger: { at: DateTime.now().plus({ weeks: 2 }).toJSDate() } },
{ trigger: { at: DateTime.now().plus({ weeks: 3 }).toJSDate() } },
{ trigger: { at: DateTime.now().plus({ weeks: 4 }).toJSDate() } },
{ trigger: { at: DateTime.now().plus({ weeks: 5 }).toJSDate() } },
{ trigger: { at: DateTime.now().plus({ weeks: 6 }).toJSDate() } },
{ trigger: { at: DateTime.now().plus({ weeks: 7 }).toJSDate() } },
];
// create the expected result (only the first 5 notifications)
const expectedResult = [
{
key: DateTime.fromMillis(mockNotifs[0].trigger.at).toFormat('DDD'),
val: DateTime.fromMillis(mockNotifs[0].trigger.at).toFormat('t'),
key: DateTime.fromJSDate(mockNotifs[0].trigger.at as Date).toFormat('DDD'),
val: DateTime.fromJSDate(mockNotifs[0].trigger.at as Date).toFormat('t'),
},
{
key: DateTime.fromMillis(mockNotifs[1].trigger.at).toFormat('DDD'),
val: DateTime.fromMillis(mockNotifs[1].trigger.at).toFormat('t'),
key: DateTime.fromJSDate(mockNotifs[1].trigger.at as Date).toFormat('DDD'),
val: DateTime.fromJSDate(mockNotifs[1].trigger.at as Date).toFormat('t'),
},
{
key: DateTime.fromMillis(mockNotifs[2].trigger.at).toFormat('DDD'),
val: DateTime.fromMillis(mockNotifs[2].trigger.at).toFormat('t'),
key: DateTime.fromJSDate(mockNotifs[2].trigger.at as Date).toFormat('DDD'),
val: DateTime.fromJSDate(mockNotifs[2].trigger.at as Date).toFormat('t'),
},
{
key: DateTime.fromMillis(mockNotifs[3].trigger.at).toFormat('DDD'),
val: DateTime.fromMillis(mockNotifs[3].trigger.at).toFormat('t'),
key: DateTime.fromJSDate(mockNotifs[3].trigger.at as Date).toFormat('DDD'),
val: DateTime.fromJSDate(mockNotifs[3].trigger.at as Date).toFormat('t'),
},
{
key: DateTime.fromMillis(mockNotifs[4].trigger.at).toFormat('DDD'),
val: DateTime.fromMillis(mockNotifs[4].trigger.at).toFormat('t'),
key: DateTime.fromJSDate(mockNotifs[4].trigger.at as Date).toFormat('DDD'),
val: DateTime.fromJSDate(mockNotifs[4].trigger.at as Date).toFormat('t'),
},
];

Expand Down Expand Up @@ -237,25 +242,38 @@ describe('updateScheduledNotifs', () => {
const setIsScheduling: Function = jest.fn((val: boolean) => (isScheduling = val));
const scheduledPromise: Promise<any> = Promise.resolve();
// create an empty array of mock notifs from cordova plugin
const mockNotifs = [];
let mockNotifs = [];

// mock the cordova plugin
jest
.spyOn(window['cordova'].plugins.notification.local, 'getScheduled')
.mockImplementation((callback) => callback(mockNotifs));
jest
.spyOn(window['cordova'].plugins.notification.local, 'cancelAll')
.mockImplementation((callback) => callback());
.mockImplementation((callback) => {
mockNotifs = [];
callback();
});
jest
.spyOn(window['cordova'].plugins.notification.local, 'schedule')
.mockImplementation((arg, callback) => callback(arg));
.mockImplementation((arg, callback) => {
arg.forEach((notif) => {
mockNotifs.push(notif);
});
console.log('called mockNotifs.concat(arg)', mockNotifs);
callback(arg);
});
// call the function
await updateScheduledNotifs(reminderSchemes, isScheduling, setIsScheduling, scheduledPromise);
const scheduledNotifs = await getScheduledNotifs(isScheduling, scheduledPromise);

expect(setIsScheduling).toHaveBeenCalledWith(true);
expect(logDebug).toHaveBeenCalledWith('After cancelling, there are no scheduled notifications');
expect(logDebug).toHaveBeenCalledWith('After scheduling, there are no scheduled notifications');
expect(logDebug).toHaveBeenCalledWith(
'After scheduling, there are 4 scheduled notifications at 21:00 first is November 19, 2023 at 9:00 PM',
);
expect(setIsScheduling).toHaveBeenCalledWith(false);
expect(scheduledNotifs).toHaveLength(4);
});

it('should resolve without scheduling if notifications are already scheduled', async () => {
Expand All @@ -267,10 +285,10 @@ describe('updateScheduledNotifs', () => {
// create the mock notifs from cordova plugin (must match the notifs that will generate from the reminder scheme above...
// in this case: exampleReminderSchemes.weekly, because getUser is mocked to return reminder_assignment: 'weekly')
const mockNotifs = [
{ trigger: { at: DateTime.fromFormat('2023-11-14 21:00', 'yyyy-MM-dd HH:mm').toMillis() } },
{ trigger: { at: DateTime.fromFormat('2023-11-15 21:00', 'yyyy-MM-dd HH:mm').toMillis() } },
{ trigger: { at: DateTime.fromFormat('2023-11-17 21:00', 'yyyy-MM-dd HH:mm').toMillis() } },
{ trigger: { at: DateTime.fromFormat('2023-11-19 21:00', 'yyyy-MM-dd HH:mm').toMillis() } },
{ trigger: { at: DateTime.fromFormat('2023-11-14 21:00', 'yyyy-MM-dd HH:mm').toJSDate() } },
{ trigger: { at: DateTime.fromFormat('2023-11-15 21:00', 'yyyy-MM-dd HH:mm').toJSDate() } },
{ trigger: { at: DateTime.fromFormat('2023-11-17 21:00', 'yyyy-MM-dd HH:mm').toJSDate() } },
{ trigger: { at: DateTime.fromFormat('2023-11-19 21:00', 'yyyy-MM-dd HH:mm').toJSDate() } },
];

// mock the cordova plugin
Expand Down
12 changes: 6 additions & 6 deletions www/js/splash/notifScheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const calcNotifTimes = (scheme, dayZeroDate, timeOfDay): DateTime[] => {
// returns true if all expected times are already scheduled
const areAlreadyScheduled = (notifs: any[], expectedTimes: DateTime[]) => {
for (const t of expectedTimes) {
if (!notifs.some((n) => DateTime.fromMillis(n.trigger.at).equals(t))) {
if (!notifs.some((n) => DateTime.fromJSDate(n.trigger.at).equals(t))) {
return false;
}
}
Expand All @@ -54,12 +54,12 @@ const areAlreadyScheduled = (notifs: any[], expectedTimes: DateTime[]) => {
function debugGetScheduled(prefix) {
window['cordova'].plugins.notification.local.getScheduled((notifs) => {
if (!notifs?.length) return logDebug(`${prefix}, there are no scheduled notifications`);
const time = DateTime.fromMillis(notifs?.[0].trigger.at).toFormat('HH:mm');
const time = DateTime.fromJSDate(notifs[0].trigger.at).toFormat('HH:mm');
//was in plugin, changed to scheduler
let scheduledNotifs = [];
scheduledNotifs = notifs.map((n) => {
const time = DateTime.fromMillis(n.trigger.at).toFormat('t');
const date = DateTime.fromMillis(n.trigger.at).toFormat('DDD');
const date = DateTime.fromJSDate(n.trigger.at).toFormat('DDD');
const time = DateTime.fromJSDate(n.trigger.at).toFormat('t');
return {
key: date,
val: time,
Expand Down Expand Up @@ -109,8 +109,8 @@ const getNotifs = function () {
const notifSubset = notifs.slice(0, 5); //prevent near-infinite listing
let scheduledNotifs = [];
scheduledNotifs = notifSubset.map((n) => {
const time: string = DateTime.fromMillis(n.trigger.at).toFormat('t');
const date: string = DateTime.fromMillis(n.trigger.at).toFormat('DDD');
const time: string = DateTime.fromJSDate(n.trigger.at).toFormat('t');
const date: string = DateTime.fromJSDate(n.trigger.at).toFormat('DDD');
return {
key: date,
val: time,
Expand Down

0 comments on commit ec9729d

Please sign in to comment.