Skip to content

Commit

Permalink
Merge pull request #1093 from Abby-Wheelis/event-notif-rewrite
Browse files Browse the repository at this point in the history
🎟️ πŸ”” πŸ“± Custom Events + pushNotify + storeDeviceSettings + remoteNotify rewrites
  • Loading branch information
shankari authored Nov 10, 2023
2 parents db08c76 + 77d2ad1 commit ccb50c5
Show file tree
Hide file tree
Showing 20 changed files with 983 additions and 450 deletions.
53 changes: 53 additions & 0 deletions www/__mocks__/cordovaMocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const mockBEMUserCache = () => {
return new Promise<void>((rs, rj) =>
setTimeout(() => {
for (let p in _cache) delete _cache[p];
for (let doc in _storage) delete _storage[doc];
rs();
}, 100),
);
Expand Down Expand Up @@ -129,7 +130,59 @@ export const mockBEMDataCollection = () => {
_storage['config/consent'] = consentDoc;
}, 100);
},
getConfig: () => {
return new Promise<any>((rs, rj) => {
setTimeout(() => {
rs({ ios_use_remote_push_for_sync: true });
}, 100);
});
},
handleSilentPush: () => {
return new Promise<void>((rs, rj) =>
setTimeout(() => {
rs();
}, 100),
);
},
};
window['cordova'] ||= {};
window['cordova'].plugins.BEMDataCollection = mockBEMDataCollection;
};

export const mockBEMServerCom = () => {
const mockBEMServerCom = {
postUserPersonalData: (actionString, typeString, updateDoc, rs, rj) => {
setTimeout(() => {
console.log('set in mock', updateDoc);
_storage['user_data'] = updateDoc;
rs();
}, 100);
},

getUserPersonalData: (actionString, rs, rj) => {
setTimeout(() => {
rs(_storage['user_data']);
}, 100);
},
};
window['cordova'].plugins.BEMServerComm = mockBEMServerCom;
};

let _url_stash = '';

export const mockInAppBrowser = () => {
const mockInAppBrowser = {
open: (url: string, mode: string, options: {}) => {
_url_stash = url;
},
};
window['cordova'].InAppBrowser = mockInAppBrowser;
};

export const getURL = () => {
return _url_stash;
};

export const clearURL = () => {
_url_stash = '';
};
16 changes: 16 additions & 0 deletions www/__mocks__/globalMocks.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
export const mockLogger = () => {
window['Logger'] = { log: console.log };
};

let alerts = [];

export const mockAlert = () => {
window['alert'] = (message) => {
alerts.push(message);
};
};

export const clearAlerts = () => {
alerts = [];
};

export const getAlerts = () => {
return alerts;
};
33 changes: 33 additions & 0 deletions www/__mocks__/pushNotificationMocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
let notifSettings;
let onList: any = {};
let called = null;

export const mockPushNotification = () => {
window['PushNotification'] = {
init: (settings: Object) => {
notifSettings = settings;
return {
on: (event: string, callback: Function) => {
onList[event] = callback;
},
finish: (content: any, errorFcn: Function, notID: any) => {
called = notID;
},
};
},
};
};

export const clearNotifMock = function () {
notifSettings = {};
onList = {};
called = null;
};

export const getOnList = function () {
return onList;
};

export const getCalled = function () {
return called;
};
24 changes: 24 additions & 0 deletions www/__tests__/customEventHandler.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { publish, subscribe, unsubscribe } from '../js/customEventHandler';
import { mockLogger } from '../__mocks__/globalMocks';

mockLogger();

it('subscribes and publishes to an event', () => {
const listener = jest.fn();
subscribe('test', listener);
publish('test', 'test data');
expect(listener).toHaveBeenCalledWith(
expect.objectContaining({
type: 'test',
detail: 'test data',
}),
);
});

it('can unsubscribe', () => {
const listener = jest.fn();
subscribe('test', listener);
unsubscribe('test', listener);
publish('test', 'test data');
expect(listener).not.toHaveBeenCalled();
});
119 changes: 119 additions & 0 deletions www/__tests__/pushNotifySettings.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { DateTime } from 'luxon';
import { EVENTS, publish } from '../js/customEventHandler';
import { INTRO_DONE_KEY, readIntroDone } from '../js/onboarding/onboardingHelper';
import { storageSet } from '../js/plugin/storage';
import { initPushNotify } from '../js/splash/pushNotifySettings';
import { mockCordova, mockBEMUserCache, mockBEMDataCollection } from '../__mocks__/cordovaMocks';
import { mockLogger } from '../__mocks__/globalMocks';
import {
clearNotifMock,
getOnList,
mockPushNotification,
getCalled,
} from '../__mocks__/pushNotificationMocks';

mockCordova();
mockLogger();
mockPushNotification();
mockBEMUserCache();
mockBEMDataCollection();

global.fetch = (url: string) =>
new Promise((rs, rj) => {
setTimeout(() =>
rs({
json: () =>
new Promise((rs, rj) => {
let myJSON = {
emSensorDataCollectionProtocol: {
protocol_id: '2014-04-6267',
approval_date: '2016-07-14',
},
};
setTimeout(() => rs(myJSON), 100);
}),
}),
);
}) as any;

afterEach(() => {
clearNotifMock();
});

