From 32b1b5d4437f2ce3b5ecc9f2d5727f7357fccc0e Mon Sep 17 00:00:00 2001 From: Alexander Sapountzis Date: Thu, 28 Mar 2024 10:16:13 -0400 Subject: [PATCH] Save Point --- src/store.ts | 139 +++++++++------- test/src/tests-persistence.ts | 1 + test/src/tests-store.ts | 290 +++++++++++++++++++++++++++++++++- 3 files changed, 367 insertions(+), 63 deletions(-) diff --git a/src/store.ts b/src/store.ts index 410177ea..f4743cb7 100644 --- a/src/store.ts +++ b/src/store.ts @@ -225,6 +225,7 @@ export interface IStore { ): void; updatePersistence?(): void; + resetPersistenceData?(): void; } // TODO: Merge this with SDKStoreApi in sdkRuntimeModels @@ -503,11 +504,6 @@ export default function Store( } } - this.setAppVersion = (appVersion: string): void => { - this.SDKConfig.appVersion = appVersion; - mpInstance._Persistence.update(); - }; - // TODO: Create an interface for T so we can restrict this method to only // valid keys of T this._getFromPersistence = (mpid: MPID, key: string): T | null => { @@ -530,12 +526,68 @@ export default function Store( } }; - this.getPersistenceData = (): IPersistenceMinified => { - const persistence = mpInstance._Persistence.getPersistence(); + this._setPersistence = (mpid: MPID, key: string, value: T): void => { + if (!mpid) { + return; + } + + const persistence: IPersistenceMinified = mpInstance._Persistence.getPersistence(); this.persistenceData = mergeObjects(this.persistenceData, persistence); - return this.persistenceData; + if (this.persistenceData) { + if (this.persistenceData[mpid]) { + this.persistenceData[mpid][key] = value; + } else { + this.persistenceData[mpid] = { + [key]: value, + }; + } + mpInstance._Persistence.savePersistence(this.persistenceData); + } + }; + + this.setAppVersion = (appVersion: string): void => { + this.SDKConfig.appVersion = appVersion; + mpInstance._Persistence.update(); + }; + + this.getDeviceId = (): string => this.deviceId; + this.setDeviceId = (guid: string): void => { + this.deviceId = guid; + + // https://go.mparticle.com/work/SQDSDKS-6045 + mpInstance._Persistence.update(); + }; + + this.getConsentState = (mpid: MPID): ConsentState => { + const serializedConsentState = this._getFromPersistence< + IMinifiedConsentJSONObject + >(mpid, 'con'); + + if (!isEmpty(serializedConsentState)) { + return mpInstance._Consent.ConsentSerialization.fromMinifiedJsonObject( + serializedConsentState + ); + } + + return null; + }; + + this.setConsentState = (mpid: MPID, consentState: ConsentState): void => { + if (!consentState) { + return; + } + + const serializedConsentState = mpInstance._Consent.ConsentSerialization.toMinifiedJsonObject( + consentState + ); + + this._setPersistence( + mpid, + 'con', + serializedConsentState + ); }; this.getFirstSeenTime = (mpid: MPID): number => @@ -560,7 +612,9 @@ export default function Store( // relying on the Identity object const currentUser = mpInstance.Identity.getCurrentUser(); + // TODO: Fix prettier to stop complaining about `?` if (mpid === currentUser?.getMPID()) { + //if the mpid is the current user, its last seen time is the current time return new Date().getTime(); } else { return this._getFromPersistence(mpid, 'lst'); @@ -572,46 +626,20 @@ export default function Store( this._setPersistence(mpid, 'lst', time); }; + this.getPersistenceData = (): IPersistenceMinified => { + const persistence = mpInstance._Persistence.getPersistence(); + + this.persistenceData = mergeObjects(this.persistenceData, persistence); + + return this.persistenceData; + }; + this.getUserIdentities = (mpid: MPID): UserIdentities => this._getFromPersistence(mpid, 'ui'); // QUESTION: Can we rename this to getUserAttributes? this.getAllUserAttributes = (mpid: MPID): Dictionary => this._getFromPersistence(mpid, 'ua'); - this.getConsentState = (mpid: MPID): ConsentState => { - const serializedConsentState = this._getFromPersistence< - IMinifiedConsentJSONObject - >(mpid, 'con'); - - if (!isEmpty(serializedConsentState)) { - return mpInstance._Consent.ConsentSerialization.fromMinifiedJsonObject( - serializedConsentState - ); - } - - return null; - }; - - this._setPersistence = (mpid: MPID, key: string, value: T): void => { - if (!mpid) { - return; - } - - const persistence: IPersistenceMinified = mpInstance._Persistence.getPersistence(); - - this.persistenceData = mergeObjects(this.persistenceData, persistence); - - if (this.persistenceData) { - if (this.persistenceData[mpid]) { - this.persistenceData[mpid][key] = value; - } else { - this.persistenceData[mpid] = { - [key]: value, - }; - } - mpInstance._Persistence.savePersistence(this.persistenceData); - } - }; this.setPersistenceData = (persistenceData: IPersistenceMinified): void => { const persistence = mpInstance._Persistence.getPersistence(); @@ -621,6 +649,8 @@ export default function Store( persistence, persistenceData ); + + mpInstance._Persistence.savePersistence(this.persistenceData); }; this.setUserIdentities = ( @@ -629,23 +659,15 @@ export default function Store( ): void => { this._setPersistence(mpid, 'ui', userIdentities); }; + this.setUserAttributes = ( mpid: MPID, userAttributes: UserAttributes ): void => { + debugger; this._setPersistence(mpid, 'ua', userAttributes); }; - this.setConsentState = (mpid: MPID, consentState: ConsentState): void => { - const serializedConsentState = mpInstance._Consent.ConsentSerialization.toMinifiedJsonObject( - consentState - ); - this._setPersistence( - mpid, - 'con', - serializedConsentState - ); - }; this.setUserCookieSyncDates = ( mpid: MPID, cookieSyncDates: CookieSyncDate[] @@ -695,14 +717,6 @@ export default function Store( return data as IPersistenceMinified; }; - this.getDeviceId = (): string => this.deviceId; - this.setDeviceId = (guid: string): void => { - this.deviceId = guid; - - // https://go.mparticle.com/work/SQDSDKS-6045 - mpInstance._Persistence.update(); - }; - this.swapIdentity = ( currentMPID: MPID, currentSessionMPIDs: MPID[] @@ -822,6 +836,11 @@ export default function Store( this.setPersistenceData(persistenceData); }; + + this.resetPersistenceData = (): void => { + this.persistenceData = mergeObjects(defaultStore.persistenceData); + mpInstance._Persistence.resetPersistence(); + }; } export function processFlags( diff --git a/test/src/tests-persistence.ts b/test/src/tests-persistence.ts index 7bc06999..0ace0693 100644 --- a/test/src/tests-persistence.ts +++ b/test/src/tests-persistence.ts @@ -1897,6 +1897,7 @@ describe('persistence', () => { const sessionId = mParticle.sessionManager.getSession(); const das = mParticle.getDeviceId(); + // QUESTION: What is client generated string? const cgid = mParticle.getInstance()._Persistence.getCookie().gs.cgid; sessionId.should.not.equal('1992BDBB-AD74-49DB-9B20-5EC8037E72DE'); das.should.not.equal('68c2ba39-c869-416a-a82c-8789caf5f1e7'); diff --git a/test/src/tests-store.ts b/test/src/tests-store.ts index 16327e67..50954877 100644 --- a/test/src/tests-store.ts +++ b/test/src/tests-store.ts @@ -17,11 +17,14 @@ import { import Utils from './config/utils'; import { Dictionary } from '../../src/utils'; import Constants from '../../src/constants'; -import { IPersistenceMinified } from '../../src/persistence.interfaces'; +import { + IGlobalStoreV2MinifiedKeys, + IPersistenceMinified, +} from '../../src/persistence.interfaces'; -const { MockSideloadedKit } = Utils; +const { MockSideloadedKit, setLocalStorage } = Utils; -describe('Store', () => { +describe.only('Store', () => { const now = new Date(); let sandbox; let clock; @@ -1361,6 +1364,154 @@ describe('Store', () => { expectedConsentState.ccpa ); }); + + it('should not set consent state if consent state is null', () => { + const store: IStore = new Store( + sampleConfig, + window.mParticle.getInstance() + ); + + const expectedConsentState = { + con: { + gdpr: { + analytics: { + c: true, + d: 'foo gdpr document', + h: 'foo gdpr hardware id', + l: 'foo gdpr location', + ts: 10, + }, + }, + ccpa: { + data_sale_opt_out: { + c: false, + d: 'foo ccpa document', + h: 'foo ccpa hardware id', + l: 'foo ccpa location', + ts: 42, + }, + }, + }, + }; + + store.persistenceData[testMPID] = expectedConsentState; + + store.setConsentState(testMPID, null); + + expect(store.persistenceData[testMPID]).to.deep.equal( + expectedConsentState + ); + }); + }); + + describe('setPersistenceData', () => { + it('should set persistence data in the store', () => { + const store: IStore = new Store( + sampleConfig, + window.mParticle.getInstance() + ); + + const persistenceObject: IPersistenceMinified = { + gs: { + les: 12345, + sid: 'sessionId', + ie: false, + sa: { + sessionAttr1: 'sessionAttr1', + sessionAttr2: 'sessionAttr2', + }, + ss: { + serverSetting: 'testServerSetting', + }, + dt: 'deviceToken', + av: '1.2.3', + cgid: 'clientId', + das: 'deviceId', + ia: { + integrationAttribute1: { + integrationAttributeKey: + 'Integration Attribute Value', + }, + integrationAttribute2: { + integrationAttributeKey: + 'Integration Attribute Value', + }, + }, + c: { + data_plan: { + plan_id: '123', + plan_version: 1, + }, + }, + csm: ['123'], + ssd: 12345, + }, + l: false, + testMPID: { + ua: { fizz: 'buzz' }, + }, + cu: 'testMPID', + }; + + store.setPersistenceData(persistenceObject); + expect(store.persistenceData).to.deep.equal(persistenceObject); + }); + + it('should set persistence data in persistence', () => { + const store: IStore = new Store( + sampleConfig, + window.mParticle.getInstance() + ); + + const persistenceObject: IPersistenceMinified = { + gs: { + les: 12345, + sid: 'sessionId', + ie: false, + sa: { + sessionAttr1: 'sessionAttr1', + sessionAttr2: 'sessionAttr2', + }, + ss: { + serverSetting: 'testServerSetting', + }, + dt: 'deviceToken', + av: '1.2.3', + cgid: 'clientId', + das: 'deviceId', + ia: { + integrationAttribute1: { + integrationAttributeKey: + 'Integration Attribute Value', + }, + integrationAttribute2: { + integrationAttributeKey: + 'Integration Attribute Value', + }, + }, + c: { + data_plan: { + plan_id: '123', + plan_version: 1, + }, + }, + csm: ['123'], + ssd: 12345, + }, + l: false, + testMPID: { + ua: { fizz: 'buzz' }, + }, + cu: 'testMPID', + }; + + store.setPersistenceData(persistenceObject); + const fromPersistence = window.mParticle + .getInstance() + ._Persistence.getPersistence(); + + expect(fromPersistence).to.deep.equal(persistenceObject); + }); }); describe('#setUserCookieSyncDates', () => { @@ -1819,4 +1970,137 @@ describe('Store', () => { }); }); }); + + describe('#resetPersistenceData', () => { + it('should clear out the persistence data in the store', () => { + debugger; + const store: IStore = new Store( + sampleConfig, + window.mParticle.getInstance() + ); + + store.persistenceData = { + gs: { + csm: ['mpid3'], + sid: 'abcd', + ie: true, + dt: apiKey, + cgid: 'cgid1', + das: 'das1', + } as IGlobalStoreV2MinifiedKeys, + cu: 'mpid3', + l: false, + mpid1: { + ua: { + gender: 'female', + age: 29, + height: '65', + color: 'blue', + id: 'abcdefghijklmnopqrstuvwxyz', + }, + ui: { 1: 'customerid123', 2: 'facebookid123' }, + }, + mpid2: { + ua: { gender: 'male', age: 20, height: '68', color: 'red' }, + ui: { + 1: 'customerid234', + 2: 'facebookid234', + id: 'abcdefghijklmnopqrstuvwxyz', + }, + }, + mpid3: { + ua: { gender: 'male', age: 20, height: '68', color: 'red' }, + ui: { + 1: 'customerid234', + 2: 'facebookid234', + id: 'abcdefghijklmnopqrstuvwxyz', + }, + }, + }; + + store.resetPersistenceData(); + + expect(store.persistenceData).to.deep.equal({ + cu: null, + gs: { + sid: null, + ie: null, + sa: null, + ss: null, + dt: null, + av: null, + cgid: null, + das: null, + ia: null, + c: null, + csm: null, + les: null, + ssd: null, + }, + l: null, + }); + }); + + it('should clear out the persistence data in persistence', () => { + const store: IStore = new Store( + sampleConfig, + window.mParticle.getInstance() + ); + + const persistenceData = { + gs: { + csm: ['mpid3'], + sid: 'abcd', + ie: true, + dt: apiKey, + cgid: 'cgid1', + das: 'das1', + } as IGlobalStoreV2MinifiedKeys, + cu: 'mpid3', + l: false, + mpid1: { + ua: { + gender: 'female', + age: 29, + height: '65', + color: 'blue', + id: 'abcdefghijklmnopqrstuvwxyz', + }, + ui: { 1: 'customerid123', 2: 'facebookid123' }, + }, + mpid2: { + ua: { gender: 'male', age: 20, height: '68', color: 'red' }, + ui: { + 1: 'customerid234', + 2: 'facebookid234', + id: 'abcdefghijklmnopqrstuvwxyz', + }, + }, + mpid3: { + ua: { gender: 'male', age: 20, height: '68', color: 'red' }, + ui: { + 1: 'customerid234', + 2: 'facebookid234', + id: 'abcdefghijklmnopqrstuvwxyz', + }, + }, + }; + + window.mParticle + .getInstance() + ._Persistence.savePersistence(persistenceData); + + expect( + window.mParticle.getInstance()._Persistence.getPersistence() + ).not.to.deep.equal(null); + + store.persistenceData = persistenceData; + + store.resetPersistenceData(); + + expect( + window.mParticle.getInstance()._Persistence.getPersistence() + ).to.deep.equal(null); + }); + }); });