diff --git a/www/__mocks__/cordovaMocks.ts b/www/__mocks__/cordovaMocks.ts index deb5e0a35..c45a01734 100644 --- a/www/__mocks__/cordovaMocks.ts +++ b/www/__mocks__/cordovaMocks.ts @@ -30,6 +30,9 @@ export const mockFile = () => { "applicationStorageDirectory" : "../path/to/app/storage/directory"}; } +//for consent document +const _storage = {}; + export const mockBEMUserCache = () => { const _cache = {}; const messages = []; @@ -98,15 +101,28 @@ export const mockBEMUserCache = () => { // this was mocked specifically for enketoHelper's use, could be expanded if needed const fakeSurveyConfig = fakeConfig; - if(key == "config/app_ui_config"){ + if (key == "config/app_ui_config") { return new Promise((rs, rj) => - setTimeout(() => { - rs(fakeSurveyConfig); - }, 100) - ); + setTimeout(() => { + rs(fakeSurveyConfig); + }, 100) + ); } else { - return null; + return new Promise((rs, rj) => + setTimeout(() => { + rs(_storage[key]); + }, 100) + ); + } + }, + isEmptyDoc: (doc) => { + if (doc == undefined) { return true } + let string = doc.toString(); + if (string.length == 0) { + return true; + } else { + return false; } } } @@ -114,3 +130,15 @@ export const mockBEMUserCache = () => { window['cordova'].plugins ||= {}; window['cordova'].plugins.BEMUserCache = mockBEMUserCache; } + +export const mockBEMDataCollection = () => { + const mockBEMDataCollection = { + markConsented: (consentDoc) => { + setTimeout(() => { + _storage['config/consent'] = consentDoc; + }, 100) + } + } + window['cordova'] ||= {}; + window['cordova'].plugins.BEMDataCollection = mockBEMDataCollection; +} diff --git a/www/__tests__/startprefs.test.ts b/www/__tests__/startprefs.test.ts new file mode 100644 index 000000000..1e62e7b5e --- /dev/null +++ b/www/__tests__/startprefs.test.ts @@ -0,0 +1,24 @@ +import { markConsented, isConsented, readConsentState, 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(() => 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; + +it('checks state of consent before and after marking consent', async () => { + expect(await readConsentState().then(isConsented)).toBeFalsy(); + let marked = await markConsented(); + expect(await readConsentState().then(isConsented)).toBeTruthy(); + expect(await getConsentDocument()).toEqual({"approval_date": "2016-07-14", "protocol_id": "2014-04-6267"}); +}); \ No newline at end of file diff --git a/www/i18n/en.json b/www/i18n/en.json index 9217339f7..4d9aea168 100644 --- a/www/i18n/en.json +++ b/www/i18n/en.json @@ -64,9 +64,10 @@ "confirm": "Confirm", "user-data-erased": "User data erased.", "consent-not-found": "Consent for data collection not found, consent now?", + "no-consent-logout": "Consent for data collection not found, please save your opcode, log out, and log back in with the same opcode. Note that you won't get any personalized stats until you do!", "no-consent-message": "OK! Note that you won't get any personalized stats until you do!", "consent-found": "Consent found!", - "consented-to": "Consented to protocol {{protocol_id}}, {{approval_date}}", + "consented-to": "Consented to protocol last updated on {{approval_date}}", "consented-ok": "OK", "qrcode": "My OPcode", "qrcode-share-title": "You can save your OPcode to login easily in the future!" @@ -154,9 +155,10 @@ "scootershare": "Scooter share", "drove_alone": "Gas Car Drove Alone", "shared_ride": "Gas Car Shared Ride", + "hybrid_drove_alone": "Hybrid Drove Alone", + "hybrid_shared_ride": "Hybrid Shared Ride", "e_car_drove_alone": "E-Car Drove Alone", "e_car_shared_ride": "E-Car Shared Ride", - "moped": "Moped", "taxi": "Taxi / Uber / Lyft", "bus": "Bus", "train": "Train", diff --git a/www/index.js b/www/index.js index b93fcd3b1..a4d448202 100644 --- a/www/index.js +++ b/www/index.js @@ -5,7 +5,6 @@ import 'leaflet/dist/leaflet.css'; import './js/ngApp.js'; import './js/splash/referral.js'; -import './js/splash/startprefs.js'; import './js/splash/pushnotify.js'; import './js/splash/storedevicesettings.js'; import './js/splash/localnotify.js'; diff --git a/www/js/App.tsx b/www/js/App.tsx index 3c6c8bec9..b1806a5cc 100644 --- a/www/js/App.tsx +++ b/www/js/App.tsx @@ -31,8 +31,6 @@ const App = () => { const { colors } = useTheme(); const { t } = useTranslation(); - const StartPrefs = getAngularService('StartPrefs'); - const routes = useMemo(() => { const showMetrics = appConfig?.survey_info?.['trip-labels'] == 'MULTILABEL'; return showMetrics ? defaultRoutes(t) : defaultRoutes(t).filter(r => r.key != 'metrics'); diff --git a/www/js/control/ProfileSettings.jsx b/www/js/control/ProfileSettings.jsx index 7678cae6b..e2e6d04fd 100644 --- a/www/js/control/ProfileSettings.jsx +++ b/www/js/control/ProfileSettings.jsx @@ -25,6 +25,8 @@ import { AppContext } from "../App"; import { shareQR } from "../components/QrCode"; import { storageClear } from "../plugin/storage"; import { getAppVersion } from "../plugin/clientStats"; +import { getConsentDocument } from "../splash/startprefs"; +import { logDebug } from "../plugin/logger"; //any pure functions can go outside const ProfileSettings = () => { @@ -39,7 +41,6 @@ const ProfileSettings = () => { const EmailHelper = getAngularService('EmailHelper'); const NotificationScheduler = getAngularService('NotificationScheduler'); const ControlHelper = getAngularService('ControlHelper'); - const StartPrefs = getAngularService('StartPrefs'); //functions that come directly from an Angular service const editCollectionConfig = () => setEditCollectionVis(true); @@ -314,8 +315,9 @@ const ProfileSettings = () => { //in ProfileSettings in DevZone (above two functions are helpers) async function checkConsent() { - StartPrefs.getConsentDocument().then(function(resultDoc){ + getConsentDocument().then(function(resultDoc){ setConsentDoc(resultDoc); + logDebug("In profile settings, consent doc found", resultDoc); if (resultDoc == null) { setNoConsentVis(true); } else { @@ -482,17 +484,13 @@ const ProfileSettings = () => { onDismiss={()=>setNoConsentVis(false)} style={settingStyles.dialog(colors.elevation.level3)}> {t('general-settings.consent-not-found')} + + {t('general-settings.no-consent-logout')} + - @@ -503,7 +501,7 @@ const ProfileSettings = () => { setConsentVis(false)} style={settingStyles.dialog(colors.elevation.level3)}> - {t('general-settings.consented-to', {protocol_id: consentDoc.protocol_id, approval_date: consentDoc.approval_date})} + {t('general-settings.consented-to', {approval_date: consentDoc.approval_date})}