Skip to content

Commit

Permalink
Merge pull request #1179 from JGreenlee/appstate-clientstats
Browse files Browse the repository at this point in the history
cleanup appstate hook, refreshTimeline on app resume, revamp clientstats
  • Loading branch information
shankari authored Sep 14, 2024
2 parents b426c9a + 4596d0c commit 003c55d
Show file tree
Hide file tree
Showing 36 changed files with 129 additions and 225 deletions.
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module.exports = {
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
moduleDirectories: ["node_modules", "src"],
globals: {"__DEV__": false},
setupFiles: ["<rootDir>/www/__mocks__/setupJestEnv.js"],
collectCoverage: true,
collectCoverageFrom: [
"www/js/**/*.{ts,tsx,js,jsx}",
Expand Down
13 changes: 13 additions & 0 deletions www/__mocks__/cordovaMocks.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
import packageJsonBuild from '../../package.cordovabuild.json';

export let alerts: string[] = [];

export const mockLogger = () => {
window['Logger'] = { log: console.log };
window['alert'] = (message) => {
console.log(message);
alerts.push(message);
};
console.error = (msg) => {
console.log(msg);
};
};

export const mockCordova = () => {
window['cordova'] ||= {};
window['cordova'].platformId ||= 'ios';
Expand Down
25 changes: 0 additions & 25 deletions www/__mocks__/globalMocks.ts

This file was deleted.

32 changes: 32 additions & 0 deletions www/__mocks__/setupJestEnv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Applies mocks to the global (window) object for use in tests.
This is run before all of the tests are run, so these mocks are available in all tests.
*/

import {
mockBEMDataCollection,
mockBEMServerCom,
mockBEMUserCache,
mockCordova,
mockDevice,
mockFile,
mockGetAppVersion,
mockInAppBrowser,
mockLogger,
mockReminders,
} from './cordovaMocks';
import { mockFileSystem } from './fileSystemMocks';
import { mockPushNotification } from './pushNotificationMocks';

mockLogger();
mockCordova();
mockDevice();
mockGetAppVersion();
mockBEMUserCache();
mockBEMDataCollection();
mockBEMServerCom();
mockFile();
mockFileSystem();
mockInAppBrowser();
mockPushNotification();
mockReminders();
5 changes: 0 additions & 5 deletions www/__tests__/TimelineContext.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@ import React, { useEffect } from 'react';
import { View, Text } from 'react-native';
import { act, render, screen, waitFor } from '@testing-library/react-native';
import { useTimelineContext } from '../js/TimelineContext';
import { mockLogger } from '../__mocks__/globalMocks';
import { mockBEMServerCom, mockBEMUserCache } from '../__mocks__/cordovaMocks';

mockLogger();
mockBEMUserCache();

jest.mock('../js/services/commHelper', () => ({
getPipelineRangeTs: jest.fn(() => Promise.resolve({ start_ts: 1, end_ts: 10 })),
Expand Down
32 changes: 12 additions & 20 deletions www/__tests__/clientStats.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
import { mockBEMUserCache, mockDevice, mockGetAppVersion } from '../__mocks__/cordovaMocks';
import {
addStatError,
addStatEvent,
addStatReading,
getAppVersion,
statKeys,
} from '../js/plugin/clientStats';
import { addStatError, addStatReading, getAppVersion } from '../js/plugin/clientStats';

mockDevice();
// this mocks cordova-plugin-app-version, generating a "Mock App", version "1.2.3"
mockGetAppVersion();
// clientStats.ts uses BEMUserCache to store the stats, so we need to mock that too
mockBEMUserCache();
const db = window['cordova']?.plugins?.BEMUserCache;

it('gets the app version', async () => {
Expand All @@ -21,10 +9,10 @@ it('gets the app version', async () => {

it('stores a client stats reading', async () => {
const reading = { a: 1, b: 2 };
await addStatReading(statKeys.REMINDER_PREFS, reading);
await addStatReading('set_reminder_prefs', reading);
const storedMessages = await db.getAllMessages('stats/client_time', false);
expect(storedMessages).toContainEqual({
name: statKeys.REMINDER_PREFS,
name: 'set_reminder_prefs',
ts: expect.any(Number),
reading,
client_app_version: '1.2.3',
Expand All @@ -33,10 +21,10 @@ it('stores a client stats reading', async () => {
});

it('stores a client stats event', async () => {
await addStatEvent(statKeys.BUTTON_FORCE_SYNC);
const storedMessages = await db.getAllMessages('stats/client_nav_event', false);
await addStatReading('force_sync');
const storedMessages = await db.getAllMessages('stats/client_time', false);
expect(storedMessages).toContainEqual({
name: statKeys.BUTTON_FORCE_SYNC,
name: 'force_sync',
ts: expect.any(Number),
reading: null,
client_app_version: '1.2.3',
Expand All @@ -46,10 +34,14 @@ it('stores a client stats event', async () => {

it('stores a client stats error', async () => {
const errorStr = 'test error';
await addStatError(statKeys.MISSING_KEYS, errorStr);
try {
throw new Error(errorStr);
} catch (error) {
await addStatError(error.message);
}
const storedMessages = await db.getAllMessages('stats/client_error', false);
expect(storedMessages).toContainEqual({
name: statKeys.MISSING_KEYS,
name: 'ui_error',
ts: expect.any(Number),
reading: errorStr,
client_app_version: '1.2.3',
Expand Down
3 changes: 0 additions & 3 deletions www/__tests__/commHelper.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { mockLogger } from '../__mocks__/globalMocks';
import { fetchUrlCached } from '../js/services/commHelper';

mockLogger();

// mock for JavaScript 'fetch'
// we emulate a 100ms delay when i) fetching data and ii) parsing it as text
global.fetch = (url: string) =>
Expand Down
3 changes: 0 additions & 3 deletions www/__tests__/confirmHelper.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { mockLogger } from '../__mocks__/globalMocks';
import * as CommHelper from '../js/services/commHelper';
import {
baseLabelInputDetails,
getLabelInputDetails,
Expand All @@ -17,7 +15,6 @@ import initializedI18next from '../js/i18nextInit';
import { CompositeTrip, UserInputEntry } from '../js/types/diaryTypes';
import { UserInputMap } from '../js/TimelineContext';
window['i18next'] = initializedI18next;
mockLogger();

const fakeAppConfig = {
label_options: 'json/label-options.json.sample',
Expand Down
3 changes: 0 additions & 3 deletions www/__tests__/customEventHandler.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import { publish, subscribe, unsubscribe } from '../js/customEventHandler';
import { mockLogger } from '../__mocks__/globalMocks';

mockLogger();

it('subscribes and publishes to an event', () => {
const listener = jest.fn();
Expand Down
2 changes: 0 additions & 2 deletions www/__tests__/customMetricsHelper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ import {
initCustomDatasetHelper,
} from '../js/metrics/customMetricsHelper';
import { mockBEMUserCache } from '../__mocks__/cordovaMocks';
import { mockLogger } from '../__mocks__/globalMocks';
import fakeLabels from '../__mocks__/fakeLabels.json';
import fakeConfig from '../__mocks__/fakeConfig.json';

mockBEMUserCache(fakeConfig);
mockLogger();

beforeEach(() => {
_test_clearCustomMetrics();
Expand Down
6 changes: 0 additions & 6 deletions www/__tests__/dynamicConfig.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import { mockBEMUserCache } from '../__mocks__/cordovaMocks';
import { mockAlert, mockLogger } from '../__mocks__/globalMocks';
import { getConfig, initByUser } from '../js/config/dynamicConfig';

import initializedI18next from '../js/i18nextInit';
import { storageClear } from '../js/plugin/storage';
window['i18next'] = initializedI18next;

mockLogger();
mockAlert();
mockBEMUserCache();

beforeEach(() => {
// clear all storage and the config document
storageClear({ local: true, native: true });
Expand Down
2 changes: 0 additions & 2 deletions www/__tests__/enketoHelper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
EnketoUserInputEntry,
} from '../js/survey/enketo/enketoHelper';
import { mockBEMUserCache } from '../__mocks__/cordovaMocks';
import { mockLogger } from '../__mocks__/globalMocks';
import { getConfig, _test_resetPromisedConfig } from '../../www/js/config/dynamicConfig';
import fakeConfig from '../__mocks__/fakeConfig.json';

Expand All @@ -18,7 +17,6 @@ import { AppConfig } from '../js/types/appConfigTypes';
window['i18next'] = initializedI18next;

mockBEMUserCache(fakeConfig);
mockLogger();

global.URL = require('url').URL;
global.Blob = require('node:buffer').Blob;
Expand Down
2 changes: 0 additions & 2 deletions www/__tests__/footprintHelper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ import {
} from '../js/metrics/footprintHelper';
import { getConfig } from '../js/config/dynamicConfig';
import { mockBEMUserCache } from '../__mocks__/cordovaMocks';
import { mockLogger } from '../__mocks__/globalMocks';
import fakeLabels from '../__mocks__/fakeLabels.json';
import fakeConfig from '../__mocks__/fakeConfig.json';

mockBEMUserCache(fakeConfig);
mockLogger();

global.fetch = (url: string) =>
new Promise((rs, rj) => {
Expand Down
5 changes: 0 additions & 5 deletions www/__tests__/inputMatcher.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { mockBEMUserCache } from '../__mocks__/cordovaMocks';
import { mockLogger } from '../__mocks__/globalMocks';
import { updateLocalUnprocessedInputs } from '../js/diary/timelineHelper';
import * as logger from '../js/plugin/logger';
import { EnketoUserInputEntry } from '../js/survey/enketo/enketoHelper';
Expand All @@ -17,9 +15,6 @@ import {
import { AppConfig } from '../js/types/appConfigTypes';
import { CompositeTrip, TimelineEntry, UserInputEntry } from '../js/types/diaryTypes';

mockLogger();
mockBEMUserCache();

describe('input-matcher', () => {
let userTrip: UserInputEntry;
let trip: TimelineEntry;
Expand Down
2 changes: 0 additions & 2 deletions www/__tests__/metHelper.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { getMet } from '../js/metrics/metHelper';
import { mockBEMUserCache } from '../__mocks__/cordovaMocks';
import { mockLogger } from '../__mocks__/globalMocks';
import fakeLabels from '../__mocks__/fakeLabels.json';
import { getConfig } from '../js/config/dynamicConfig';
import { initCustomDatasetHelper } from '../js/metrics/customMetricsHelper';
import fakeConfig from '../__mocks__/fakeConfig.json';

mockBEMUserCache(fakeConfig);
mockLogger();

global.fetch = (url: string) =>
new Promise((rs, rj) => {
Expand Down
6 changes: 0 additions & 6 deletions www/__tests__/notifScheduler.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
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 @@ -60,9 +57,6 @@ const exampleReminderSchemes = {
},
};

mockLogger();
mockReminders();

jest.mock('i18next', () => ({
resolvedLanguage: 'en',
}));
Expand Down
15 changes: 1 addition & 14 deletions www/__tests__/pushNotifySettings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,7 @@ 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();
import { clearNotifMock, getOnList, getCalled } from '../__mocks__/pushNotificationMocks';

global.fetch = (url: string) =>
new Promise((rs, rj) => {
Expand Down
31 changes: 8 additions & 23 deletions www/__tests__/remoteNotifyHandler.test.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,17 @@
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();
import { alerts, clearURL, getURL } from '../__mocks__/cordovaMocks';

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

beforeEach(() => {
clearURL();
clearAlerts();
alerts.length = 0;
});

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);
const storedMessages = await db.getAllMessages('stats/client_time', false);
expect(storedMessages).toEqual([]);
});

Expand All @@ -35,11 +20,11 @@ it('adds a statEvent if subscribed', async () => {
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);
const storedMessages = await db.getAllMessages('stats/client_time', false);
expect(storedMessages).toContainEqual({
name: 'notification_open',
name: 'open_notification',
ts: expect.any(Number),
reading: null,
reading: 'test data',
client_app_version: '1.2.3',
client_os_version: '14.0.0',
});
Expand All @@ -65,12 +50,12 @@ it('handles the popup if subscribed', () => {
},
},
});
expect(getAlerts()).toEqual(expect.arrayContaining(['Hello World']));
expect(alerts).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([]);
expect(alerts).toEqual([]);
});
7 changes: 0 additions & 7 deletions www/__tests__/startprefs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@ import {
getConsentDocument,
} from '../js/splash/startprefs';

import { mockBEMUserCache, mockBEMDataCollection } from '../__mocks__/cordovaMocks';
import { mockLogger } from '../__mocks__/globalMocks';

mockBEMUserCache();
mockBEMDataCollection();
mockLogger();

global.fetch = (url: string) =>
new Promise((rs, rj) => {
setTimeout(() =>
Expand Down
Loading

0 comments on commit 003c55d

Please sign in to comment.