Skip to content

Commit

Permalink
add service worker tests
Browse files Browse the repository at this point in the history
  • Loading branch information
fadi-george committed Feb 3, 2025
1 parent 97d6811 commit c566166
Show file tree
Hide file tree
Showing 13 changed files with 468 additions and 76 deletions.
9 changes: 5 additions & 4 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ module.exports = {
root: true,
rules: {
'no-extra-boolean-cast': 0,
'quotes': [
quotes: [
'error',
'single',
{ 'avoidEscape': true, 'allowTemplateLiterals': true }
]
{ avoidEscape: true, allowTemplateLiterals: true },
],
'@typescript-eslint/triple-slash-reference': 'off',
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'prettier'
'prettier',
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
Expand Down
4 changes: 4 additions & 0 deletions __test__/jest.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ declare namespace jest {
nock: (responseBody: any, status?: number) => void;
}
}

declare namespace global {
const flushPromises: () => Promise<void>;
}
8 changes: 8 additions & 0 deletions __test__/jest/jest.setup.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { setImmediate } from 'timers';
require('fake-indexeddb/auto');
require('core-js/actual/structured-clone');

test.stub = (obj: any, method: string, returnValue?: any) => {
const stub = jest.spyOn(obj, method);
stub.mockReturnValue(returnValue);
Expand All @@ -19,3 +23,7 @@ test.nock = (responseBody: any, status = 200) => {
import { TextEncoder, TextDecoder } from 'util';
(global as any).TextEncoder = TextEncoder;
(global as any).TextDecoder = TextDecoder;
(global as any).setImmediate = setImmediate;
(global as any).flushPromises = () => {
return new Promise((resolve) => setImmediate(resolve));
};
18 changes: 18 additions & 0 deletions __test__/support/helpers/general.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export function merge<T extends object, U extends object>(
target: T,
source: U,
): T & U {
if (typeof target !== 'object' || target === null) {
return source as T & U;
}

for (const key of Object.keys(source) as Array<keyof U>) {
if (source[key] instanceof Object && target[key] instanceof Object) {
target[key] = merge(target[key], source[key] as any);
} else {
target[key] = source[key] as any;
}
}

return target as T & U;
}
19 changes: 19 additions & 0 deletions __test__/support/mocks/notifcations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { OSMinifiedNotificationPayload } from 'src/sw/models/OSMinifiedNotificationPayload';
import { merge } from '../helpers/general';
import { PartialDeep } from 'type-fest';

export const mockOSMinifiedNotificationPayload = (
data: PartialDeep<OSMinifiedNotificationPayload> = {},
): OSMinifiedNotificationPayload => {
const defaultPayload: OSMinifiedNotificationPayload = {
alert: 'This is a test notification',
custom: {
a: 'test-action',
i: 'test-id',
},
icon: 'https://example.com/icon.png',
title: 'Test Notification',
};

return merge(defaultPayload, data);
};
53 changes: 0 additions & 53 deletions __test__/unit/sw/serviceWorker.test.ts

This file was deleted.

6 changes: 6 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
/** @returns {Promise<import('jest').Config>} */
module.exports = async () => {
return {
clearMocks: true,
collectCoverageFrom: ['src/**/*.{ts,tsx}'],
coverageDirectory: 'coverage',
coverageReporters: ['text-summary', 'lcov'],
verbose: true,
preset: 'ts-jest',
forceExit: true,
bail: true,
testEnvironment: 'jsdom',
moduleNameMapper: {
'^__test__(.*)$': '<rootDir>/__test__/$1',
'^src/(.*)$': '<rootDir>/src/$1',
},
// Run these files after jest has been
// installed in the environment
setupFilesAfterEnv: ['<rootDir>/__test__/jest/jest.setup.ts'], // use .js if you prefer JavaScript,
Expand Down
15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"dependencies": {
"@types/intl-tel-input": "^17.0.1",
"bowser": "github:OneSignal/bowser#fix-android8-opr6-build-detection",
"core-js-bundle": "^3.1.3",
"core-js": "^3.40.0",
"glob": "^10.2.2",
"jsonp": "github:OneSignal/jsonp#onesignal",
"npm-css": "https://registry.npmjs.org/npm-css/-/npm-css-0.2.3.tgz",
Expand Down Expand Up @@ -59,7 +59,7 @@
"@types/cors": "latest",
"@types/express": "^4.17.17",
"@types/jest": "^29.4.0",
"@types/jsdom": "^21.1.0",
"@types/jsdom": "^21.1.7",
"@types/loglevel": "latest",
"@types/mocha": "^5.0.0",
"@types/nconf": "latest",
Expand All @@ -83,12 +83,12 @@
"dom-storage": "^2.0.2",
"eslint": "^8.23.0",
"eslint-config-prettier": "9.0.0",
"fake-indexeddb": "^4.0.1",
"fake-indexeddb": "^5.0.2",
"imports-loader": "^0.7.1",
"jest": "^29.0.1",
"jest-environment-jsdom": "^29.4.1",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-localstorage-mock": "^2.4.26",
"jsdom": "^21.1.0",
"jsdom": "^26.0.0",
"md5-file": "^3.2.2",
"mini-css-extract-plugin": "^2.7.5",
"nock": "^9.1.6",
Expand All @@ -103,9 +103,10 @@
"style-loader": "^3.3.2",
"svgo": "^0.7.2",
"timemachine": "^0.3.0",
"ts-jest": "^29.0.5",
"ts-jest": "^29.2.5",
"ts-loader": "^9.4.2",
"ts-node": "^10.1.1",
"type-fest": "^4.33.0",
"typescript": "^4.9.5",
"webpack": "^5.80.0",
"webpack-bundle-analyzer": "^3.3.2",
Expand Down
17 changes: 9 additions & 8 deletions src/shared/services/Database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,18 @@ interface DatabaseResult {
* "NotificationOpened" = Pending Notification Click events that haven't fired yet
*/

export const INDEXED_DB_NAME = 'ONE_SIGNAL_SDK_DB';
export const TABLE_OUTCOMES_NOTIFICATION_CLICKED =
'Outcomes.NotificationClicked';
export const TABLE_OUTCOMES_NOTIFICATION_RECEIVED =
'Outcomes.NotificationReceived';
export const TABLE_NOTIFICATION_OPENED = 'NotificationOpened';

export type OneSignalDbTable =
| 'Options'
| 'Ids'
| 'NotificationOpened'
| 'Sessions'
| 'NotificationOpened'
| typeof TABLE_NOTIFICATION_OPENED
| typeof TABLE_OUTCOMES_NOTIFICATION_RECEIVED
| typeof TABLE_OUTCOMES_NOTIFICATION_CLICKED
| 'SentUniqueOutcome'
Expand Down Expand Up @@ -76,7 +77,7 @@ export default class Database {

public static get singletonInstance(): Database {
if (!Database.databaseInstanceName) {
Database.databaseInstanceName = 'ONE_SIGNAL_SDK_DB';
Database.databaseInstanceName = INDEXED_DB_NAME;
}
if (!Database.databaseInstance) {
Database.databaseInstance = new Database(Database.databaseInstanceName);
Expand Down Expand Up @@ -232,7 +233,7 @@ export default class Database {
const notificationDetails =
appState.pendingNotificationClickEvents[url];
if (notificationDetails) {
await this.put('NotificationOpened', {
await this.put(TABLE_NOTIFICATION_OPENED, {
url: url,
data: (notificationDetails as any).data,
timestamp: (notificationDetails as any).timestamp,
Expand All @@ -241,7 +242,7 @@ export default class Database {
// If we get an object like:
// { "http://site.com/page": null}
// It means we need to remove that entry
await this.remove('NotificationOpened', url);
await this.remove(TABLE_NOTIFICATION_OPENED, url);
}
}
}
Expand Down Expand Up @@ -418,7 +419,7 @@ export default class Database {
event: NotificationClickEventInternal,
): Promise<void> {
await this.put(
'NotificationOpened',
TABLE_NOTIFICATION_OPENED,
NotificationClickForOpenHandlingSerializer.toDatabase(event),
);
}
Expand All @@ -427,7 +428,7 @@ export default class Database {
const clickedNotifications: PendingNotificationClickEvents = {};
const eventsFromDb =
await this.getAll<NotificationClickForOpenHandlingSchema>(
'NotificationOpened',
TABLE_NOTIFICATION_OPENED,
);
for (const eventFromDb of eventsFromDb) {
const event =
Expand Down Expand Up @@ -488,7 +489,7 @@ export default class Database {
static async rebuild() {
return Promise.all([
Database.singletonInstance.remove('Ids'),
Database.singletonInstance.remove('NotificationOpened'),
Database.singletonInstance.remove(TABLE_NOTIFICATION_OPENED),
Database.singletonInstance.remove('Options'),
Database.singletonInstance.remove(TABLE_OUTCOMES_NOTIFICATION_RECEIVED),
Database.singletonInstance.remove(TABLE_OUTCOMES_NOTIFICATION_CLICKED),
Expand Down
2 changes: 1 addition & 1 deletion src/shared/services/IndexedDb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Utils from '../context/Utils';
import Emitter from '../libraries/Emitter';
import Log from '../libraries/Log';

const DATABASE_VERSION = 6;
export const DATABASE_VERSION = 6;

export default class IndexedDb {
public emitter: Emitter;
Expand Down
1 change: 0 additions & 1 deletion src/shared/services/indexedDb.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import IndexedDb from './IndexedDb';
import Random from '../../../__test__/support/utils/Random';
import { SubscriptionType } from '../../core/models/SubscriptionModels';
import Log from '../../shared/libraries/Log';
require('fake-indexeddb/auto');

function newOSIndexedDb(
dbName = Random.getRandomString(10),
Expand Down
Loading

0 comments on commit c566166

Please sign in to comment.