it('intro done does nothing if not registered', () => {
expect(getOnList()).toStrictEqual({});
publish(EVENTS.INTRO_DONE_EVENT, 'test data');
expect(getOnList()).toStrictEqual({});
});

it('intro done initializes the push notifications', () => {
expect(getOnList()).toStrictEqual({});

initPushNotify();
publish(EVENTS.INTRO_DONE_EVENT, 'test data');
expect(getOnList()).toStrictEqual(
expect.objectContaining({
notification: expect.any(Function),
error: expect.any(Function),
registration: expect.any(Function),
}),
);
});

it('cloud event does nothing if not registered', () => {
expect(window['cordova'].platformId).toEqual('ios');
publish(EVENTS.CLOUD_NOTIFICATION_EVENT, {
additionalData: { 'content-available': 1, payload: { notId: 3 } },
});
expect(getCalled()).toBeNull();
});

it('cloud event handles notification if registered', async () => {
expect(window['cordova'].platformId).toEqual('ios');
initPushNotify();
publish(EVENTS.INTRO_DONE_EVENT, 'intro done');
publish(EVENTS.CLOUD_NOTIFICATION_EVENT, {
additionalData: { 'content-available': 1, payload: { notId: 3 } },
});
await new Promise((r) => setTimeout(r, 1000));
expect(getCalled()).toEqual(3);
});

it('consent event does nothing if not registered', () => {
expect(getOnList()).toStrictEqual({});
publish(EVENTS.CONSENTED_EVENT, 'test data');
expect(getOnList()).toStrictEqual({});
});

it('consent event registers if intro done', async () => {
//make sure the mock is clear
expect(getOnList()).toStrictEqual({});

//initialize the pushNotify, to subscribe to events
initPushNotify();

//mark the intro as done
const currDateTime = DateTime.now().toISO();
let marked = await storageSet(INTRO_DONE_KEY, currDateTime);
let introDone = await readIntroDone();
expect(introDone).toBeTruthy();

//publish consent event and check results
publish(EVENTS.CONSENTED_EVENT, 'test data');
//have to wait a beat since event response is async
await new Promise((r) => setTimeout(r, 1000));
expect(getOnList()).toStrictEqual(
expect.objectContaining({
notification: expect.any(Function),
error: expect.any(Function),
registration: expect.any(Function),
}),
);
});

it('consent event does not register if intro not done', () => {
expect(getOnList()).toStrictEqual({});
initPushNotify();
publish(EVENTS.CONSENTED_EVENT, 'test data');
expect(getOnList()).toStrictEqual({}); //nothing, intro not done
});
76 changes: 76 additions & 0 deletions www/__tests__/remoteNotifyHandler.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { EVENTS, publish } from '../js/customEventHandler';
import { initRemoteNotifyHandler } from '../js/splash/remoteNotifyHandler';
import {
clearURL,
getURL,
mockBEMUserCache,
mockDevice,
mockGetAppVersion,
mockInAppBrowser,
} from '../__mocks__/cordovaMocks';
import { clearAlerts, getAlerts, mockAlert, mockLogger } from '../__mocks__/globalMocks';

mockLogger();
mockDevice();
mockBEMUserCache();
mockGetAppVersion();
mockInAppBrowser();
mockAlert();

const db = window['cordova']?.plugins?.BEMUserCache;

beforeEach(() => {
clearURL();
clearAlerts();
});

it('does not adds a statEvent if not subscribed', async () => {
publish(EVENTS.CLOUD_NOTIFICATION_EVENT, 'test data');
const storedMessages = await db.getAllMessages('stats/client_nav_event', false);
expect(storedMessages).toEqual([]);
});

it('adds a statEvent if subscribed', async () => {
initRemoteNotifyHandler();
await new Promise((r) => setTimeout(r, 500)); //wait for subscription
publish(EVENTS.CLOUD_NOTIFICATION_EVENT, 'test data');
await new Promise((r) => setTimeout(r, 500)); //wait for event handling
const storedMessages = await db.getAllMessages('stats/client_nav_event', false);
expect(storedMessages).toContainEqual({
name: 'notification_open',
ts: expect.any(Number),
reading: null,
client_app_version: '1.2.3',
client_os_version: '14.0.0',
});
});

it('handles the url if subscribed', () => {
initRemoteNotifyHandler();
publish(EVENTS.CLOUD_NOTIFICATION_EVENT, {
additionalData: {
payload: { alert_type: 'website', spec: { url: 'https://this_is_a_test.com' } },
},
});
expect(getURL()).toBe('https://this_is_a_test.com');
});

it('handles the popup if subscribed', () => {
initRemoteNotifyHandler();
publish(EVENTS.CLOUD_NOTIFICATION_EVENT, {
additionalData: {
payload: {
alert_type: 'popup',
spec: { title: 'Hello', text: 'World' },
},
},
});
expect(getAlerts()).toEqual(expect.arrayContaining(['Hello World']));
});

it('does nothing if subscribed and no data', () => {
initRemoteNotifyHandler();
publish(EVENTS.CLOUD_NOTIFICATION_EVENT, {});
expect(getURL()).toEqual('');
expect(getAlerts()).toEqual([]);
});
Loading

0 comments on commit ccb50c5

Please sign in to comment.