Skip to content

Commit 71c891c

Browse files
authored
feat: disable time tracking when noTargeting is set to true (#1064)
1 parent 97dd88a commit 71c891c

File tree

5 files changed

+86
-23
lines changed

5 files changed

+86
-23
lines changed

src/store.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -740,9 +740,21 @@ export default function Store(
740740
this.SDKConfig[baseUrlKeys] = baseUrls[baseUrlKeys];
741741
}
742742

743+
const { noFunctional, noTargeting } = config?.launcherOptions ?? {};
744+
745+
if (noFunctional != null) {
746+
this.setNoFunctional(noFunctional);
747+
}
748+
749+
if (noTargeting != null) {
750+
this.setNoTargeting(noTargeting);
751+
}
752+
743753
if (workspaceToken) {
744754
this.SDKConfig.workspaceToken = workspaceToken;
745-
mpInstance._timeOnSiteTimer = new ForegroundTimer(workspaceToken);
755+
if (!this.getPrivacyFlag('TimeOnSite')) {
756+
mpInstance._timeOnSiteTimer = new ForegroundTimer(workspaceToken);
757+
}
746758
} else {
747759
mpInstance.Logger.warning(
748760
'You should have a workspaceToken on your config object for security purposes.'
@@ -752,15 +764,6 @@ export default function Store(
752764
this.storageName = createMainStorageName(workspaceToken);
753765
this.prodStorageName = createProductStorageName(workspaceToken);
754766

755-
// Extract privacy flags directly from config into Store
756-
if (config.hasOwnProperty('noFunctional')) {
757-
this.setNoFunctional(config.noFunctional);
758-
}
759-
760-
if (config.hasOwnProperty('noTargeting')) {
761-
this.setNoTargeting(config.noTargeting);
762-
}
763-
764767
this.SDKConfig.requiredWebviewBridgeName =
765768
requiredWebviewBridgeName || workspaceToken;
766769

test/jest/foregroundTimeTracker.spec.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import ForegroundTimeTracker from '../../src/foregroundTimeTracker';
2+
import Store, { IStore } from '../../src/store';
3+
import { SDKInitConfig } from '../../src/sdkRuntimeModels';
4+
import { IMParticleWebSDKInstance } from '../../src/mp-instance';
25

36
describe('ForegroundTimeTracker', () => {
47
let foregroundTimeTracker: ForegroundTimeTracker;
@@ -490,4 +493,65 @@ describe('ForegroundTimeTracker', () => {
490493
expect(updatePersistenceSpy).toHaveBeenCalled();
491494
});
492495
});
496+
497+
describe('#privacy flags', () => {
498+
const workspaceToken = 'abcdef';
499+
const tosKey = `mprtcl-tos-${workspaceToken}`;
500+
let mockMPInstance: IMParticleWebSDKInstance;
501+
let store: IStore;
502+
503+
beforeEach(() => {
504+
jest.useFakeTimers({ now: Date.now(), advanceTimers: true });
505+
localStorage.clear();
506+
507+
mockMPInstance = {
508+
_Helpers: {
509+
createMainStorageName: () => `mprtcl-v4_${workspaceToken}`,
510+
createProductStorageName: () => `mprtcl-prodv4_${workspaceToken}`,
511+
Validators: { isFunction: () => true },
512+
extend: Object.assign,
513+
},
514+
_NativeSdkHelpers: { isWebviewEnabled: () => false },
515+
_Persistence: {
516+
update: jest.fn(),
517+
savePersistence: jest.fn(),
518+
getPersistence: () => ({ gs: {} }),
519+
},
520+
Logger: { verbose: jest.fn(), warning: jest.fn(), error: jest.fn() },
521+
Identity: { getCurrentUser: () => ({ getMPID: () => 'mpid' }) },
522+
_timeOnSiteTimer: undefined as any,
523+
} as unknown as IMParticleWebSDKInstance;
524+
525+
store = {} as IStore;
526+
(Store as any).call(store, {} as SDKInitConfig, mockMPInstance, 'apikey');
527+
mockMPInstance._Store = store;
528+
});
529+
530+
afterEach(() => {
531+
jest.useRealTimers();
532+
localStorage.clear();
533+
});
534+
535+
it('should track time on site when noTargeting is false by default', () => {
536+
store.processConfig({ workspaceToken } as SDKInitConfig);
537+
expect(mockMPInstance._timeOnSiteTimer).toBeDefined();
538+
jest.advanceTimersByTime(1000);
539+
mockMPInstance._timeOnSiteTimer.getTimeInForeground();
540+
expect(localStorage.getItem(tosKey)).not.toBeNull();
541+
});
542+
543+
it('should NOT track time on site when noTargeting is true', () => {
544+
store.processConfig({ workspaceToken, launcherOptions: { noTargeting: true } } as SDKInitConfig);
545+
expect(mockMPInstance._timeOnSiteTimer).toBeUndefined();
546+
expect(localStorage.getItem(tosKey)).toBeNull();
547+
});
548+
549+
it('should track time on site when noTargeting is false', () => {
550+
store.processConfig({ workspaceToken, launcherOptions: { noTargeting: false } } as SDKInitConfig);
551+
expect(mockMPInstance._timeOnSiteTimer).toBeDefined();
552+
jest.advanceTimersByTime(1000);
553+
mockMPInstance._timeOnSiteTimer.getTimeInForeground();
554+
expect(localStorage.getItem(tosKey)).not.toBeNull();
555+
});
556+
});
493557
});

test/jest/store.flags.spec.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ describe('Store privacy flags', () => {
4646

4747
it('should set noFunctional as true and noTargeting as true from config', () => {
4848
const cfg: SDKInitConfig = {
49-
noFunctional: true,
50-
noTargeting: true,
49+
launcherOptions: { noFunctional: true, noTargeting: true },
5150
flags: {},
5251
} as any;
5352

@@ -59,8 +58,7 @@ describe('Store privacy flags', () => {
5958

6059
it('should set noFunctional as true and noTargeting as false from config', () => {
6160
const cfg: SDKInitConfig = {
62-
noFunctional: true,
63-
noTargeting: false,
61+
launcherOptions: { noFunctional: true, noTargeting: false },
6462
flags: {},
6563
} as any;
6664

@@ -72,13 +70,12 @@ describe('Store privacy flags', () => {
7270

7371
it('should set noFunctional as false and noTargeting as true from config', () => {
7472
const cfg: SDKInitConfig = {
75-
noFunctional: false,
76-
noTargeting: true,
73+
launcherOptions: { noFunctional: false, noTargeting: true },
7774
flags: {},
7875
} as any;
7976

8077
store.processConfig(cfg);
81-
78+
8279
expect(store.getNoFunctional()).toBe(false);
8380
expect(store.getNoTargeting()).toBe(true);
8481
});

test/src/tests-batchUploader.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,7 +1744,7 @@ describe('batch uploader', () => {
17441744
offlineStorage: '100',
17451745
...enableBatchingConfigFlags,
17461746
};
1747-
window.mParticle.config.noFunctional = true;
1747+
window.mParticle.config.launcherOptions = { noFunctional: true };
17481748
window.mParticle.init(apiKey, window.mParticle.config);
17491749
await waitForCondition(hasIdentifyReturned);
17501750
const mpInstance = window.mParticle.getInstance();
@@ -1758,7 +1758,7 @@ describe('batch uploader', () => {
17581758
offlineStorage: '100',
17591759
...enableBatchingConfigFlags,
17601760
};
1761-
window.mParticle.config.noFunctional = false;
1761+
window.mParticle.config.launcherOptions = { noFunctional: false };
17621762
window.mParticle.init(apiKey, window.mParticle.config);
17631763
await waitForCondition(hasIdentifyReturned);
17641764
const mpInstance = window.mParticle.getInstance();
@@ -1783,7 +1783,7 @@ describe('batch uploader', () => {
17831783
offlineStorage: '100',
17841784
...enableBatchingConfigFlags,
17851785
};
1786-
window.mParticle.config.noFunctional = true;
1786+
window.mParticle.config.launcherOptions = { noFunctional: true };
17871787
window.mParticle.init(apiKey, window.mParticle.config);
17881788
await waitForCondition(hasIdentifyReturned);
17891789
const mpInstance = window.mParticle.getInstance();
@@ -1798,7 +1798,7 @@ describe('batch uploader', () => {
17981798
offlineStorage: '100',
17991799
...enableBatchingConfigFlags,
18001800
};
1801-
window.mParticle.config.noFunctional = false;
1801+
window.mParticle.config.launcherOptions = { noFunctional: false };
18021802
window.mParticle.init(apiKey, window.mParticle.config);
18031803
await waitForCondition(hasIdentifyReturned);
18041804
const mpInstance = window.mParticle.getInstance();

test/src/tests-store.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,8 +1817,7 @@ describe('Store', () => {
18171817
it('should set noFunctional and noTargeting from init config', () => {
18181818
window.mParticle._resetForTests(MPConfig);
18191819
window.mParticle.config = window.mParticle.config || {};
1820-
window.mParticle.config.noFunctional = true;
1821-
window.mParticle.config.noTargeting = true;
1820+
window.mParticle.config.launcherOptions = { noFunctional: true, noTargeting: true };
18221821

18231822
window.mParticle.init(apiKey, window.mParticle.config);
18241823

0 commit comments

Comments
 (0)