From 2f0726bd3aecee9adde467688ab94d96fed60093 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Wed, 7 Aug 2024 15:17:45 -0600 Subject: [PATCH 01/23] allow init multiple calls and certain properties to be changed --- src/apiClient.ts | 4 ++ src/sdkBase.ts | 89 +++++++++++++++++++++++++++++++++---------- src/storageManager.ts | 4 ++ 3 files changed, 76 insertions(+), 21 deletions(-) diff --git a/src/apiClient.ts b/src/apiClient.ts index a2c8f66..8b33ed6 100644 --- a/src/apiClient.ts +++ b/src/apiClient.ts @@ -127,6 +127,10 @@ export class ApiClient { return this._requestsInFlight.length > 0; } + public updateBaseUrl(newBaseUrl: string) { + this._baseUrl = newBaseUrl; + } + private ResponseToRefreshResult( response: UnvalidatedRefreshResponse | unknown ): RefreshResult | string { diff --git a/src/sdkBase.ts b/src/sdkBase.ts index eeea648..8a67698 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -172,34 +172,81 @@ export abstract class SdkBase { if (this._apiClient) this._apiClient.abortActiveRequests(); } + private createApiClient(opts: SdkOptions) { + this._apiClient = new ApiClient(opts, this._product.defaultBaseUrl, this._product.name); + this._tokenPromiseHandler.registerApiClient(this._apiClient); + } + private initInternal(opts: SdkOptions | unknown) { - if (this._initComplete) { - throw new TypeError('Calling init() more than once is not allowed'); - } if (!isSDKOptionsOrThrow(opts)) throw new TypeError(`Options provided to ${this._product.name} init couldn't be validated.`); - this._opts = opts; - this._storageManager = new StorageManager( - { ...opts }, - this._product.cookieName, - this._product.localStorageKey - ); - this._apiClient = new ApiClient(opts, this._product.defaultBaseUrl, this._product.name); - this._tokenPromiseHandler.registerApiClient(this._apiClient); + if (this._initComplete) { + //throw new TypeError('Calling init() more than once is not allowed'); + + // do nothing if nothing changed between init calls + if (this._opts === opts) { + this._logger.log('SdkOptions have not changed from the previous init() call'); + return; + } + + // update storage manager + if (opts.cookieDomain || opts.cookiePath) { + this._storageManager?.updateCookieManager(opts, this._product.cookieName); + } + + // update base URL of existing client if it has changed + if (opts.baseUrl) { + if (this._apiClient && opts.baseUrl !== this._opts.baseUrl) { + this._apiClient.updateBaseUrl(opts.baseUrl); + this._logger.log('BaseUrl updated for ApiClient'); + } else { + this.createApiClient(opts); + this._logger.log('new API client created'); + } + } + + // update identity if it is given and is not expired + if (opts.identity && opts.identity.identity_expires < Date.now()) { + /// update identity if an identity doesnt exist or if the expiration date of the new identity if later than the expiration date of old identity + if ( + !this._opts.identity || + opts.identity.identity_expires > this._opts.identity.identity_expires + ) { + this.setIdentity(opts.identity); + this._logger.log('new identity set'); + } else { + this._logger.log('previous identity kept because it expires after new identity'); + } + } else { + this._logger.log('new identity does not exist or is expired'); + } - let identity; - if (this._opts.identity) { - identity = this._opts.identity; + // set opts + this._opts = opts; } else { - identity = this._storageManager.loadIdentityWithFallback(); + this._opts = opts; + this._storageManager = new StorageManager( + { ...opts }, + this._product.cookieName, + this._product.localStorageKey + ); + + this.createApiClient(this._opts); + + let identity; + if (this._opts.identity) { + identity = this._opts.identity; + } else { + identity = this._storageManager.loadIdentityWithFallback(); + } + const validatedIdentity = this.validateAndSetIdentity(identity); + if (validatedIdentity && !isOptoutIdentity(validatedIdentity)) + this.triggerRefreshOrSetTimer(validatedIdentity); + this._initComplete = true; + this._callbackManager?.runCallbacks(EventType.InitCompleted, {}); + if (this.hasOptedOut()) this._callbackManager.runCallbacks(EventType.OptoutReceived, {}); } - const validatedIdentity = this.validateAndSetIdentity(identity); - if (validatedIdentity && !isOptoutIdentity(validatedIdentity)) - this.triggerRefreshOrSetTimer(validatedIdentity); - this._initComplete = true; - this._callbackManager?.runCallbacks(EventType.InitCompleted, {}); - if (this.hasOptedOut()) this._callbackManager.runCallbacks(EventType.OptoutReceived, {}); } private isLoggedIn() { diff --git a/src/storageManager.ts b/src/storageManager.ts index f11d5e4..0193b34 100644 --- a/src/storageManager.ts +++ b/src/storageManager.ts @@ -34,6 +34,10 @@ export class StorageManager { this.setValue(identity); } + public updateCookieManager(opts: SdkOptions, cookieName: string) { + this._cookieManager = new CookieManager({ ...opts }, cookieName); + } + public setOptout() { const expiry = Date.now() + 72 * 60 * 60 * 1000; // 3 days - need to pick something const optout: OptoutIdentity = { From 50c4a2610ba80594a27173397dfd8a0aeaaa281e Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Thu, 8 Aug 2024 14:20:28 -0600 Subject: [PATCH 02/23] wrote tests and add check for init complete --- src/integrationTests/options.test.ts | 208 +++++++++++++++++++++++++++ src/sdkBase.ts | 30 +++- 2 files changed, 232 insertions(+), 6 deletions(-) diff --git a/src/integrationTests/options.test.ts b/src/integrationTests/options.test.ts index a67c4bc..933fcd9 100644 --- a/src/integrationTests/options.test.ts +++ b/src/integrationTests/options.test.ts @@ -193,3 +193,211 @@ describe('useCookie option', () => { }); }); }); + +describe('multiple init calls', () => { + const identity = makeIdentity(); + const baseUrl = 'http://test-host'; + const cookiePath = '/test/'; + + describe('when nothing has changed', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + }); + test('should return next two init calls without changing anything', () => { + //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + }); + }); + + describe('invalid options given in first init call', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + }); + test('should throw error', () => { + expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + }); + }); + + describe('invalid options given in second init call', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + }); + test('should throw error', () => { + expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + }); + }); + + describe('new base URL is given', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + uid2.init({ + baseUrl: 'http://test', + }); + }); + test('should update base url', () => { + //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + }); + }); + + describe('new identity provided and old identity does not exist', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + uid2.init({ + baseUrl: 'http://test', + }); + }); + test('should create new identity', () => { + //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + }); + }); + + describe('new identity provided but expired', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + uid2.init({ + baseUrl: 'http://test', + }); + }); + test('should not update the identity', () => { + //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + }); + }); + + describe('new identity provided but expires before old identity', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + uid2.init({ + baseUrl: 'http://test', + }); + }); + test('should not update the identity', () => { + //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + }); + }); + + describe('new identity provided and expires after old identity', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + uid2.init({ + baseUrl: 'http://test', + }); + }); + test('should update identity to the new one', () => { + //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + }); + }); + + describe('new cookie domain and new cookie path', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + uid2.init({ + baseUrl: 'http://test', + }); + }); + test('should update cookie manager', () => { + //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + }); + }); + + describe('new cookie domain only', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + uid2.init({ + baseUrl: 'http://test', + }); + }); + test('should update cookie manager', () => { + //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + }); + }); + + describe('new cookie path only', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + uid2.init({ + baseUrl: 'http://test', + }); + }); + test('should update cookie manager', () => { + //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + }); + }); +}); diff --git a/src/sdkBase.ts b/src/sdkBase.ts index 8a67698..a7d9149 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -71,6 +71,14 @@ export abstract class SdkBase { this.initInternal(opts); } + public isInitialized() { + return this._initComplete; + } + + public setInitComplete(isInitComplete: boolean) { + this._initComplete = isInitComplete; + } + public getAdvertisingToken() { return this.getIdentity()?.advertising_token ?? undefined; } @@ -182,17 +190,21 @@ export abstract class SdkBase { throw new TypeError(`Options provided to ${this._product.name} init couldn't be validated.`); if (this._initComplete) { - //throw new TypeError('Calling init() more than once is not allowed'); - // do nothing if nothing changed between init calls if (this._opts === opts) { this._logger.log('SdkOptions have not changed from the previous init() call'); return; } + this.setInitComplete(false); + // update storage manager - if (opts.cookieDomain || opts.cookiePath) { + if ( + (opts.cookieDomain && opts.cookieDomain != this._opts.cookieDomain) || + (opts.cookiePath && opts.cookiePath !== this._opts.cookiePath) + ) { this._storageManager?.updateCookieManager(opts, this._product.cookieName); + this._logger.log('cookie manager updated'); } // update base URL of existing client if it has changed @@ -208,7 +220,8 @@ export abstract class SdkBase { // update identity if it is given and is not expired if (opts.identity && opts.identity.identity_expires < Date.now()) { - /// update identity if an identity doesnt exist or if the expiration date of the new identity if later than the expiration date of old identity + /// update identity if an identity doesnt exist or + // if the expiration date of the new identity if later than the expiration date of old identity if ( !this._opts.identity || opts.identity.identity_expires > this._opts.identity.identity_expires @@ -216,14 +229,19 @@ export abstract class SdkBase { this.setIdentity(opts.identity); this._logger.log('new identity set'); } else { - this._logger.log('previous identity kept because it expires after new identity'); + this._logger.log('new identity not set because expires before current identity'); } } else { this._logger.log('new identity does not exist or is expired'); } + // update usecookie + + // update refreshretryperiod + // set opts this._opts = opts; + this.setInitComplete(true); } else { this._opts = opts; this._storageManager = new StorageManager( @@ -243,7 +261,7 @@ export abstract class SdkBase { const validatedIdentity = this.validateAndSetIdentity(identity); if (validatedIdentity && !isOptoutIdentity(validatedIdentity)) this.triggerRefreshOrSetTimer(validatedIdentity); - this._initComplete = true; + this.setInitComplete(true); this._callbackManager?.runCallbacks(EventType.InitCompleted, {}); if (this.hasOptedOut()) this._callbackManager.runCallbacks(EventType.OptoutReceived, {}); } From e53d1c611e9591291825b16c92ce446319dd0178 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Fri, 9 Aug 2024 13:08:48 -0600 Subject: [PATCH 03/23] added refreshretryperiod logic --- src/sdkBase.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/sdkBase.ts b/src/sdkBase.ts index a7d9149..dcdcdb4 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -203,8 +203,8 @@ export abstract class SdkBase { (opts.cookieDomain && opts.cookieDomain != this._opts.cookieDomain) || (opts.cookiePath && opts.cookiePath !== this._opts.cookiePath) ) { - this._storageManager?.updateCookieManager(opts, this._product.cookieName); - this._logger.log('cookie manager updated'); + this._storageManager?.updateCookieOptions(opts, this._product.cookieName); + this._logger.log('cookie options updated'); } // update base URL of existing client if it has changed @@ -238,6 +238,10 @@ export abstract class SdkBase { // update usecookie // update refreshretryperiod + if (opts.refreshRetryPeriod && this._opts.refreshRetryPeriod !== opts.refreshRetryPeriod) { + this._opts.refreshRetryPeriod = opts.refreshRetryPeriod; + this.setRefreshTimer(); + } // set opts this._opts = opts; From 10f387365762545400f07604ed5509f828999ccb Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Fri, 9 Aug 2024 13:50:13 -0600 Subject: [PATCH 04/23] update identity when cookie is being used and cookie path or domain changes --- src/sdkBase.ts | 33 +++++++++++++++------------------ src/storageManager.ts | 7 ++++++- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/sdkBase.ts b/src/sdkBase.ts index 3707b54..9b8ad76 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -181,11 +181,6 @@ export abstract class SdkBase { if (this._apiClient) this._apiClient.abortActiveRequests(); } - private createApiClient(opts: SdkOptions) { - this._apiClient = new ApiClient(opts, this._product.defaultBaseUrl, this._product.name); - this._tokenPromiseHandler.registerApiClient(this._apiClient); - } - private initInternal(opts: SdkOptions | unknown) { if (!isSDKOptionsOrThrow(opts)) throw new TypeError(`Options provided to ${this._product.name} init couldn't be validated.`); @@ -197,15 +192,6 @@ export abstract class SdkBase { return; } - this._opts = opts; - this._storageManager = new StorageManager( - { ...opts }, - this._product.cookieName, - this._product.localStorageKey - ); - this._apiClient = new ApiClient(opts, this._product.defaultBaseUrl, this._product.name); - this._tokenPromiseHandler.registerApiClient(this._apiClient); - this.setInitComplete(false); // update storage manager @@ -213,7 +199,13 @@ export abstract class SdkBase { (opts.cookieDomain && opts.cookieDomain != this._opts.cookieDomain) || (opts.cookiePath && opts.cookiePath !== this._opts.cookiePath) ) { + storeConfig(opts, this._product); this._storageManager?.updateCookieOptions(opts, this._product.cookieName); + + if (this._opts.useCookie === true || opts.useCookie === true) { + this._storageManager?.loadIdentity(); + } + this._logger.log('cookie options updated'); } @@ -222,9 +214,6 @@ export abstract class SdkBase { if (this._apiClient && opts.baseUrl !== this._opts.baseUrl) { this._apiClient.updateBaseUrl(opts.baseUrl); this._logger.log('BaseUrl updated for ApiClient'); - } else { - this.createApiClient(opts); - this._logger.log('new API client created'); } } @@ -246,6 +235,11 @@ export abstract class SdkBase { } // update usecookie + if (opts.useCookie && this._opts.useCookie !== opts.useCookie) { + storeConfig(opts, this._product); + this._storageManager?.updateUseCookie(opts.useCookie); + this._logger.log('new use cookie variable, updated store config and storage manager '); + } // update refreshretryperiod if (opts.refreshRetryPeriod && this._opts.refreshRetryPeriod !== opts.refreshRetryPeriod) { @@ -253,6 +247,8 @@ export abstract class SdkBase { this.setRefreshTimer(); } + //update init callback + // set opts this._opts = opts; this.setInitComplete(true); @@ -265,7 +261,8 @@ export abstract class SdkBase { this._product.localStorageKey ); - this.createApiClient(this._opts); + this._apiClient = new ApiClient(opts, this._product.defaultBaseUrl, this._product.name); + this._tokenPromiseHandler.registerApiClient(this._apiClient); let identity; if (this._opts.identity) { diff --git a/src/storageManager.ts b/src/storageManager.ts index 0193b34..196ee6e 100644 --- a/src/storageManager.ts +++ b/src/storageManager.ts @@ -34,10 +34,15 @@ export class StorageManager { this.setValue(identity); } - public updateCookieManager(opts: SdkOptions, cookieName: string) { + public updateCookieOptions(opts: SdkOptions, cookieName: string) { this._cookieManager = new CookieManager({ ...opts }, cookieName); } + public updateUseCookie(useCookie: boolean) { + this._opts.useCookie = useCookie; + this.loadIdentity(); + } + public setOptout() { const expiry = Date.now() + 72 * 60 * 60 * 1000; // 3 days - need to pick something const optout: OptoutIdentity = { From bcf77b3cd877150b514e222bc3aae1bd1a33ba28 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Fri, 9 Aug 2024 16:03:25 -0600 Subject: [PATCH 05/23] changes to have multiple initcallbacks that are pushed into array --- src/initCallbacks.ts | 49 ++++++++++++++++++++++++---------------- src/sdkBase.ts | 53 ++++++++++++++++++-------------------------- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/initCallbacks.ts b/src/initCallbacks.ts index 257887a..81a7bd3 100644 --- a/src/initCallbacks.ts +++ b/src/initCallbacks.ts @@ -21,24 +21,35 @@ export enum IdentityStatus { OPTOUT = -4, } -export function notifyInitCallback( - options: InitCallbackOptions, - status: IdentityStatus, - statusText: string, - advertisingToken: string | undefined, - logger: Logger -) { - if (options.callback) { - const payload = { - advertisingToken: advertisingToken, - advertising_token: advertisingToken, - status: status, - statusText: statusText, - }; - try { - options.callback(payload); - } catch (exception) { - logger.warn('SDK init callback threw an exception', exception); - } +export class InitCallbackManager { + private _callbacks: InitCallbackFunction[]; + + constructor(opts: InitCallbackOptions) { + this._callbacks = opts.callback ? [opts.callback] : []; + } + + public addCallback(callback: InitCallbackFunction) { + this._callbacks.push(callback); + } + + public notifyInitCallbacks( + status: IdentityStatus, + statusText: string, + advertisingToken: string | undefined, + logger: Logger + ) { + this._callbacks.forEach((callback) => { + const payload = { + advertisingToken: advertisingToken, + advertising_token: advertisingToken, + status: status, + statusText: statusText, + }; + try { + callback(payload); + } catch (exception) { + logger.warn('SDK init callback threw an exception', exception); + } + }); } } diff --git a/src/sdkBase.ts b/src/sdkBase.ts index 9b8ad76..a28874d 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -1,6 +1,6 @@ import { version } from '../package.json'; import { OptoutIdentity, Identity, isOptoutIdentity } from './Identity'; -import { IdentityStatus, notifyInitCallback } from './initCallbacks'; +import { IdentityStatus, InitCallbackManager } from './initCallbacks'; import { SdkOptions, isSDKOptionsOrThrow } from './sdkOptions'; import { Logger, MakeLogger } from './sdk/logger'; import { ApiClient } from './apiClient'; @@ -46,6 +46,7 @@ export abstract class SdkBase { // Dependencies initialised on call to init due to requirement for options private _storageManager: StorageManager | undefined; private _apiClient: ApiClient | undefined; + private _initCallbackManager: InitCallbackManager | undefined; // State protected _product: ProductDetails; @@ -185,16 +186,9 @@ export abstract class SdkBase { if (!isSDKOptionsOrThrow(opts)) throw new TypeError(`Options provided to ${this._product.name} init couldn't be validated.`); - if (this._initComplete) { - // do nothing if nothing changed between init calls - if (this._opts === opts) { - this._logger.log('SdkOptions have not changed from the previous init() call'); - return; - } - + if (this.isInitialized()) { this.setInitComplete(false); - // update storage manager if ( (opts.cookieDomain && opts.cookieDomain != this._opts.cookieDomain) || (opts.cookiePath && opts.cookiePath !== this._opts.cookiePath) @@ -205,53 +199,46 @@ export abstract class SdkBase { if (this._opts.useCookie === true || opts.useCookie === true) { this._storageManager?.loadIdentity(); } - this._logger.log('cookie options updated'); } - // update base URL of existing client if it has changed - if (opts.baseUrl) { - if (this._apiClient && opts.baseUrl !== this._opts.baseUrl) { - this._apiClient.updateBaseUrl(opts.baseUrl); - this._logger.log('BaseUrl updated for ApiClient'); - } + if (opts.baseUrl && opts.baseUrl !== this._opts.baseUrl) { + this._apiClient?.updateBaseUrl(opts.baseUrl); + this._logger.log('BaseUrl updated for ApiClient'); } - // update identity if it is given and is not expired if (opts.identity && opts.identity.identity_expires < Date.now()) { - /// update identity if an identity doesnt exist or - // if the expiration date of the new identity if later than the expiration date of old identity if ( !this._opts.identity || opts.identity.identity_expires > this._opts.identity.identity_expires ) { - this.setIdentity(opts.identity); + const validatedIdentity = this.validateAndSetIdentity(opts.identity); + if (validatedIdentity && !isOptoutIdentity(validatedIdentity)) + this.triggerRefreshOrSetTimer(validatedIdentity); this._logger.log('new identity set'); } else { this._logger.log('new identity not set because expires before current identity'); } - } else { - this._logger.log('new identity does not exist or is expired'); } - // update usecookie if (opts.useCookie && this._opts.useCookie !== opts.useCookie) { storeConfig(opts, this._product); this._storageManager?.updateUseCookie(opts.useCookie); this._logger.log('new use cookie variable, updated store config and storage manager '); } - // update refreshretryperiod if (opts.refreshRetryPeriod && this._opts.refreshRetryPeriod !== opts.refreshRetryPeriod) { this._opts.refreshRetryPeriod = opts.refreshRetryPeriod; this.setRefreshTimer(); + this._logger.log('new refresh period set and refresh timer set'); } - //update init callback + if (opts.callback) { + this._initCallbackManager?.addCallback(opts.callback); + this._logger.log('init callback added to list'); + } - // set opts this._opts = opts; - this.setInitComplete(true); } else { storeConfig(opts, this._product); this._opts = opts; @@ -264,6 +251,8 @@ export abstract class SdkBase { this._apiClient = new ApiClient(opts, this._product.defaultBaseUrl, this._product.name); this._tokenPromiseHandler.registerApiClient(this._apiClient); + this._initCallbackManager = new InitCallbackManager(opts); + let identity; if (this._opts.identity) { identity = this._opts.identity; @@ -273,10 +262,11 @@ export abstract class SdkBase { const validatedIdentity = this.validateAndSetIdentity(identity); if (validatedIdentity && !isOptoutIdentity(validatedIdentity)) this.triggerRefreshOrSetTimer(validatedIdentity); - this.setInitComplete(true); - this._callbackManager?.runCallbacks(EventType.InitCompleted, {}); - if (this.hasOptedOut()) this._callbackManager.runCallbacks(EventType.OptoutReceived, {}); } + + this.setInitComplete(true); + this._callbackManager?.runCallbacks(EventType.InitCompleted, {}); + if (this.hasOptedOut()) this._callbackManager.runCallbacks(EventType.OptoutReceived, {}); } private isLoggedIn() { @@ -394,8 +384,7 @@ export abstract class SdkBase { this.abort(); this._storageManager.removeValues(); } - notifyInitCallback( - this._opts, + this._initCallbackManager?.notifyInitCallbacks( status ?? validity.status, statusText ?? validity.errorMessage, this.getAdvertisingToken(), From 9131642475c890daa1421b47d8f7dc39c0a60ca7 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Fri, 9 Aug 2024 17:10:48 -0600 Subject: [PATCH 06/23] adding tests for multiple init calls --- src/integrationTests/basic.test.ts | 8 +- src/integrationTests/options.test.ts | 214 ++++++++++++++++++++++++--- 2 files changed, 198 insertions(+), 24 deletions(-) diff --git a/src/integrationTests/basic.test.ts b/src/integrationTests/basic.test.ts index b391f61..489bc81 100644 --- a/src/integrationTests/basic.test.ts +++ b/src/integrationTests/basic.test.ts @@ -134,10 +134,10 @@ testCookieAndLocalStorage(() => { }); }); - test('init() should fail if called multiple times', () => { - uid2.init({ callback: () => {} }); - expect(() => uid2.init({ callback: () => {} })).toThrow(); - }); + // test('init() should fail if called multiple times', () => { + // uid2.init({ callback: () => {} }); + // expect(() => uid2.init({ callback: () => {} })).toThrow(); + // }); describe('when initialised without identity', () => { describe('when uid2 value is not available', () => { diff --git a/src/integrationTests/options.test.ts b/src/integrationTests/options.test.ts index 6594a13..fedcad1 100644 --- a/src/integrationTests/options.test.ts +++ b/src/integrationTests/options.test.ts @@ -32,6 +32,9 @@ const getUid2Cookie = mocks.getUid2Cookie; const getUid2LocalStorage = mocks.getUid2LocalStorage; const removeUid2Cookie = mocks.removeUid2Cookie; const removeUid2LocalStorage = mocks.removeUid2LocalStorage; +const getUid2 = mocks.getUid2; + +let useCookie: boolean | undefined = undefined; const getConfigCookie = () => { const docCookie = document.cookie; @@ -220,6 +223,7 @@ describe('multiple init calls', () => { const identity = makeIdentity(); const baseUrl = 'http://test-host'; const cookiePath = '/test/'; + const cookieDomain = 'uidapi.com'; describe('when nothing has changed', () => { beforeEach(() => { @@ -263,7 +267,7 @@ describe('multiple init calls', () => { }); }); test('should throw error', () => { - expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); }); }); @@ -295,33 +299,56 @@ describe('multiple init calls', () => { baseUrl: baseUrl, cookiePath: cookiePath, }); + }); + test('should use new base url', () => { uid2.init({ baseUrl: 'http://test', }); + expect(xhrMock.open.mock.calls.length).toBe(1); + expect(xhrMock.open.mock.calls[0][1]).not.toContain(baseUrl); + expect(xhrMock.open.mock.calls[0][1]).toContain('http://test'); }); - test('should update base url', () => { - //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + + test('should use old base url', () => { + uid2.init({ + cookiePath: cookiePath, + }); + expect(xhrMock.open.mock.calls.length).toBe(1); + expect(xhrMock.open.mock.calls[0][1]).not.toContain('http://test'); + expect(xhrMock.open.mock.calls[0][1]).toContain(baseUrl); }); }); describe('new identity provided and old identity does not exist', () => { + const newIdentity = makeIdentity(); + beforeEach(() => { uid2.init({ callback: callback, - identity: identity, baseUrl: baseUrl, cookiePath: cookiePath, }); uid2.init({ - baseUrl: 'http://test', + identity: newIdentity, }); }); test('should create new identity', () => { - //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + test('should set value', () => { + expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); + }); + test('should set refresh timer', () => { + expect(setTimeout).toHaveBeenCalledTimes(1); + expect(clearTimeout).not.toHaveBeenCalled(); + }); + test('should be in available state', () => { + (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); + }); }); }); describe('new identity provided but expired', () => { + const newIdentity = makeIdentity({ refresh_expires: Date.now() - 100000 }); + beforeEach(() => { uid2.init({ callback: callback, @@ -330,32 +357,55 @@ describe('multiple init calls', () => { cookiePath: cookiePath, }); uid2.init({ - baseUrl: 'http://test', + identity: newIdentity, }); }); test('should not update the identity', () => { - //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + test('should set value', () => { + expect(getUid2(useCookie).advertising_token).toBe(identity.advertising_token); + }); + test('should set refresh timer', () => { + expect(setTimeout).toHaveBeenCalledTimes(1); + expect(clearTimeout).not.toHaveBeenCalled(); + }); + test('should be in available state', () => { + (expect(uid2) as any).toBeInAvailableState(identity.advertising_token); + }); }); }); describe('new identity provided but expires before old identity', () => { + const oldIdentity = makeIdentity({ refresh_expires: Date.now() + 5000 }); + const newIdentity = makeIdentity({ refresh_expires: Date.now() + 100000 }); + beforeEach(() => { uid2.init({ callback: callback, - identity: identity, + identity: oldIdentity, baseUrl: baseUrl, cookiePath: cookiePath, }); uid2.init({ - baseUrl: 'http://test', + identity: newIdentity, }); }); test('should not update the identity', () => { - //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + test('should set value', () => { + expect(getUid2(useCookie).advertising_token).toBe(oldIdentity.advertising_token); + }); + test('should set refresh timer', () => { + expect(setTimeout).toHaveBeenCalledTimes(1); + expect(clearTimeout).not.toHaveBeenCalled(); + }); + test('should be in available state', () => { + (expect(uid2) as any).toBeInAvailableState(oldIdentity.advertising_token); + }); }); }); describe('new identity provided and expires after old identity', () => { + const newIdentity = makeIdentity(); + beforeEach(() => { uid2.init({ callback: callback, @@ -364,32 +414,51 @@ describe('multiple init calls', () => { cookiePath: cookiePath, }); uid2.init({ - baseUrl: 'http://test', + identity: newIdentity, }); }); test('should update identity to the new one', () => { - //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + test('should set value', () => { + expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); + }); + test('should set refresh timer', () => { + expect(setTimeout).toHaveBeenCalledTimes(1); + expect(clearTimeout).not.toHaveBeenCalled(); + }); + test('should be in available state', () => { + (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); + }); }); }); describe('new cookie domain and new cookie path', () => { + const newCookiePath = '/'; + const newCookieDomain = 'test.com'; + beforeEach(() => { uid2.init({ callback: callback, identity: identity, baseUrl: baseUrl, cookiePath: cookiePath, + cookieDomain: cookieDomain, }); uid2.init({ - baseUrl: 'http://test', + cookiePath: newCookiePath, + cookieDomain: newCookieDomain, }); }); - test('should update cookie manager', () => { - //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + test('should update cookie manager and config cookie', () => { + const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); + expect(cookie).toContain(`Domain=${newCookieDomain};`); + expect(cookie + ';').toContain(`Path=${newCookiePath};`); + expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); + expect(getConfigCookie() + ';').toHaveProperty('cookiePath', newCookiePath); }); }); describe('new cookie domain only', () => { + const newCookieDomain = 'test.com'; beforeEach(() => { uid2.init({ callback: callback, @@ -398,28 +467,133 @@ describe('multiple init calls', () => { cookiePath: cookiePath, }); uid2.init({ - baseUrl: 'http://test', + cookieDomain: newCookieDomain, }); }); test('should update cookie manager', () => { - //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); + expect(cookie).toContain(`Domain=${newCookieDomain};`); + expect(cookie + ';').toContain(`Path=${cookiePath};`); + expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); + expect(getConfigCookie() + ';').toHaveProperty('cookiePath', cookiePath); }); }); describe('new cookie path only', () => { + const newCookiePath = '/'; + beforeEach(() => { uid2.init({ callback: callback, identity: identity, baseUrl: baseUrl, + cookieDomain: cookieDomain, cookiePath: cookiePath, }); uid2.init({ - baseUrl: 'http://test', + cookiePath: newCookiePath, }); }); test('should update cookie manager', () => { - //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); + expect(cookie).toContain(`Domain=${cookieDomain};`); + expect(cookie + ';').toContain(`Path=${newCookiePath};`); + expect(getConfigCookie()).toHaveProperty('cookieDomain', cookieDomain); + expect(getConfigCookie() + ';').toHaveProperty('cookiePath', newCookiePath); + }); + }); + + describe('new refreshretry period', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + refreshRetryPeriod: 12345, + }); + uid2.init({ + refreshRetryPeriod: 67890, + }); + }); + test('should use the new refresh retry period', () => { + expect(setTimeout).toHaveBeenCalledTimes(1); + expect(setTimeout).toBeCalledWith(expect.any(Function), 67890); + }); + }); + + describe('usecookie changing from true to false', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + refreshRetryPeriod: 12345, + useCookie: true, + }); + uid2.init({ + useCookie: false, + }); + }); + test('should change config from cookie to local storage', () => { + test('should store config in local storage', () => { + const storageConfig = getConfigStorage(); + expect(storageConfig).toBeInstanceOf(Object); + expect(storageConfig).toHaveProperty('cookiePath'); + const cookie = getConfigCookie(); + expect(cookie).toBeNull(); + }); + }); + + describe('adding a callback when no callbacks exist before', () => { + beforeEach(() => { + uid2.init({ + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + refreshRetryPeriod: 12345, + useCookie: true, + }); + uid2.init({ + useCookie: false, + callback: callback, + }); + }); + test('should change config from cookie to local storage', () => { + test('should store config in local storage', () => { + const storageConfig = getConfigStorage(); + expect(storageConfig).toBeInstanceOf(Object); + expect(storageConfig).toHaveProperty('cookiePath'); + const cookie = getConfigCookie(); + expect(cookie).toBeNull(); + }); + }); + }); + + describe('adding a callback', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + refreshRetryPeriod: 12345, + useCookie: false, + }); + uid2.init({ + callback: jest.fn(), + }); + }); + test('should change config from local storage to cookie', () => { + test('should store config in cookie', () => { + const cookie = getConfigCookie(); + expect(cookie).toBeInstanceOf(Object); + expect(cookie).toHaveProperty('cookiePath'); + const storageConfig = getConfigStorage(); + expect(storageConfig).toBeNull(); + }); + }); }); }); }); From cc5b91862d800d88ce46c6e4a855dd522145be7c Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Sat, 10 Aug 2024 00:17:48 -0600 Subject: [PATCH 07/23] testing the tests --- src/configManager.ts | 11 +- src/integrationTests/basic.test.ts | 16 +- src/integrationTests/options.test.ts | 779 ++++++++++++++------------- src/sdkBase.ts | 41 +- 4 files changed, 438 insertions(+), 409 deletions(-) diff --git a/src/configManager.ts b/src/configManager.ts index 2d14f7a..49eac88 100644 --- a/src/configManager.ts +++ b/src/configManager.ts @@ -36,6 +36,15 @@ export const loadConfig = ( } }; +export const updateConfig = (options: SdkOptions, productDetails: ProductDetails) => { + if (options.useCookie) { + removeConfigCookie(productDetails); + } else { + removeConfigFromLocalStorage(productDetails); + } + storeConfig(options, productDetails); +}; + const setConfigCookie = (options: SdkOptions, productDetails: ProductDetails) => { const cookieDomain = options.cookieDomain; const path = options.cookiePath ?? '/'; @@ -58,7 +67,7 @@ const getConfigCookie = (productDetails: ProductDetails) => { if (docCookie) { const payload = docCookie .split('; ') - .find((row) => row.startsWith(productDetails.cookieName + '_config' + '=')); + .filter((row) => row.startsWith(productDetails.cookieName + '_config' + '='))[1]; if (payload) { return decodeURIComponent(payload.split('=')[1]); } diff --git a/src/integrationTests/basic.test.ts b/src/integrationTests/basic.test.ts index 489bc81..26f157f 100644 --- a/src/integrationTests/basic.test.ts +++ b/src/integrationTests/basic.test.ts @@ -963,10 +963,10 @@ testCookieAndLocalStorage(() => { expect(xhrMock.send).toHaveBeenCalledTimes(1); expect(xhrMock.abort).toHaveBeenCalledTimes(1); }); - test('should prevent subsequent calls to init()', () => { - uid2.abort(); - expect(() => uid2.init({ callback: () => {} })).toThrow(); - }); + // test('should prevent subsequent calls to init()', () => { + // uid2.abort(); + // expect(() => uid2.init({ callback: () => {} })).toThrow(); + // }); }); describe('disconnect()', () => { @@ -999,10 +999,10 @@ testCookieAndLocalStorage(() => { expect(xhrMock.send).toHaveBeenCalledTimes(1); expect(xhrMock.abort).toHaveBeenCalledTimes(1); }); - test('should prevent subsequent calls to init()', () => { - uid2.disconnect(); - expect(() => uid2.init({ callback: () => {} })).toThrow(); - }); + // test('should prevent subsequent calls to init()', () => { + // uid2.disconnect(); + // expect(() => uid2.init({ callback: () => {} })).toThrow(); + // }); test('should switch to unavailable state', () => { uid2.init({ callback: callback, diff --git a/src/integrationTests/options.test.ts b/src/integrationTests/options.test.ts index fedcad1..8456cf5 100644 --- a/src/integrationTests/options.test.ts +++ b/src/integrationTests/options.test.ts @@ -225,283 +225,288 @@ describe('multiple init calls', () => { const cookiePath = '/test/'; const cookieDomain = 'uidapi.com'; - describe('when nothing has changed', () => { - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - }); - test('should return next two init calls without changing anything', () => { - //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); - }); - }); - - describe('invalid options given in first init call', () => { - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - }); - test('should throw error', () => { - //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); - }); - }); - - describe('invalid options given in second init call', () => { - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - }); - test('should throw error', () => { - expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); - }); - }); - - describe('new base URL is given', () => { - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - }); - test('should use new base url', () => { - uid2.init({ - baseUrl: 'http://test', - }); - expect(xhrMock.open.mock.calls.length).toBe(1); - expect(xhrMock.open.mock.calls[0][1]).not.toContain(baseUrl); - expect(xhrMock.open.mock.calls[0][1]).toContain('http://test'); - }); - - test('should use old base url', () => { - uid2.init({ - cookiePath: cookiePath, - }); - expect(xhrMock.open.mock.calls.length).toBe(1); - expect(xhrMock.open.mock.calls[0][1]).not.toContain('http://test'); - expect(xhrMock.open.mock.calls[0][1]).toContain(baseUrl); - }); - }); - - describe('new identity provided and old identity does not exist', () => { - const newIdentity = makeIdentity(); - - beforeEach(() => { - uid2.init({ - callback: callback, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - uid2.init({ - identity: newIdentity, - }); - }); - test('should create new identity', () => { - test('should set value', () => { - expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); - }); - test('should set refresh timer', () => { - expect(setTimeout).toHaveBeenCalledTimes(1); - expect(clearTimeout).not.toHaveBeenCalled(); - }); - test('should be in available state', () => { - (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); - }); - }); - }); - - describe('new identity provided but expired', () => { - const newIdentity = makeIdentity({ refresh_expires: Date.now() - 100000 }); - - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - uid2.init({ - identity: newIdentity, - }); - }); - test('should not update the identity', () => { - test('should set value', () => { - expect(getUid2(useCookie).advertising_token).toBe(identity.advertising_token); - }); - test('should set refresh timer', () => { - expect(setTimeout).toHaveBeenCalledTimes(1); - expect(clearTimeout).not.toHaveBeenCalled(); - }); - test('should be in available state', () => { - (expect(uid2) as any).toBeInAvailableState(identity.advertising_token); - }); - }); - }); - - describe('new identity provided but expires before old identity', () => { - const oldIdentity = makeIdentity({ refresh_expires: Date.now() + 5000 }); - const newIdentity = makeIdentity({ refresh_expires: Date.now() + 100000 }); - - beforeEach(() => { - uid2.init({ - callback: callback, - identity: oldIdentity, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - uid2.init({ - identity: newIdentity, - }); - }); - test('should not update the identity', () => { - test('should set value', () => { - expect(getUid2(useCookie).advertising_token).toBe(oldIdentity.advertising_token); - }); - test('should set refresh timer', () => { - expect(setTimeout).toHaveBeenCalledTimes(1); - expect(clearTimeout).not.toHaveBeenCalled(); - }); - test('should be in available state', () => { - (expect(uid2) as any).toBeInAvailableState(oldIdentity.advertising_token); - }); - }); - }); - - describe('new identity provided and expires after old identity', () => { - const newIdentity = makeIdentity(); - - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - uid2.init({ - identity: newIdentity, - }); - }); - test('should update identity to the new one', () => { - test('should set value', () => { - expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); - }); - test('should set refresh timer', () => { - expect(setTimeout).toHaveBeenCalledTimes(1); - expect(clearTimeout).not.toHaveBeenCalled(); - }); - test('should be in available state', () => { - (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); - }); - }); - }); - - describe('new cookie domain and new cookie path', () => { - const newCookiePath = '/'; - const newCookieDomain = 'test.com'; - - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - cookieDomain: cookieDomain, - }); - uid2.init({ - cookiePath: newCookiePath, - cookieDomain: newCookieDomain, - }); - }); - test('should update cookie manager and config cookie', () => { - const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); - expect(cookie).toContain(`Domain=${newCookieDomain};`); - expect(cookie + ';').toContain(`Path=${newCookiePath};`); - expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); - expect(getConfigCookie() + ';').toHaveProperty('cookiePath', newCookiePath); - }); - }); - - describe('new cookie domain only', () => { - const newCookieDomain = 'test.com'; - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - uid2.init({ - cookieDomain: newCookieDomain, - }); - }); - test('should update cookie manager', () => { - const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); - expect(cookie).toContain(`Domain=${newCookieDomain};`); - expect(cookie + ';').toContain(`Path=${cookiePath};`); - expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); - expect(getConfigCookie() + ';').toHaveProperty('cookiePath', cookiePath); - }); - }); - - describe('new cookie path only', () => { - const newCookiePath = '/'; - - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookieDomain: cookieDomain, - cookiePath: cookiePath, - }); - uid2.init({ - cookiePath: newCookiePath, - }); - }); - test('should update cookie manager', () => { - const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); - expect(cookie).toContain(`Domain=${cookieDomain};`); - expect(cookie + ';').toContain(`Path=${newCookiePath};`); - expect(getConfigCookie()).toHaveProperty('cookieDomain', cookieDomain); - expect(getConfigCookie() + ';').toHaveProperty('cookiePath', newCookiePath); - }); - }); + // describe('when nothing has changed', () => { + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // }); + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // }); + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // }); + // }); + // test('should return next two init calls without changing anything', () => { + // //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + // }); + // }); + + // describe('invalid options given in first init call', () => { + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // }); + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // }); + // }); + // test('should throw error', () => { + // //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + // }); + // }); + + // describe('invalid options given in second init call', () => { + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // }); + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // }); + // }); + // test('should throw error', () => { + // expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + // }); + // }); + + // describe('new base URL is given', () => { + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // }); + // }); + // test('should use new base url', () => { + // uid2.init({ + // baseUrl: 'http://test', + // }); + // //expect(xhrMock.open.mock.calls.length).toBe(1); + // expect(xhrMock.open.mock.calls[0][1]).not.toContain(baseUrl); + // expect(xhrMock.open.mock.calls[0][1]).toContain('http://test'); + // }); + + // test('should use old base url', () => { + // uid2.init({ + // cookiePath: cookiePath, + // }); + // //expect(xhrMock.open.mock.calls.length).toBe(1); + // expect(xhrMock.open.mock.calls[0][1]).not.toContain('http://test'); + // expect(xhrMock.open.mock.calls[0][1]).toContain(baseUrl); + // }); + // }); + + // describe('new identity provided and old identity does not exist', () => { + // const newIdentity = makeIdentity(); + + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // }); + // uid2.init({ + // identity: newIdentity, + // }); + // }); + // test('should create new identity', () => { + // test('should set value', () => { + // expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); + // }); + // test('should set refresh timer', () => { + // expect(setTimeout).toHaveBeenCalledTimes(1); + // expect(clearTimeout).not.toHaveBeenCalled(); + // }); + // test('should be in available state', () => { + // (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); + // }); + // }); + // }); + + // describe('new identity provided but expired', () => { + // const newIdentity = makeIdentity({ refresh_expires: Date.now() - 100000 }); + + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // }); + // uid2.init({ + // identity: newIdentity, + // }); + // }); + // test('should not update the identity', () => { + // test('should set value', () => { + // expect(getUid2(useCookie).advertising_token).toBe(identity.advertising_token); + // }); + // test('should set refresh timer', () => { + // expect(setTimeout).toHaveBeenCalledTimes(1); + // expect(clearTimeout).not.toHaveBeenCalled(); + // }); + // test('should be in available state', () => { + // (expect(uid2) as any).toBeInAvailableState(identity.advertising_token); + // }); + // }); + // }); + + // describe('new identity provided but expires before old identity', () => { + // const oldIdentity = makeIdentity({ refresh_expires: Date.now() + 5000 }); + // const newIdentity = makeIdentity({ refresh_expires: Date.now() + 100000 }); + + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // identity: oldIdentity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // }); + // uid2.init({ + // identity: newIdentity, + // }); + // }); + // test('should not update the identity', () => { + // test('should set value', () => { + // expect(getUid2(useCookie).advertising_token).toBe(oldIdentity.advertising_token); + // }); + // test('should set refresh timer', () => { + // expect(setTimeout).toHaveBeenCalledTimes(1); + // expect(clearTimeout).not.toHaveBeenCalled(); + // }); + // test('should be in available state', () => { + // (expect(uid2) as any).toBeInAvailableState(oldIdentity.advertising_token); + // }); + // }); + // }); + + // describe('new identity provided and expires after old identity', () => { + // const newIdentity = makeIdentity(); + + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // }); + // uid2.init({ + // identity: newIdentity, + // }); + // }); + // test('should update identity to the new one', () => { + // test('should set value', () => { + // expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); + // }); + // test('should set refresh timer', () => { + // expect(setTimeout).toHaveBeenCalledTimes(1); + // expect(clearTimeout).not.toHaveBeenCalled(); + // }); + // test('should be in available state', () => { + // (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); + // }); + // }); + // }); + + // describe('new cookie domain and new cookie path', () => { + // const newCookiePath = '/'; + // const newCookieDomain = 'www.uidapi.com'; + + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // cookieDomain: cookieDomain, + // useCookie: true, + // }); + // uid2.init({ + // cookiePath: newCookiePath, + // cookieDomain: newCookieDomain, + // }); + // }); + // test('should update cookie manager and config cookie', () => { + // const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); + // //expect(cookie).toContain(`Domain=${newCookieDomain};`); + // //expect(cookie + ';').toContain(`Path=${newCookiePath};`); + // expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); + // expect(getConfigCookie() + ';').toHaveProperty('cookiePath', newCookiePath); + // }); + // }); + + // describe('new cookie domain only', () => { + // const newCookieDomain = 'www.uidapi.com'; + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // useCookie: true, + // }); + // uid2.init({ + // cookieDomain: newCookieDomain, + // }); + // }); + // test('should update cookie manager', () => { + // const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); + // //expect(cookie).toContain(`Domain=${newCookieDomain};`); + // //expect(cookie + ';').toContain(`Path=${cookiePath};`); + // expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); + // expect(getConfigCookie() + ';').toHaveProperty('cookiePath', cookiePath); + // }); + // }); + + // describe('new cookie path only', () => { + // const newCookiePath = '/'; + + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookieDomain: cookieDomain, + // cookiePath: cookiePath, + // useCookie: true, + // }); + // uid2.init({ + // cookiePath: newCookiePath, + // }); + // }); + + // test('should update cookie manager', () => { + // const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); + // expect(cookie).toContain(`Domain=${cookieDomain};`); + // expect(cookie + ';').toContain(`Path=${newCookiePath};`); + // const configCookie = getConfigCookie(); + // expect(configCookie).toHaveProperty('cookieDomain', cookieDomain); + // expect(configCookie).toHaveProperty('cookiePath', newCookiePath); + // }); + // }); describe('new refreshretry period', () => { beforeEach(() => { @@ -517,119 +522,119 @@ describe('multiple init calls', () => { }); }); test('should use the new refresh retry period', () => { - expect(setTimeout).toHaveBeenCalledTimes(1); + expect(setTimeout).toHaveBeenCalledTimes(2); expect(setTimeout).toBeCalledWith(expect.any(Function), 67890); }); }); - describe('usecookie changing from true to false', () => { - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - refreshRetryPeriod: 12345, - useCookie: true, - }); - uid2.init({ - useCookie: false, - }); - }); - test('should change config from cookie to local storage', () => { - test('should store config in local storage', () => { - const storageConfig = getConfigStorage(); - expect(storageConfig).toBeInstanceOf(Object); - expect(storageConfig).toHaveProperty('cookiePath'); - const cookie = getConfigCookie(); - expect(cookie).toBeNull(); - }); - }); - - describe('adding a callback when no callbacks exist before', () => { - beforeEach(() => { - uid2.init({ - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - refreshRetryPeriod: 12345, - useCookie: true, - }); - uid2.init({ - useCookie: false, - callback: callback, - }); - }); - test('should change config from cookie to local storage', () => { - test('should store config in local storage', () => { - const storageConfig = getConfigStorage(); - expect(storageConfig).toBeInstanceOf(Object); - expect(storageConfig).toHaveProperty('cookiePath'); - const cookie = getConfigCookie(); - expect(cookie).toBeNull(); - }); - }); - }); - - describe('adding a callback', () => { - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - refreshRetryPeriod: 12345, - useCookie: false, - }); - uid2.init({ - callback: jest.fn(), - }); - }); - test('should change config from local storage to cookie', () => { - test('should store config in cookie', () => { - const cookie = getConfigCookie(); - expect(cookie).toBeInstanceOf(Object); - expect(cookie).toHaveProperty('cookiePath'); - const storageConfig = getConfigStorage(); - expect(storageConfig).toBeNull(); - }); - }); - }); - }); + // describe('usecookie changing from true to false', () => { + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // refreshRetryPeriod: 12345, + // useCookie: true, + // }); + // uid2.init({ + // useCookie: false, + // }); + // }); + // test('should change config from cookie to local storage', () => { + // test('should store config in local storage', () => { + // const storageConfig = getConfigStorage(); + // expect(storageConfig).toBeInstanceOf(Object); + // expect(storageConfig).toHaveProperty('cookiePath'); + // const cookie = getConfigCookie(); + // expect(cookie).toBeNull(); + // }); + // }); + + // describe('adding a callback when no callbacks exist before', () => { + // beforeEach(() => { + // uid2.init({ + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // refreshRetryPeriod: 12345, + // useCookie: true, + // }); + // uid2.init({ + // useCookie: false, + // callback: callback, + // }); + // }); + // test('should change config from cookie to local storage', () => { + // test('should store config in local storage', () => { + // const storageConfig = getConfigStorage(); + // expect(storageConfig).toBeInstanceOf(Object); + // expect(storageConfig).toHaveProperty('cookiePath'); + // const cookie = getConfigCookie(); + // expect(cookie).toBeNull(); + // }); + // }); + // }); + + // describe('adding a callback', () => { + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // refreshRetryPeriod: 12345, + // useCookie: false, + // }); + // uid2.init({ + // callback: jest.fn(), + // }); + // }); + // test('should change config from local storage to cookie', () => { + // test('should store config in cookie', () => { + // const cookie = getConfigCookie(); + // expect(cookie).toBeInstanceOf(Object); + // expect(cookie).toHaveProperty('cookiePath'); + // const storageConfig = getConfigStorage(); + // expect(storageConfig).toBeNull(); + // }); + // }); + // }); + // }); }); -describe('Store config UID2', () => { - const identity = makeIdentity(); - const options: SdkOptions = { - baseUrl: 'http://test-host', - cookieDomain: mockDomain, - refreshRetryPeriod: 1000, - useCookie: false, - }; - - beforeEach(() => { - localStorage.removeItem('UID2-sdk-identity_config'); - document.cookie = UID2.COOKIE_NAME + '_config' + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT'; - }); - - describe('when useCookie is true', () => { - test('should store config in cookie', () => { - uid2.init({ callback: callback, identity: identity, ...options, useCookie: true }); - const cookie = getConfigCookie(); - expect(cookie).toBeInstanceOf(Object); - expect(cookie).toHaveProperty('cookieDomain'); - const storageConfig = getConfigStorage(); - expect(storageConfig).toBeNull(); - }); - }); - describe('when useCookie is false', () => { - test('should store config in local storage', () => { - uid2.init({ callback: callback, identity: identity, ...options }); - const storageConfig = getConfigStorage(); - expect(storageConfig).toBeInstanceOf(Object); - expect(storageConfig).toHaveProperty('cookieDomain'); - const cookie = getConfigCookie(); - expect(cookie).toBeNull(); - }); - }); -}); +// describe('Store config UID2', () => { +// const identity = makeIdentity(); +// const options: SdkOptions = { +// baseUrl: 'http://test-host', +// cookieDomain: mockDomain, +// refreshRetryPeriod: 1000, +// useCookie: false, +// }; + +// beforeEach(() => { +// localStorage.removeItem('UID2-sdk-identity_config'); +// document.cookie = UID2.COOKIE_NAME + '_config' + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT'; +// }); + +// describe('when useCookie is true', () => { +// test('should store config in cookie', () => { +// uid2.init({ callback: callback, identity: identity, ...options, useCookie: true }); +// const cookie = getConfigCookie(); +// expect(cookie).toBeInstanceOf(Object); +// expect(cookie).toHaveProperty('cookieDomain'); +// const storageConfig = getConfigStorage(); +// expect(storageConfig).toBeNull(); +// }); +// }); +// describe('when useCookie is false', () => { +// test('should store config in local storage', () => { +// uid2.init({ callback: callback, identity: identity, ...options }); +// const storageConfig = getConfigStorage(); +// expect(storageConfig).toBeInstanceOf(Object); +// expect(storageConfig).toHaveProperty('cookieDomain'); +// const cookie = getConfigCookie(); +// expect(cookie).toBeNull(); +// }); +// }); +// }); diff --git a/src/sdkBase.ts b/src/sdkBase.ts index a28874d..a932333 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -15,7 +15,7 @@ import { PromiseHandler } from './promiseHandler'; import { StorageManager } from './storageManager'; import { hashAndEncodeIdentifier } from './encoding/hash'; import { ProductDetails, ProductName } from './product'; -import { storeConfig } from './configManager'; +import { storeConfig, updateConfig } from './configManager'; function hasExpired(expiry: number, now = Date.now()) { return expiry <= now; @@ -189,21 +189,29 @@ export abstract class SdkBase { if (this.isInitialized()) { this.setInitComplete(false); - if ( - (opts.cookieDomain && opts.cookieDomain != this._opts.cookieDomain) || - (opts.cookiePath && opts.cookiePath !== this._opts.cookiePath) - ) { - storeConfig(opts, this._product); - this._storageManager?.updateCookieOptions(opts, this._product.cookieName); + let shouldUpdateConfig = false; + let shouldUpdateCookieOptions = false; + + if (opts.cookieDomain && opts.cookieDomain != this._opts.cookieDomain) { + shouldUpdateConfig = true; + shouldUpdateCookieOptions = true; + // if (this._opts.useCookie === true || opts.useCookie === true) { + // this._storageManager?.loadIdentity(); + // } + this._opts.cookieDomain = opts.cookieDomain; + this._logger.log('cookie domain updated'); + } - if (this._opts.useCookie === true || opts.useCookie === true) { - this._storageManager?.loadIdentity(); - } - this._logger.log('cookie options updated'); + if (opts.cookiePath && opts.cookiePath !== this._opts.cookiePath) { + shouldUpdateConfig = true; + shouldUpdateCookieOptions = true; + this._opts.cookiePath = opts.cookiePath; + this._logger.log('cookie path updated'); } if (opts.baseUrl && opts.baseUrl !== this._opts.baseUrl) { this._apiClient?.updateBaseUrl(opts.baseUrl); + this._opts.baseUrl = opts.baseUrl; this._logger.log('BaseUrl updated for ApiClient'); } @@ -215,6 +223,7 @@ export abstract class SdkBase { const validatedIdentity = this.validateAndSetIdentity(opts.identity); if (validatedIdentity && !isOptoutIdentity(validatedIdentity)) this.triggerRefreshOrSetTimer(validatedIdentity); + this._opts.identity = opts.identity; this._logger.log('new identity set'); } else { this._logger.log('new identity not set because expires before current identity'); @@ -222,8 +231,9 @@ export abstract class SdkBase { } if (opts.useCookie && this._opts.useCookie !== opts.useCookie) { - storeConfig(opts, this._product); + shouldUpdateConfig = true; this._storageManager?.updateUseCookie(opts.useCookie); + this._opts.useCookie = opts.useCookie; this._logger.log('new use cookie variable, updated store config and storage manager '); } @@ -238,7 +248,12 @@ export abstract class SdkBase { this._logger.log('init callback added to list'); } - this._opts = opts; + if (shouldUpdateConfig) { + updateConfig(this._opts, this._product); + } + if (shouldUpdateCookieOptions) { + this._storageManager?.updateCookieOptions(opts, this._product.cookieName); + } } else { storeConfig(opts, this._product); this._opts = opts; From 6391c85ba030254b87f313e8335755e240d1b063 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Mon, 12 Aug 2024 17:55:44 -0600 Subject: [PATCH 08/23] working through tests --- src/configManager.ts | 3 +- src/cookieManager.ts | 6 +- src/integrationTests/options.test.ts | 465 ++++++++++++++------------- src/sdkBase.ts | 6 +- src/storageManager.ts | 6 +- 5 files changed, 249 insertions(+), 237 deletions(-) diff --git a/src/configManager.ts b/src/configManager.ts index 49eac88..5e0d38b 100644 --- a/src/configManager.ts +++ b/src/configManager.ts @@ -59,7 +59,8 @@ const setConfigCookie = (options: SdkOptions, productDetails: ProductDetails) => const removeConfigCookie = (productDetails: ProductDetails) => { document.cookie = - productDetails.cookieName + '_config' + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT'; + productDetails.cookieName + '_config' + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT;path=/'; + console.log(document.cookie); }; const getConfigCookie = (productDetails: ProductDetails) => { diff --git a/src/cookieManager.ts b/src/cookieManager.ts index 2b093c7..46b2313 100644 --- a/src/cookieManager.ts +++ b/src/cookieManager.ts @@ -51,9 +51,11 @@ export class CookieManager { cookie += ';domain=' + this._opts.cookieDomain; } document.cookie = cookie; + let testcookie = document.cookie; + console.log(testcookie); } - public removeCookie() { - document.cookie = this._cookieName + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT'; + public async removeCookie() { + document.cookie = this._cookieName + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT;path=/'; } private getCookie() { const docCookie = document.cookie; diff --git a/src/integrationTests/options.test.ts b/src/integrationTests/options.test.ts index 8456cf5..f3381c9 100644 --- a/src/integrationTests/options.test.ts +++ b/src/integrationTests/options.test.ts @@ -21,6 +21,9 @@ beforeEach(() => { cookieMock = new mocks.CookieMock(sdkWindow.document); removeUid2Cookie(); removeUid2LocalStorage(); + localStorage.removeItem('UID2-sdk-identity_config'); + document.cookie = UID2.COOKIE_NAME + '_config' + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT'; + document.cookie = UID2.COOKIE_NAME + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT'; }); afterEach(() => { @@ -251,262 +254,263 @@ describe('multiple init calls', () => { // }); // }); - // describe('invalid options given in first init call', () => { - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // }); - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // }); - // }); - // test('should throw error', () => { - // //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + // describe('new base URL is given', () => { + // const identity = makeIdentity({ + // refresh_from: Date.now() - 100000, // }); - // }); - // describe('invalid options given in second init call', () => { - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // }); - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // }); - // }); - // test('should throw error', () => { - // expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); - // }); - // }); + // const oldBaseUrl = baseUrl; + // const newBaseUrl = 'http://example'; - // describe('new base URL is given', () => { // beforeEach(() => { // uid2.init({ // callback: callback, // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, + // baseUrl: oldBaseUrl, // }); // }); // test('should use new base url', () => { // uid2.init({ - // baseUrl: 'http://test', - // }); - // //expect(xhrMock.open.mock.calls.length).toBe(1); - // expect(xhrMock.open.mock.calls[0][1]).not.toContain(baseUrl); - // expect(xhrMock.open.mock.calls[0][1]).toContain('http://test'); - // }); + // callback: callback, + // identity: identity, + // baseUrl: newBaseUrl, + // }); + // console.log(xhrMock.open.mock.calls); + // expect(xhrMock.open.mock.calls.length).toBe(1); + // expect(xhrMock.open.mock.calls[0][1]).not.toContain(oldBaseUrl); + //expect(xhrMock.open.mock.calls[0][1]).toContain(newBaseUrl); + //}); + + // // test('should use old base url', () => { + // // uid2.init({ + // // cookiePath: cookiePath, + // // }); + // // expect(xhrMock.open.mock.calls.length).toBe(1); + // // expect(xhrMock.open.mock.calls[0][1]).not.toContain(newBaseUrl); + // // expect(xhrMock.open.mock.calls[0][1]).toContain(oldBaseUrl); + // // }); + //}); + + describe('new identity provided and old identity does not exist', () => { + const newIdentity = makeIdentity(); + const useCookie = true; - // test('should use old base url', () => { - // uid2.init({ - // cookiePath: cookiePath, - // }); - // //expect(xhrMock.open.mock.calls.length).toBe(1); - // expect(xhrMock.open.mock.calls[0][1]).not.toContain('http://test'); - // expect(xhrMock.open.mock.calls[0][1]).toContain(baseUrl); - // }); - // }); + beforeEach(() => { + uid2.init({ + callback: callback, + baseUrl: baseUrl, + cookiePath: cookiePath, + useCookie: useCookie, + }); + uid2.init({ + identity: newIdentity, + }); + }); - // describe('new identity provided and old identity does not exist', () => { - // const newIdentity = makeIdentity(); + test('should set value to new identity', () => { + expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); + }); + test('should set refresh timer and call it once', () => { + expect(setTimeout).toHaveBeenCalledTimes(1); + expect(clearTimeout).not.toHaveBeenCalled(); + }); + test('new identity should be in available state', () => { + (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); + }); + }); - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // }); - // uid2.init({ - // identity: newIdentity, - // }); - // }); - // test('should create new identity', () => { - // test('should set value', () => { - // expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); - // }); - // test('should set refresh timer', () => { - // expect(setTimeout).toHaveBeenCalledTimes(1); - // expect(clearTimeout).not.toHaveBeenCalled(); - // }); - // test('should be in available state', () => { - // (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); - // }); - // }); - // }); + describe('new identity provided but expired', () => { + const newIdentity = makeIdentity({ refresh_expires: Date.now() - 100000 }); + const useCookie = true; - // describe('new identity provided but expired', () => { - // const newIdentity = makeIdentity({ refresh_expires: Date.now() - 100000 }); + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + useCookie: useCookie, + }); + uid2.init({ + identity: newIdentity, + }); + }); + test('should set value to old identity', () => { + expect(getUid2(useCookie).advertising_token).toBe(identity.advertising_token); + }); + test('should set refresh timer once', () => { + expect(setTimeout).toHaveBeenCalledTimes(1); + expect(clearTimeout).not.toHaveBeenCalled(); + }); + test('old ideneity should be in available state', () => { + (expect(uid2) as any).toBeInAvailableState(identity.advertising_token); + }); + }); - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // }); - // uid2.init({ - // identity: newIdentity, - // }); - // }); - // test('should not update the identity', () => { - // test('should set value', () => { - // expect(getUid2(useCookie).advertising_token).toBe(identity.advertising_token); - // }); - // test('should set refresh timer', () => { - // expect(setTimeout).toHaveBeenCalledTimes(1); - // expect(clearTimeout).not.toHaveBeenCalled(); - // }); - // test('should be in available state', () => { - // (expect(uid2) as any).toBeInAvailableState(identity.advertising_token); - // }); - // }); - // }); + describe('new identity provided but expires before old identity', () => { + const oldIdentity = makeIdentity({ refresh_expires: Date.now() + 5000 }); + const newIdentity = makeIdentity({ refresh_expires: Date.now() + 100000 }); + const useCookie = true; - // describe('new identity provided but expires before old identity', () => { - // const oldIdentity = makeIdentity({ refresh_expires: Date.now() + 5000 }); - // const newIdentity = makeIdentity({ refresh_expires: Date.now() + 100000 }); + beforeEach(() => { + uid2.init({ + callback: callback, + identity: oldIdentity, + baseUrl: baseUrl, + cookiePath: cookiePath, + useCookie: useCookie, + }); + uid2.init({ + identity: newIdentity, + }); + }); - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // identity: oldIdentity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // }); - // uid2.init({ - // identity: newIdentity, - // }); - // }); - // test('should not update the identity', () => { - // test('should set value', () => { - // expect(getUid2(useCookie).advertising_token).toBe(oldIdentity.advertising_token); - // }); - // test('should set refresh timer', () => { - // expect(setTimeout).toHaveBeenCalledTimes(1); - // expect(clearTimeout).not.toHaveBeenCalled(); - // }); - // test('should be in available state', () => { - // (expect(uid2) as any).toBeInAvailableState(oldIdentity.advertising_token); - // }); - // }); - // }); + test('should set value', () => { + expect(getUid2(useCookie).advertising_token).toBe(oldIdentity.advertising_token); + }); + test('should set refresh timer', () => { + expect(setTimeout).toHaveBeenCalledTimes(1); + expect(clearTimeout).not.toHaveBeenCalled(); + }); + test('should be in available state', () => { + (expect(uid2) as any).toBeInAvailableState(oldIdentity.advertising_token); + }); + }); - // describe('new identity provided and expires after old identity', () => { - // const newIdentity = makeIdentity(); + describe('new identity provided and expires after old identity', () => { + const newIdentity = makeIdentity(); + const useCookie = true; - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // }); - // uid2.init({ - // identity: newIdentity, - // }); - // }); - // test('should update identity to the new one', () => { - // test('should set value', () => { - // expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); - // }); - // test('should set refresh timer', () => { - // expect(setTimeout).toHaveBeenCalledTimes(1); - // expect(clearTimeout).not.toHaveBeenCalled(); - // }); - // test('should be in available state', () => { - // (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); - // }); - // }); - // }); + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + useCookie: useCookie, + }); + uid2.init({ + identity: newIdentity, + }); + }); - // describe('new cookie domain and new cookie path', () => { - // const newCookiePath = '/'; - // const newCookieDomain = 'www.uidapi.com'; + test('should set value', () => { + expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); + }); + test('should set refresh timer', () => { + expect(setTimeout).toHaveBeenCalledTimes(1); + expect(clearTimeout).not.toHaveBeenCalled(); + }); + test('should be in available state', () => { + (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); + }); + }); - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // cookieDomain: cookieDomain, - // useCookie: true, - // }); - // uid2.init({ - // cookiePath: newCookiePath, - // cookieDomain: newCookieDomain, - // }); - // }); - // test('should update cookie manager and config cookie', () => { - // const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); - // //expect(cookie).toContain(`Domain=${newCookieDomain};`); - // //expect(cookie + ';').toContain(`Path=${newCookiePath};`); - // expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); - // expect(getConfigCookie() + ';').toHaveProperty('cookiePath', newCookiePath); - // }); - // }); + describe('new identity provided and use cookie is false', () => { + const newIdentity = makeIdentity(); + const useCookie = false; - // describe('new cookie domain only', () => { - // const newCookieDomain = 'www.uidapi.com'; - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // useCookie: true, - // }); - // uid2.init({ - // cookieDomain: newCookieDomain, - // }); - // }); - // test('should update cookie manager', () => { - // const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); - // //expect(cookie).toContain(`Domain=${newCookieDomain};`); - // //expect(cookie + ';').toContain(`Path=${cookiePath};`); - // expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); - // expect(getConfigCookie() + ';').toHaveProperty('cookiePath', cookiePath); - // }); - // }); + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + useCookie: useCookie, + }); + uid2.init({ + identity: newIdentity, + }); + }); - // describe('new cookie path only', () => { - // const newCookiePath = '/'; + test('should set value', () => { + expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); + }); + test('should set refresh timer', () => { + expect(setTimeout).toHaveBeenCalledTimes(1); + expect(clearTimeout).not.toHaveBeenCalled(); + }); + test('should be in available state', () => { + (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); + }); + }); - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookieDomain: cookieDomain, - // cookiePath: cookiePath, - // useCookie: true, - // }); - // uid2.init({ - // cookiePath: newCookiePath, - // }); - // }); + describe('new cookie domain and new cookie path', () => { + const newCookiePath = '/'; + const newCookieDomain = 'www.test.com'; - // test('should update cookie manager', () => { - // const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); - // expect(cookie).toContain(`Domain=${cookieDomain};`); - // expect(cookie + ';').toContain(`Path=${newCookiePath};`); - // const configCookie = getConfigCookie(); - // expect(configCookie).toHaveProperty('cookieDomain', cookieDomain); - // expect(configCookie).toHaveProperty('cookiePath', newCookiePath); - // }); - // }); + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + cookieDomain: cookieDomain, + useCookie: true, + }); + uid2.init({ + cookiePath: newCookiePath, + cookieDomain: newCookieDomain, + }); + }); + test('should update cookie manager and config cookie', () => { + const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); + expect(cookie).toContain(`Domain=${newCookieDomain};`); + expect(cookie + ';').toContain(`Path=${newCookiePath};`); + //expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); + //expect(getConfigCookie() + ';').toHaveProperty('cookiePath', newCookiePath); + }); + }); + + describe('new cookie domain only', () => { + const newCookieDomain = 'www.uidapi.com'; + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + useCookie: true, + }); + uid2.init({ + cookieDomain: newCookieDomain, + }); + }); + test('should update cookie manager', () => { + const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); + expect(cookie).toContain(`Domain=${newCookieDomain};`); + expect(cookie + ';').toContain(`Path=${cookiePath};`); + //expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); + //expect(getConfigCookie() + ';').toHaveProperty('cookiePath', cookiePath); + }); + }); + + describe('new cookie path only', () => { + const newCookiePath = '/'; + + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookieDomain: cookieDomain, + cookiePath: cookiePath, + useCookie: true, + }); + uid2.init({ + cookiePath: newCookiePath, + }); + }); + + test('should update cookie manager', () => { + const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); + expect(cookie).toContain(`Domain=${cookieDomain};`); + expect(cookie + ';').toContain(`Path=${newCookiePath};`); + //const configCookie = getConfigCookie(); + //expect(configCookie).toHaveProperty('cookieDomain', cookieDomain); + //expect(configCookie).toHaveProperty('cookiePath', newCookiePath); + }); + }); describe('new refreshretry period', () => { beforeEach(() => { @@ -550,6 +554,7 @@ describe('multiple init calls', () => { // expect(cookie).toBeNull(); // }); // }); + // }); // describe('adding a callback when no callbacks exist before', () => { // beforeEach(() => { diff --git a/src/sdkBase.ts b/src/sdkBase.ts index a932333..5fcfa16 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -215,7 +215,7 @@ export abstract class SdkBase { this._logger.log('BaseUrl updated for ApiClient'); } - if (opts.identity && opts.identity.identity_expires < Date.now()) { + if (opts.identity && opts.identity.identity_expires > Date.now()) { if ( !this._opts.identity || opts.identity.identity_expires > this._opts.identity.identity_expires @@ -230,7 +230,7 @@ export abstract class SdkBase { } } - if (opts.useCookie && this._opts.useCookie !== opts.useCookie) { + if (opts.useCookie !== undefined && this._opts.useCookie !== opts.useCookie) { shouldUpdateConfig = true; this._storageManager?.updateUseCookie(opts.useCookie); this._opts.useCookie = opts.useCookie; @@ -252,7 +252,7 @@ export abstract class SdkBase { updateConfig(this._opts, this._product); } if (shouldUpdateCookieOptions) { - this._storageManager?.updateCookieOptions(opts, this._product.cookieName); + this._storageManager?.updateCookieOptions(this._opts, this._product.cookieName); } } else { storeConfig(opts, this._product); diff --git a/src/storageManager.ts b/src/storageManager.ts index 196ee6e..4a6bc88 100644 --- a/src/storageManager.ts +++ b/src/storageManager.ts @@ -34,8 +34,12 @@ export class StorageManager { this.setValue(identity); } - public updateCookieOptions(opts: SdkOptions, cookieName: string) { + public async updateCookieOptions(opts: SdkOptions, cookieName: string) { this._cookieManager = new CookieManager({ ...opts }, cookieName); + if (opts.identity) { + await this._cookieManager.removeCookie(); + this._cookieManager.setCookie(opts.identity); + } } public updateUseCookie(useCookie: boolean) { From baa3abb3543d49f224c78ead9465f9938542641b Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Mon, 12 Aug 2024 23:15:12 -0600 Subject: [PATCH 09/23] changes to remove cookie and remove config cookie --- src/configManager.ts | 27 +++++++++++++++++++++------ src/cookieManager.ts | 10 +++++++--- src/integrationTests/options.test.ts | 16 +++++++++------- src/sdkBase.ts | 8 +++++--- src/storageManager.ts | 4 ++-- 5 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/configManager.ts b/src/configManager.ts index 5e0d38b..32c0024 100644 --- a/src/configManager.ts +++ b/src/configManager.ts @@ -36,16 +36,21 @@ export const loadConfig = ( } }; -export const updateConfig = (options: SdkOptions, productDetails: ProductDetails) => { +export const updateConfig = ( + options: SdkOptions, + productDetails: ProductDetails, + previousCookieDomain: string | undefined, + previousCookiePath: string | undefined +) => { if (options.useCookie) { - removeConfigCookie(productDetails); + removeConfigCookie(options, productDetails, previousCookieDomain, previousCookiePath); } else { removeConfigFromLocalStorage(productDetails); } storeConfig(options, productDetails); }; -const setConfigCookie = (options: SdkOptions, productDetails: ProductDetails) => { +export const setConfigCookie = (options: SdkOptions, productDetails: ProductDetails) => { const cookieDomain = options.cookieDomain; const path = options.cookiePath ?? '/'; const value = JSON.stringify(getConfigFromSdkOptions(options)); @@ -57,10 +62,20 @@ const setConfigCookie = (options: SdkOptions, productDetails: ProductDetails) => document.cookie = cookie; }; -const removeConfigCookie = (productDetails: ProductDetails) => { +export const removeConfigCookie = ( + options: SdkOptions, + productDetails: ProductDetails, + previousCookieDomain: string | undefined, + previousCookiePath: string | undefined +) => { document.cookie = - productDetails.cookieName + '_config' + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT;path=/'; - console.log(document.cookie); + productDetails.cookieName + + '_config' + + '=;path=' + + (previousCookiePath ?? '/') + + ';domain=' + + (previousCookieDomain ?? '') + + ';expires=Tue, 1 Jan 1980 23:59:59 GMT'; }; const getConfigCookie = (productDetails: ProductDetails) => { diff --git a/src/cookieManager.ts b/src/cookieManager.ts index 46b2313..b2fba63 100644 --- a/src/cookieManager.ts +++ b/src/cookieManager.ts @@ -51,11 +51,15 @@ export class CookieManager { cookie += ';domain=' + this._opts.cookieDomain; } document.cookie = cookie; - let testcookie = document.cookie; - console.log(testcookie); } public async removeCookie() { - document.cookie = this._cookieName + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT;path=/'; + document.cookie = + this._cookieName + + '=;path=' + + (this._opts.cookiePath ?? '/') + + ';domain=' + + (this._opts.cookieDomain ?? '') + + ';expires=Tue, 1 Jan 1980 23:59:59 GMT'; } private getCookie() { const docCookie = document.cookie; diff --git a/src/integrationTests/options.test.ts b/src/integrationTests/options.test.ts index f3381c9..f8fb283 100644 --- a/src/integrationTests/options.test.ts +++ b/src/integrationTests/options.test.ts @@ -457,8 +457,8 @@ describe('multiple init calls', () => { const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); expect(cookie).toContain(`Domain=${newCookieDomain};`); expect(cookie + ';').toContain(`Path=${newCookiePath};`); - //expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); - //expect(getConfigCookie() + ';').toHaveProperty('cookiePath', newCookiePath); + expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); + expect(getConfigCookie()).toHaveProperty('cookiePath', newCookiePath); }); }); @@ -470,6 +470,7 @@ describe('multiple init calls', () => { identity: identity, baseUrl: baseUrl, cookiePath: cookiePath, + cookieDomain: cookieDomain, useCookie: true, }); uid2.init({ @@ -480,8 +481,9 @@ describe('multiple init calls', () => { const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); expect(cookie).toContain(`Domain=${newCookieDomain};`); expect(cookie + ';').toContain(`Path=${cookiePath};`); - //expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); - //expect(getConfigCookie() + ';').toHaveProperty('cookiePath', cookiePath); + const configCookie = getConfigCookie(); + expect(configCookie).toHaveProperty('cookieDomain', newCookieDomain); + expect(configCookie).toHaveProperty('cookiePath', cookiePath); }); }); @@ -506,9 +508,9 @@ describe('multiple init calls', () => { const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); expect(cookie).toContain(`Domain=${cookieDomain};`); expect(cookie + ';').toContain(`Path=${newCookiePath};`); - //const configCookie = getConfigCookie(); - //expect(configCookie).toHaveProperty('cookieDomain', cookieDomain); - //expect(configCookie).toHaveProperty('cookiePath', newCookiePath); + const configCookie = getConfigCookie(); + expect(configCookie).toHaveProperty('cookieDomain', cookieDomain); + expect(configCookie).toHaveProperty('cookiePath', newCookiePath); }); }); diff --git a/src/sdkBase.ts b/src/sdkBase.ts index 5fcfa16..882e6e7 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -192,6 +192,7 @@ export abstract class SdkBase { let shouldUpdateConfig = false; let shouldUpdateCookieOptions = false; + let previousCookieDomain = this._opts.cookieDomain; if (opts.cookieDomain && opts.cookieDomain != this._opts.cookieDomain) { shouldUpdateConfig = true; shouldUpdateCookieOptions = true; @@ -202,6 +203,7 @@ export abstract class SdkBase { this._logger.log('cookie domain updated'); } + let previousCookiePath = this._opts.cookiePath; if (opts.cookiePath && opts.cookiePath !== this._opts.cookiePath) { shouldUpdateConfig = true; shouldUpdateCookieOptions = true; @@ -248,12 +250,12 @@ export abstract class SdkBase { this._logger.log('init callback added to list'); } - if (shouldUpdateConfig) { - updateConfig(this._opts, this._product); - } if (shouldUpdateCookieOptions) { this._storageManager?.updateCookieOptions(this._opts, this._product.cookieName); } + if (shouldUpdateConfig) { + updateConfig(this._opts, this._product, previousCookieDomain, previousCookiePath); + } } else { storeConfig(opts, this._product); this._opts = opts; diff --git a/src/storageManager.ts b/src/storageManager.ts index 4a6bc88..69d63fe 100644 --- a/src/storageManager.ts +++ b/src/storageManager.ts @@ -35,9 +35,9 @@ export class StorageManager { } public async updateCookieOptions(opts: SdkOptions, cookieName: string) { - this._cookieManager = new CookieManager({ ...opts }, cookieName); if (opts.identity) { - await this._cookieManager.removeCookie(); + this._cookieManager.removeCookie(); + this._cookieManager = new CookieManager({ ...opts }, cookieName); this._cookieManager.setCookie(opts.identity); } } From 12ac959c64fa2d40812032d9fa419b602f63e0d1 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Tue, 13 Aug 2024 14:21:42 -0600 Subject: [PATCH 10/23] changes when usecookie changes its value --- src/configManager.ts | 25 ++-- src/integrationTests/euidSdk.test.ts | 1 + src/integrationTests/options.test.ts | 182 ++++++++++++++------------- src/sdkBase.ts | 16 +-- src/storageManager.ts | 23 +++- 5 files changed, 133 insertions(+), 114 deletions(-) diff --git a/src/configManager.ts b/src/configManager.ts index 32c0024..65a6a8e 100644 --- a/src/configManager.ts +++ b/src/configManager.ts @@ -39,15 +39,18 @@ export const loadConfig = ( export const updateConfig = ( options: SdkOptions, productDetails: ProductDetails, - previousCookieDomain: string | undefined, - previousCookiePath: string | undefined + previousOptions: SdkOptions ) => { - if (options.useCookie) { - removeConfigCookie(options, productDetails, previousCookieDomain, previousCookiePath); + removeConfig(previousOptions, productDetails); + storeConfig(options, productDetails); +}; + +export const removeConfig = (previousOptions: SdkOptions, productDetails: ProductDetails) => { + if (previousOptions.useCookie) { + removeConfigCookie(productDetails, previousOptions); } else { removeConfigFromLocalStorage(productDetails); } - storeConfig(options, productDetails); }; export const setConfigCookie = (options: SdkOptions, productDetails: ProductDetails) => { @@ -59,22 +62,18 @@ export const setConfigCookie = (options: SdkOptions, productDetails: ProductDeta if (typeof cookieDomain !== 'undefined') { cookie += ';domain=' + cookieDomain; } + const testbefore = document.cookie; document.cookie = cookie; }; -export const removeConfigCookie = ( - options: SdkOptions, - productDetails: ProductDetails, - previousCookieDomain: string | undefined, - previousCookiePath: string | undefined -) => { +export const removeConfigCookie = (productDetails: ProductDetails, previousOptions: SdkOptions) => { document.cookie = productDetails.cookieName + '_config' + '=;path=' + - (previousCookiePath ?? '/') + + (previousOptions.cookiePath ?? '/') + ';domain=' + - (previousCookieDomain ?? '') + + (previousOptions.cookieDomain ?? '') + ';expires=Tue, 1 Jan 1980 23:59:59 GMT'; }; diff --git a/src/integrationTests/euidSdk.test.ts b/src/integrationTests/euidSdk.test.ts index 73711d6..3d8b15a 100644 --- a/src/integrationTests/euidSdk.test.ts +++ b/src/integrationTests/euidSdk.test.ts @@ -181,6 +181,7 @@ describe('Store config EUID', () => { }); }); describe('when useCookie is true', () => { + const previousOptions = options; test('can successfully clear the config cookie', () => { (sdkWindow.__euid as EUID).init({ callback: callback, diff --git a/src/integrationTests/options.test.ts b/src/integrationTests/options.test.ts index e40b2b3..462d655 100644 --- a/src/integrationTests/options.test.ts +++ b/src/integrationTests/options.test.ts @@ -54,6 +54,15 @@ const getConfigCookie = () => { return null; }; +const getConfigStorage = () => { + const data = localStorage.getItem('UID2-sdk-identity_config'); + if (data) { + const result = JSON.parse(data); + return result; + } + return null; +}; + describe('cookieDomain option', () => { describe('when using default value', () => { beforeEach(() => { @@ -428,46 +437,46 @@ describe('multiple init calls', () => { }); }); - describe('new cookie domain and new cookie path', () => { - const newCookiePath = '/'; - const newCookieDomain = 'www.test.com'; + // describe('new cookie domain and new cookie path', () => { + // const newCookiePath = '/'; + // const newCookieDomain = 'www.test.com'; - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - cookieDomain: cookieDomain, - useCookie: true, - }); - uid2.init({ - cookiePath: newCookiePath, - cookieDomain: newCookieDomain, - }); - }); - test('should update cookie manager and config cookie', () => { - const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); - expect(cookie).toContain(`Domain=${newCookieDomain};`); - expect(cookie + ';').toContain(`Path=${newCookiePath};`); - expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); - expect(getConfigCookie()).toHaveProperty('cookiePath', newCookiePath); - }); - }); + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // cookieDomain: cookieDomain, + // useCookie: true, + // }); + // uid2.init({ + // cookiePath: newCookiePath, + // cookieDomain: newCookieDomain, + // }); + // }); + // test('should update cookie manager and config cookie', () => { + // const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); + // expect(cookie).toContain(`Domain=${newCookieDomain};`); + // expect(cookie + ';').toContain(`Path=${newCookiePath};`); + // expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); + // expect(getConfigCookie()).toHaveProperty('cookiePath', newCookiePath); + // }); + // }); describe('new cookie domain only', () => { - const newCookieDomain = 'www.uidapi.com'; + const newCookieDomain = 'test.uidapi.com'; beforeEach(() => { uid2.init({ callback: callback, identity: identity, baseUrl: baseUrl, cookiePath: cookiePath, - cookieDomain: cookieDomain, + cookieDomain: newCookieDomain, useCookie: true, }); uid2.init({ - cookieDomain: newCookieDomain, + cookieDomain: cookieDomain, }); }); test('should update cookie manager', () => { @@ -526,30 +535,55 @@ describe('multiple init calls', () => { }); }); - // describe('usecookie changing from true to false', () => { - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // refreshRetryPeriod: 12345, - // useCookie: true, - // }); - // uid2.init({ - // useCookie: false, - // }); - // }); - // test('should change config from cookie to local storage', () => { - // test('should store config in local storage', () => { - // const storageConfig = getConfigStorage(); - // expect(storageConfig).toBeInstanceOf(Object); - // expect(storageConfig).toHaveProperty('cookiePath'); - // const cookie = getConfigCookie(); - // expect(cookie).toBeNull(); - // }); - // }); - // }); + describe('usecookie changing from true to false', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + refreshRetryPeriod: 12345, + useCookie: true, + }); + uid2.init({ + useCookie: false, + }); + }); + test('should change config from cookie to local storage', () => { + const storageConfig = getConfigStorage(); + expect(storageConfig).toBeInstanceOf(Object); + expect(storageConfig).toHaveProperty('cookiePath'); + const configCookie = getConfigCookie(); + expect(configCookie).toBeNull(); + expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + expect(getUid2Cookie()).toBeNull(); + }); + }); + + describe('usecookie changing from false to true', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + refreshRetryPeriod: 12345, + useCookie: false, + }); + uid2.init({ + useCookie: true, + cookiePath: cookiePath, + }); + }); + test('should change config from cookie to local storage', () => { + const storageConfig = getConfigStorage(); + expect(storageConfig).toBeNull(); + const configCookie = getConfigCookie(); + expect(configCookie).toBeInstanceOf(Object); + expect(configCookie).toHaveProperty('cookiePath'); + expect(getUid2Cookie().advertising_token).toBe(identity.advertising_token); + expect(getUid2LocalStorage()).toBeNull(); + }); + }); // describe('adding a callback when no callbacks exist before', () => { // beforeEach(() => { @@ -601,9 +635,14 @@ describe('multiple init calls', () => { // }); // }); // }); +}); + +describe('Store config UID2', () => { + const identity = makeIdentity(); const options: SdkOptions = { baseUrl: 'http://test-host', cookieDomain: mockDomain, + cookiePath: '/', refreshRetryPeriod: 1000, useCookie: false, }; @@ -613,6 +652,7 @@ describe('multiple init calls', () => { localStorageKey: 'UID2-sdk-identity', name: 'UID2', }; + const previousOptions: SdkOptions = options; beforeEach(() => { localStorage.removeItem('UID2-sdk-identity_config'); @@ -646,45 +686,9 @@ describe('multiple init calls', () => { let storageConfig = loadConfig(options, productDetails); expect(storageConfig).toBeInstanceOf(Object); expect(storageConfig).toHaveProperty('cookieDomain'); - removeConfig(options, productDetails); + removeConfig(previousOptions, productDetails); storageConfig = loadConfig(options, productDetails); expect(storageConfig).toBeNull(); }); }); }); - -// describe('Store config UID2', () => { -// const identity = makeIdentity(); -// const options: SdkOptions = { -// baseUrl: 'http://test-host', -// cookieDomain: mockDomain, -// refreshRetryPeriod: 1000, -// useCookie: false, -// }; - -// beforeEach(() => { -// localStorage.removeItem('UID2-sdk-identity_config'); -// document.cookie = UID2.COOKIE_NAME + '_config' + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT'; -// }); - -// describe('when useCookie is true', () => { -// test('should store config in cookie', () => { -// uid2.init({ callback: callback, identity: identity, ...options, useCookie: true }); -// const cookie = getConfigCookie(); -// expect(cookie).toBeInstanceOf(Object); -// expect(cookie).toHaveProperty('cookieDomain'); -// const storageConfig = getConfigStorage(); -// expect(storageConfig).toBeNull(); -// }); -// }); -// describe('when useCookie is false', () => { -// test('should store config in local storage', () => { -// uid2.init({ callback: callback, identity: identity, ...options }); -// const storageConfig = getConfigStorage(); -// expect(storageConfig).toBeInstanceOf(Object); -// expect(storageConfig).toHaveProperty('cookieDomain'); -// const cookie = getConfigCookie(); -// expect(cookie).toBeNull(); -// }); -// }); -// }); diff --git a/src/sdkBase.ts b/src/sdkBase.ts index 882e6e7..87a9693 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -189,13 +189,13 @@ export abstract class SdkBase { if (this.isInitialized()) { this.setInitComplete(false); + const previousOpts = { ...this._opts }; let shouldUpdateConfig = false; - let shouldUpdateCookieOptions = false; + let shouldUpdateIdentityValue = false; - let previousCookieDomain = this._opts.cookieDomain; if (opts.cookieDomain && opts.cookieDomain != this._opts.cookieDomain) { shouldUpdateConfig = true; - shouldUpdateCookieOptions = true; + shouldUpdateIdentityValue = true; // if (this._opts.useCookie === true || opts.useCookie === true) { // this._storageManager?.loadIdentity(); // } @@ -203,10 +203,9 @@ export abstract class SdkBase { this._logger.log('cookie domain updated'); } - let previousCookiePath = this._opts.cookiePath; if (opts.cookiePath && opts.cookiePath !== this._opts.cookiePath) { shouldUpdateConfig = true; - shouldUpdateCookieOptions = true; + shouldUpdateIdentityValue = true; this._opts.cookiePath = opts.cookiePath; this._logger.log('cookie path updated'); } @@ -234,6 +233,7 @@ export abstract class SdkBase { if (opts.useCookie !== undefined && this._opts.useCookie !== opts.useCookie) { shouldUpdateConfig = true; + shouldUpdateIdentityValue = true; this._storageManager?.updateUseCookie(opts.useCookie); this._opts.useCookie = opts.useCookie; this._logger.log('new use cookie variable, updated store config and storage manager '); @@ -250,11 +250,11 @@ export abstract class SdkBase { this._logger.log('init callback added to list'); } - if (shouldUpdateCookieOptions) { - this._storageManager?.updateCookieOptions(this._opts, this._product.cookieName); + if (shouldUpdateIdentityValue) { + this._storageManager?.updateValue(this._opts, this._product.cookieName, previousOpts); } if (shouldUpdateConfig) { - updateConfig(this._opts, this._product, previousCookieDomain, previousCookiePath); + updateConfig(this._opts, this._product, previousOpts); } } else { storeConfig(opts, this._product); diff --git a/src/storageManager.ts b/src/storageManager.ts index 69d63fe..bf571e9 100644 --- a/src/storageManager.ts +++ b/src/storageManager.ts @@ -34,17 +34,32 @@ export class StorageManager { this.setValue(identity); } - public async updateCookieOptions(opts: SdkOptions, cookieName: string) { + public updateValue(opts: SdkOptions, cookieName: string, previousOpts: SdkOptions) { if (opts.identity) { - this._cookieManager.removeCookie(); + if (previousOpts.useCookie === true) { + this._cookieManager.removeCookie(); + //this._cookieManager = new CookieManager({ ...opts }, cookieName); + // if (opts.useCookie) { + // this._cookieManager.setCookie(opts.identity); + // } else { + // this._localStorageManager.setValue(opts.identity); + // } + } else if (!previousOpts || previousOpts.useCookie === false) { + this._localStorageManager.removeValue(); + //this._cookieManager = new CookieManager({ ...opts }, cookieName); + // if (opts.useCookie) { + // this._cookieManager.setCookie(opts.identity); + // } else { + // this._localStorageManager.setValue(opts.identity); + // } + } this._cookieManager = new CookieManager({ ...opts }, cookieName); - this._cookieManager.setCookie(opts.identity); + this.setValue(opts.identity); } } public updateUseCookie(useCookie: boolean) { this._opts.useCookie = useCookie; - this.loadIdentity(); } public setOptout() { From 29b3969b31bba52e33b42681375b90928f37fa93 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Tue, 13 Aug 2024 15:25:53 -0600 Subject: [PATCH 11/23] added testing for updated base url --- src/integrationTests/options.test.ts | 205 ++++++++++++++------------- src/sdkBase.ts | 1 + 2 files changed, 104 insertions(+), 102 deletions(-) diff --git a/src/integrationTests/options.test.ts b/src/integrationTests/options.test.ts index 462d655..70b9dee 100644 --- a/src/integrationTests/options.test.ts +++ b/src/integrationTests/options.test.ts @@ -9,6 +9,7 @@ let callback: any; let uid2: UID2; let xhrMock: any; let cookieMock: any; +let cookieMock2: any; mocks.setupFakeTime(); @@ -24,8 +25,8 @@ beforeEach(() => { removeUid2Cookie(); removeUid2LocalStorage(); localStorage.removeItem('UID2-sdk-identity_config'); - document.cookie = UID2.COOKIE_NAME + '_config' + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT'; - document.cookie = UID2.COOKIE_NAME + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT'; + //document.cookie = UID2.COOKIE_NAME + '_config' + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT'; + //document.cookie = UID2.COOKIE_NAME + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT'; }); afterEach(() => { @@ -256,42 +257,38 @@ describe('multiple init calls', () => { // }); // }); - // describe('new base URL is given', () => { - // const identity = makeIdentity({ - // refresh_from: Date.now() - 100000, - // }); + describe('new base URL is given', () => { + const identity = makeIdentity({ + refresh_from: Date.now() - 100000, + }); - // const oldBaseUrl = baseUrl; - // const newBaseUrl = 'http://example'; + const oldBaseUrl = baseUrl; + const newBaseUrl = 'http://example'; - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: oldBaseUrl, - // }); - // }); - // test('should use new base url', () => { - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: newBaseUrl, - // }); - // console.log(xhrMock.open.mock.calls); - // expect(xhrMock.open.mock.calls.length).toBe(1); - // expect(xhrMock.open.mock.calls[0][1]).not.toContain(oldBaseUrl); - //expect(xhrMock.open.mock.calls[0][1]).toContain(newBaseUrl); - //}); - - // // test('should use old base url', () => { - // // uid2.init({ - // // cookiePath: cookiePath, - // // }); - // // expect(xhrMock.open.mock.calls.length).toBe(1); - // // expect(xhrMock.open.mock.calls[0][1]).not.toContain(newBaseUrl); - // // expect(xhrMock.open.mock.calls[0][1]).toContain(oldBaseUrl); - // // }); - //}); + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: oldBaseUrl, + useCookie: true, + }); + }); + test('should use new base url', () => { + uid2.init({ + baseUrl: newBaseUrl, + }); + const configCookie = getConfigCookie(); + expect(configCookie).toHaveProperty('baseUrl', newBaseUrl); + }); + + test('should use old base url', () => { + uid2.init({ + cookiePath: cookiePath, + }); + const configCookie = getConfigCookie(); + expect(configCookie).toHaveProperty('baseUrl', oldBaseUrl); + }); + }); describe('new identity provided and old identity does not exist', () => { const newIdentity = makeIdentity(); @@ -464,30 +461,35 @@ describe('multiple init calls', () => { // }); // }); - describe('new cookie domain only', () => { - const newCookieDomain = 'test.uidapi.com'; - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - cookieDomain: newCookieDomain, - useCookie: true, - }); - uid2.init({ - cookieDomain: cookieDomain, - }); - }); - test('should update cookie manager', () => { - const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); - expect(cookie).toContain(`Domain=${newCookieDomain};`); - expect(cookie + ';').toContain(`Path=${cookiePath};`); - const configCookie = getConfigCookie(); - expect(configCookie).toHaveProperty('cookieDomain', newCookieDomain); - expect(configCookie).toHaveProperty('cookiePath', cookiePath); - }); - }); + // describe('new cookie domain only', () => { + // const newCookieDomain = 'www.test.com'; + // const newMockUrl = `http://${newCookieDomain}/test/index.html`; + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // cookieDomain: cookieDomain, + // useCookie: true, + // }); + // jest.spyOn(document, 'URL', 'get').mockImplementation(() => newMockUrl); + // cookieMock = new mocks.CookieMock(sdkWindow.document); + // jest.spyOn(document, 'URL', 'get').mockImplementation(() => mockUrl); + // cookieMock2 = new mocks.CookieMock(sdkWindow.document); + // uid2.init({ + // cookieDomain: newCookieDomain, + // }); + // }); + // test('should update cookie manager', () => { + // const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); + // expect(cookie).toContain(`Domain=${newCookieDomain};`); + // expect(cookie + ';').toContain(`Path=${cookiePath};`); + // const configCookie = getConfigCookie(); + // expect(configCookie).toHaveProperty('cookieDomain', newCookieDomain); + // expect(configCookie).toHaveProperty('cookiePath', cookiePath); + // }); + // }); describe('new cookie path only', () => { const newCookiePath = '/'; @@ -585,53 +587,52 @@ describe('multiple init calls', () => { }); }); - // describe('adding a callback when no callbacks exist before', () => { - // beforeEach(() => { - // uid2.init({ - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // refreshRetryPeriod: 12345, - // useCookie: true, - // }); - // uid2.init({ - // useCookie: false, - // callback: callback, - // }); + // describe('adding a callback when no callbacks exist before', () => { + // beforeEach(() => { + // uid2.init({ + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // refreshRetryPeriod: 12345, + // useCookie: true, // }); - // test('should change config from cookie to local storage', () => { - // test('should store config in local storage', () => { - // const storageConfig = getConfigStorage(); - // expect(storageConfig).toBeInstanceOf(Object); - // expect(storageConfig).toHaveProperty('cookiePath'); - // const cookie = getConfigCookie(); - // expect(cookie).toBeNull(); - // }); + // uid2.init({ + // useCookie: false, + // callback: callback, + // }); + // }); + // test('should change config from cookie to local storage', () => { + // test('should store config in local storage', () => { + // const storageConfig = getConfigStorage(); + // expect(storageConfig).toBeInstanceOf(Object); + // expect(storageConfig).toHaveProperty('cookiePath'); + // const cookie = getConfigCookie(); + // expect(cookie).toBeNull(); // }); // }); + // }); - // describe('adding a callback', () => { - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // refreshRetryPeriod: 12345, - // useCookie: false, - // }); - // uid2.init({ - // callback: jest.fn(), - // }); + // describe('adding a callback', () => { + // beforeEach(() => { + // uid2.init({ + // callback: callback, + // identity: identity, + // baseUrl: baseUrl, + // cookiePath: cookiePath, + // refreshRetryPeriod: 12345, + // useCookie: false, // }); - // test('should change config from local storage to cookie', () => { - // test('should store config in cookie', () => { - // const cookie = getConfigCookie(); - // expect(cookie).toBeInstanceOf(Object); - // expect(cookie).toHaveProperty('cookiePath'); - // const storageConfig = getConfigStorage(); - // expect(storageConfig).toBeNull(); - // }); + // uid2.init({ + // callback: jest.fn(), + // }); + // }); + // test('should change config from local storage to cookie', () => { + // test('should store config in cookie', () => { + // const cookie = getConfigCookie(); + // expect(cookie).toBeInstanceOf(Object); + // expect(cookie).toHaveProperty('cookiePath'); + // const storageConfig = getConfigStorage(); + // expect(storageConfig).toBeNull(); // }); // }); // }); diff --git a/src/sdkBase.ts b/src/sdkBase.ts index 87a9693..4afc5bd 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -211,6 +211,7 @@ export abstract class SdkBase { } if (opts.baseUrl && opts.baseUrl !== this._opts.baseUrl) { + shouldUpdateConfig = true; this._apiClient?.updateBaseUrl(opts.baseUrl); this._opts.baseUrl = opts.baseUrl; this._logger.log('BaseUrl updated for ApiClient'); From cfe3c49bb5a2438a4b83e3dbb05f07848a024e8b Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Tue, 13 Aug 2024 15:54:36 -0600 Subject: [PATCH 12/23] added init callback tests --- src/initCallbacks.ts | 16 +-- src/integrationTests/euidSdk.test.ts | 1 - src/integrationTests/options.test.ts | 149 ++++++++------------------- src/sdkBase.ts | 10 +- 4 files changed, 58 insertions(+), 118 deletions(-) diff --git a/src/initCallbacks.ts b/src/initCallbacks.ts index 81a7bd3..09d90d0 100644 --- a/src/initCallbacks.ts +++ b/src/initCallbacks.ts @@ -22,14 +22,18 @@ export enum IdentityStatus { } export class InitCallbackManager { - private _callbacks: InitCallbackFunction[]; + private _initCallbacks: InitCallbackFunction[]; constructor(opts: InitCallbackOptions) { - this._callbacks = opts.callback ? [opts.callback] : []; + this._initCallbacks = opts.callback ? [opts.callback] : []; } - public addCallback(callback: InitCallbackFunction) { - this._callbacks.push(callback); + public addInitCallback(callback: InitCallbackFunction) { + this._initCallbacks.push(callback); + } + + public getInitCallbacks() { + return this._initCallbacks; } public notifyInitCallbacks( @@ -38,7 +42,7 @@ export class InitCallbackManager { advertisingToken: string | undefined, logger: Logger ) { - this._callbacks.forEach((callback) => { + this._initCallbacks.forEach((initCallback) => { const payload = { advertisingToken: advertisingToken, advertising_token: advertisingToken, @@ -46,7 +50,7 @@ export class InitCallbackManager { statusText: statusText, }; try { - callback(payload); + initCallback(payload); } catch (exception) { logger.warn('SDK init callback threw an exception', exception); } diff --git a/src/integrationTests/euidSdk.test.ts b/src/integrationTests/euidSdk.test.ts index 3d8b15a..73711d6 100644 --- a/src/integrationTests/euidSdk.test.ts +++ b/src/integrationTests/euidSdk.test.ts @@ -181,7 +181,6 @@ describe('Store config EUID', () => { }); }); describe('when useCookie is true', () => { - const previousOptions = options; test('can successfully clear the config cookie', () => { (sdkWindow.__euid as EUID).init({ callback: callback, diff --git a/src/integrationTests/options.test.ts b/src/integrationTests/options.test.ts index 70b9dee..4aad5e3 100644 --- a/src/integrationTests/options.test.ts +++ b/src/integrationTests/options.test.ts @@ -9,7 +9,6 @@ let callback: any; let uid2: UID2; let xhrMock: any; let cookieMock: any; -let cookieMock2: any; mocks.setupFakeTime(); @@ -434,64 +433,7 @@ describe('multiple init calls', () => { }); }); - // describe('new cookie domain and new cookie path', () => { - // const newCookiePath = '/'; - // const newCookieDomain = 'www.test.com'; - - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // cookieDomain: cookieDomain, - // useCookie: true, - // }); - // uid2.init({ - // cookiePath: newCookiePath, - // cookieDomain: newCookieDomain, - // }); - // }); - // test('should update cookie manager and config cookie', () => { - // const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); - // expect(cookie).toContain(`Domain=${newCookieDomain};`); - // expect(cookie + ';').toContain(`Path=${newCookiePath};`); - // expect(getConfigCookie()).toHaveProperty('cookieDomain', newCookieDomain); - // expect(getConfigCookie()).toHaveProperty('cookiePath', newCookiePath); - // }); - // }); - - // describe('new cookie domain only', () => { - // const newCookieDomain = 'www.test.com'; - // const newMockUrl = `http://${newCookieDomain}/test/index.html`; - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // cookieDomain: cookieDomain, - // useCookie: true, - // }); - // jest.spyOn(document, 'URL', 'get').mockImplementation(() => newMockUrl); - // cookieMock = new mocks.CookieMock(sdkWindow.document); - // jest.spyOn(document, 'URL', 'get').mockImplementation(() => mockUrl); - // cookieMock2 = new mocks.CookieMock(sdkWindow.document); - // uid2.init({ - // cookieDomain: newCookieDomain, - // }); - // }); - // test('should update cookie manager', () => { - // const cookie = cookieMock.getSetCookieString(UID2.COOKIE_NAME); - // expect(cookie).toContain(`Domain=${newCookieDomain};`); - // expect(cookie + ';').toContain(`Path=${cookiePath};`); - // const configCookie = getConfigCookie(); - // expect(configCookie).toHaveProperty('cookieDomain', newCookieDomain); - // expect(configCookie).toHaveProperty('cookiePath', cookiePath); - // }); - // }); - - describe('new cookie path only', () => { + describe('new cookie path', () => { const newCookiePath = '/'; beforeEach(() => { @@ -587,55 +529,48 @@ describe('multiple init calls', () => { }); }); - // describe('adding a callback when no callbacks exist before', () => { - // beforeEach(() => { - // uid2.init({ - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // refreshRetryPeriod: 12345, - // useCookie: true, - // }); - // uid2.init({ - // useCookie: false, - // callback: callback, - // }); - // }); - // test('should change config from cookie to local storage', () => { - // test('should store config in local storage', () => { - // const storageConfig = getConfigStorage(); - // expect(storageConfig).toBeInstanceOf(Object); - // expect(storageConfig).toHaveProperty('cookiePath'); - // const cookie = getConfigCookie(); - // expect(cookie).toBeNull(); - // }); - // }); - // }); + describe('adding a callback when no callbacks exist before', () => { + beforeEach(() => { + uid2.init({ + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + refreshRetryPeriod: 12345, + useCookie: true, + }); + uid2.init({ + useCookie: false, + callback: callback, + }); + }); + test('should contain one init callback', () => { + const initCallbacks = uid2.getInitCallbacks(); + expect(initCallbacks).toEqual([callback]); + }); + }); - // describe('adding a callback', () => { - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // refreshRetryPeriod: 12345, - // useCookie: false, - // }); - // uid2.init({ - // callback: jest.fn(), - // }); - // }); - // test('should change config from local storage to cookie', () => { - // test('should store config in cookie', () => { - // const cookie = getConfigCookie(); - // expect(cookie).toBeInstanceOf(Object); - // expect(cookie).toHaveProperty('cookiePath'); - // const storageConfig = getConfigStorage(); - // expect(storageConfig).toBeNull(); - // }); - // }); - // }); + describe('adding multiple callbacks', () => { + beforeEach(() => { + uid2.init({ + callback: callback, + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + refreshRetryPeriod: 12345, + useCookie: false, + }); + uid2.init({ + callback: jest.fn(), + }); + uid2.init({ + callback: jest.fn(), + }); + }); + test('should contain three init callback functions', () => { + const initCallbacks = uid2.getInitCallbacks(); + expect(initCallbacks?.length).toEqual(3); + }); + }); }); describe('Store config UID2', () => { diff --git a/src/sdkBase.ts b/src/sdkBase.ts index 4afc5bd..44ccae4 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -136,6 +136,10 @@ export abstract class SdkBase { return this._tokenPromiseHandler.createMaybeDeferredPromise(token ?? null); } + public getInitCallbacks() { + return this._initCallbackManager?.getInitCallbacks(); + } + /** * Deprecated */ @@ -196,9 +200,6 @@ export abstract class SdkBase { if (opts.cookieDomain && opts.cookieDomain != this._opts.cookieDomain) { shouldUpdateConfig = true; shouldUpdateIdentityValue = true; - // if (this._opts.useCookie === true || opts.useCookie === true) { - // this._storageManager?.loadIdentity(); - // } this._opts.cookieDomain = opts.cookieDomain; this._logger.log('cookie domain updated'); } @@ -247,7 +248,8 @@ export abstract class SdkBase { } if (opts.callback) { - this._initCallbackManager?.addCallback(opts.callback); + this._initCallbackManager?.addInitCallback(opts.callback); + if (this._opts.identity) this.validateAndSetIdentity(this._opts.identity); this._logger.log('init callback added to list'); } From 3feb2034b009a8cd0ac4db6851420b1a391be828 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Tue, 13 Aug 2024 15:56:34 -0600 Subject: [PATCH 13/23] exports not needed for these functions --- src/configManager.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/configManager.ts b/src/configManager.ts index 65a6a8e..9c6384c 100644 --- a/src/configManager.ts +++ b/src/configManager.ts @@ -53,7 +53,7 @@ export const removeConfig = (previousOptions: SdkOptions, productDetails: Produc } }; -export const setConfigCookie = (options: SdkOptions, productDetails: ProductDetails) => { +const setConfigCookie = (options: SdkOptions, productDetails: ProductDetails) => { const cookieDomain = options.cookieDomain; const path = options.cookiePath ?? '/'; const value = JSON.stringify(getConfigFromSdkOptions(options)); @@ -62,11 +62,10 @@ export const setConfigCookie = (options: SdkOptions, productDetails: ProductDeta if (typeof cookieDomain !== 'undefined') { cookie += ';domain=' + cookieDomain; } - const testbefore = document.cookie; document.cookie = cookie; }; -export const removeConfigCookie = (productDetails: ProductDetails, previousOptions: SdkOptions) => { +const removeConfigCookie = (productDetails: ProductDetails, previousOptions: SdkOptions) => { document.cookie = productDetails.cookieName + '_config' + From 764969e3997b370c18ab7d9582b5f5d61045b603 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Tue, 13 Aug 2024 16:19:41 -0600 Subject: [PATCH 14/23] removed unnecessary comments --- src/configManager.ts | 2 +- src/cookieManager.ts | 2 +- src/integrationTests/basic.test.ts | 24 ++++++++++++------------ src/sdkBase.ts | 7 ++++++- src/storageManager.ts | 12 ------------ 5 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/configManager.ts b/src/configManager.ts index 9c6384c..3e96f61 100644 --- a/src/configManager.ts +++ b/src/configManager.ts @@ -81,7 +81,7 @@ const getConfigCookie = (productDetails: ProductDetails) => { if (docCookie) { const payload = docCookie .split('; ') - .filter((row) => row.startsWith(productDetails.cookieName + '_config' + '='))[1]; + .find((row) => row.startsWith(productDetails.cookieName + '_config' + '=')); if (payload) { return decodeURIComponent(payload.split('=')[1]); } diff --git a/src/cookieManager.ts b/src/cookieManager.ts index b2fba63..d670087 100644 --- a/src/cookieManager.ts +++ b/src/cookieManager.ts @@ -52,7 +52,7 @@ export class CookieManager { } document.cookie = cookie; } - public async removeCookie() { + public removeCookie() { document.cookie = this._cookieName + '=;path=' + diff --git a/src/integrationTests/basic.test.ts b/src/integrationTests/basic.test.ts index 26f157f..0169dbd 100644 --- a/src/integrationTests/basic.test.ts +++ b/src/integrationTests/basic.test.ts @@ -134,10 +134,10 @@ testCookieAndLocalStorage(() => { }); }); - // test('init() should fail if called multiple times', () => { - // uid2.init({ callback: () => {} }); - // expect(() => uid2.init({ callback: () => {} })).toThrow(); - // }); + test('init() should not fail if called multiple times', () => { + uid2.init({ callback: () => {}, identity: makeIdentityV2() }); + expect(() => uid2.init({ callback: () => {} })).not.toThrow(); + }); describe('when initialised without identity', () => { describe('when uid2 value is not available', () => { @@ -963,10 +963,10 @@ testCookieAndLocalStorage(() => { expect(xhrMock.send).toHaveBeenCalledTimes(1); expect(xhrMock.abort).toHaveBeenCalledTimes(1); }); - // test('should prevent subsequent calls to init()', () => { - // uid2.abort(); - // expect(() => uid2.init({ callback: () => {} })).toThrow(); - // }); + test('should prevent subsequent calls to init()', () => { + uid2.abort(); + expect(() => uid2.init({ callback: () => {} })).toThrow(); + }); }); describe('disconnect()', () => { @@ -999,10 +999,10 @@ testCookieAndLocalStorage(() => { expect(xhrMock.send).toHaveBeenCalledTimes(1); expect(xhrMock.abort).toHaveBeenCalledTimes(1); }); - // test('should prevent subsequent calls to init()', () => { - // uid2.disconnect(); - // expect(() => uid2.init({ callback: () => {} })).toThrow(); - // }); + test('should prevent subsequent calls to init()', () => { + uid2.disconnect(); + expect(() => uid2.init({ callback: () => {} })).toThrow(); + }); test('should switch to unavailable state', () => { uid2.init({ callback: callback, diff --git a/src/sdkBase.ts b/src/sdkBase.ts index 44ccae4..ffa3256 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -53,6 +53,7 @@ export abstract class SdkBase { private _opts: SdkOptions = {}; private _identity: Identity | OptoutIdentity | null | undefined; private _initComplete = false; + private _hasAborted = false; // Sets up nearly everything, but does not run SdkLoaded callbacks - derived classes must run them. protected constructor(existingCallbacks: CallbackHandler[] | undefined, product: ProductDetails) { @@ -175,7 +176,7 @@ export abstract class SdkBase { // Note: This doesn't invoke callbacks. It's a hard, silent reset. public abort(reason?: string) { - this._initComplete = true; + this._hasAborted = true; this._tokenPromiseHandler.rejectAllPromises( reason ?? new Error(`${this._product.name} SDK aborted.`) ); @@ -190,6 +191,10 @@ export abstract class SdkBase { if (!isSDKOptionsOrThrow(opts)) throw new TypeError(`Options provided to ${this._product.name} init couldn't be validated.`); + if (this._hasAborted) { + throw new TypeError('Calling init() once aborted or disconnected is not allowed'); + } + if (this.isInitialized()) { this.setInitComplete(false); diff --git a/src/storageManager.ts b/src/storageManager.ts index bf571e9..5998906 100644 --- a/src/storageManager.ts +++ b/src/storageManager.ts @@ -38,20 +38,8 @@ export class StorageManager { if (opts.identity) { if (previousOpts.useCookie === true) { this._cookieManager.removeCookie(); - //this._cookieManager = new CookieManager({ ...opts }, cookieName); - // if (opts.useCookie) { - // this._cookieManager.setCookie(opts.identity); - // } else { - // this._localStorageManager.setValue(opts.identity); - // } } else if (!previousOpts || previousOpts.useCookie === false) { this._localStorageManager.removeValue(); - //this._cookieManager = new CookieManager({ ...opts }, cookieName); - // if (opts.useCookie) { - // this._cookieManager.setCookie(opts.identity); - // } else { - // this._localStorageManager.setValue(opts.identity); - // } } this._cookieManager = new CookieManager({ ...opts }, cookieName); this.setValue(opts.identity); From 96348b779a4eb67a55815e5eabdd9151e6fbd5a2 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Tue, 13 Aug 2024 16:33:30 -0600 Subject: [PATCH 15/23] identity has to be provided first or will abort --- src/integrationTests/options.test.ts | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/src/integrationTests/options.test.ts b/src/integrationTests/options.test.ts index 4aad5e3..aad69c7 100644 --- a/src/integrationTests/options.test.ts +++ b/src/integrationTests/options.test.ts @@ -289,34 +289,6 @@ describe('multiple init calls', () => { }); }); - describe('new identity provided and old identity does not exist', () => { - const newIdentity = makeIdentity(); - const useCookie = true; - - beforeEach(() => { - uid2.init({ - callback: callback, - baseUrl: baseUrl, - cookiePath: cookiePath, - useCookie: useCookie, - }); - uid2.init({ - identity: newIdentity, - }); - }); - - test('should set value to new identity', () => { - expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); - }); - test('should set refresh timer and call it once', () => { - expect(setTimeout).toHaveBeenCalledTimes(1); - expect(clearTimeout).not.toHaveBeenCalled(); - }); - test('new identity should be in available state', () => { - (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); - }); - }); - describe('new identity provided but expired', () => { const newIdentity = makeIdentity({ refresh_expires: Date.now() - 100000 }); const useCookie = true; From 7d23a5fcc50557b2e881f8ea2967a99aa061b9f4 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Tue, 13 Aug 2024 16:42:41 -0600 Subject: [PATCH 16/23] added test for if nothing changes --- src/integrationTests/options.test.ts | 55 +++++++++++++--------------- src/sdkBase.ts | 1 + 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/integrationTests/options.test.ts b/src/integrationTests/options.test.ts index aad69c7..2ddc7d1 100644 --- a/src/integrationTests/options.test.ts +++ b/src/integrationTests/options.test.ts @@ -23,9 +23,6 @@ beforeEach(() => { cookieMock = new mocks.CookieMock(sdkWindow.document); removeUid2Cookie(); removeUid2LocalStorage(); - localStorage.removeItem('UID2-sdk-identity_config'); - //document.cookie = UID2.COOKIE_NAME + '_config' + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT'; - //document.cookie = UID2.COOKIE_NAME + '=;expires=Tue, 1 Jan 1980 23:59:59 GMT'; }); afterEach(() => { @@ -39,8 +36,6 @@ const removeUid2Cookie = mocks.removeUid2Cookie; const removeUid2LocalStorage = mocks.removeUid2LocalStorage; const getUid2 = mocks.getUid2; -let useCookie: boolean | undefined = undefined; - const getConfigCookie = () => { const docCookie = document.cookie; if (docCookie) { @@ -230,31 +225,31 @@ describe('multiple init calls', () => { const cookiePath = '/test/'; const cookieDomain = 'uidapi.com'; - // describe('when nothing has changed', () => { - // beforeEach(() => { - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // }); - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // }); - // uid2.init({ - // callback: callback, - // identity: identity, - // baseUrl: baseUrl, - // cookiePath: cookiePath, - // }); - // }); - // test('should return next two init calls without changing anything', () => { - // //expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); - // }); - // }); + describe('when nothing has changed', () => { + beforeEach(() => { + uid2.init({ + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + uid2.init({ + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + uid2.init({ + identity: identity, + baseUrl: baseUrl, + cookiePath: cookiePath, + }); + }); + test('should return next two init calls without changing anything', () => { + expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); + let storageConfig = getConfigStorage(); + expect(storageConfig).toBeInstanceOf(Object); + expect(storageConfig).toHaveProperty('cookiePath', cookiePath); + }); + }); describe('new base URL is given', () => { const identity = makeIdentity({ diff --git a/src/sdkBase.ts b/src/sdkBase.ts index ffa3256..fcb8384 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -255,6 +255,7 @@ export abstract class SdkBase { if (opts.callback) { this._initCallbackManager?.addInitCallback(opts.callback); if (this._opts.identity) this.validateAndSetIdentity(this._opts.identity); + this._opts.callback = opts.callback; this._logger.log('init callback added to list'); } From b9e3e651b8bf43abd3914cef9ca069f7cca6bc8b Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Tue, 13 Aug 2024 16:58:29 -0600 Subject: [PATCH 17/23] check for callbacks added --- src/integrationTests/options.test.ts | 17 ++++++++--------- src/sdkBase.ts | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/integrationTests/options.test.ts b/src/integrationTests/options.test.ts index 2ddc7d1..0288ff9 100644 --- a/src/integrationTests/options.test.ts +++ b/src/integrationTests/options.test.ts @@ -252,10 +252,6 @@ describe('multiple init calls', () => { }); describe('new base URL is given', () => { - const identity = makeIdentity({ - refresh_from: Date.now() - 100000, - }); - const oldBaseUrl = baseUrl; const newBaseUrl = 'http://example'; @@ -441,7 +437,6 @@ describe('multiple init calls', () => { }); }); test('should use the new refresh retry period', () => { - expect(setTimeout).toHaveBeenCalledTimes(2); expect(setTimeout).toBeCalledWith(expect.any(Function), 67890); }); }); @@ -516,7 +511,7 @@ describe('multiple init calls', () => { }); }); - describe('adding multiple callbacks', () => { + describe('adding multiple callbacks that are different', () => { beforeEach(() => { uid2.init({ callback: callback, @@ -527,13 +522,17 @@ describe('multiple init calls', () => { useCookie: false, }); uid2.init({ - callback: jest.fn(), + callback: jest.fn(() => { + return 'testing one'; + }), }); uid2.init({ - callback: jest.fn(), + callback: jest.fn(() => { + return 'testing two'; + }), }); }); - test('should contain three init callback functions', () => { + test('should contain only one init callback function', () => { const initCallbacks = uid2.getInitCallbacks(); expect(initCallbacks?.length).toEqual(3); }); diff --git a/src/sdkBase.ts b/src/sdkBase.ts index fcb8384..19b611e 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -252,7 +252,7 @@ export abstract class SdkBase { this._logger.log('new refresh period set and refresh timer set'); } - if (opts.callback) { + if (opts.callback && opts.callback !== this._opts.callback) { this._initCallbackManager?.addInitCallback(opts.callback); if (this._opts.identity) this.validateAndSetIdentity(this._opts.identity); this._opts.callback = opts.callback; From 42a1404abe45bcf52bf1e2e6c1df3c32fefbc15a Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Tue, 13 Aug 2024 17:19:29 -0600 Subject: [PATCH 18/23] swtiched order of params --- src/configManager.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/configManager.ts b/src/configManager.ts index 3e96f61..fe64bb8 100644 --- a/src/configManager.ts +++ b/src/configManager.ts @@ -47,7 +47,7 @@ export const updateConfig = ( export const removeConfig = (previousOptions: SdkOptions, productDetails: ProductDetails) => { if (previousOptions.useCookie) { - removeConfigCookie(productDetails, previousOptions); + removeConfigCookie(previousOptions, productDetails); } else { removeConfigFromLocalStorage(productDetails); } @@ -65,7 +65,7 @@ const setConfigCookie = (options: SdkOptions, productDetails: ProductDetails) => document.cookie = cookie; }; -const removeConfigCookie = (productDetails: ProductDetails, previousOptions: SdkOptions) => { +const removeConfigCookie = (previousOptions: SdkOptions, productDetails: ProductDetails) => { document.cookie = productDetails.cookieName + '_config' + From 90d0c744793ebdf6e24ee573280edbae99427d14 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Mon, 19 Aug 2024 11:47:55 -0600 Subject: [PATCH 19/23] compressed the initialize function if already initialized --- src/cookieManager.ts | 7 +-- src/integrationTests/options.test.ts | 61 +++++++++++++---------- src/sdkBase.ts | 74 +++++++++------------------- src/storageManager.ts | 6 +-- 4 files changed, 65 insertions(+), 83 deletions(-) diff --git a/src/cookieManager.ts b/src/cookieManager.ts index d670087..b0abea5 100644 --- a/src/cookieManager.ts +++ b/src/cookieManager.ts @@ -1,4 +1,5 @@ import { isValidIdentity, Identity, OptoutIdentity, isOptoutIdentity } from './Identity'; +import { SdkOptions } from './sdkOptions'; export type CookieOptions = { cookieDomain?: string; @@ -52,13 +53,13 @@ export class CookieManager { } document.cookie = cookie; } - public removeCookie() { + public removeCookie(previousOptions: SdkOptions) { document.cookie = this._cookieName + '=;path=' + - (this._opts.cookiePath ?? '/') + + (previousOptions.cookiePath ?? '/') + ';domain=' + - (this._opts.cookieDomain ?? '') + + (previousOptions.cookieDomain ?? '') + ';expires=Tue, 1 Jan 1980 23:59:59 GMT'; } private getCookie() { diff --git a/src/integrationTests/options.test.ts b/src/integrationTests/options.test.ts index 0288ff9..9a9c466 100644 --- a/src/integrationTests/options.test.ts +++ b/src/integrationTests/options.test.ts @@ -262,26 +262,40 @@ describe('multiple init calls', () => { baseUrl: oldBaseUrl, useCookie: true, }); - }); - test('should use new base url', () => { uid2.init({ baseUrl: newBaseUrl, }); + }); + test('should use new base url', () => { const configCookie = getConfigCookie(); expect(configCookie).toHaveProperty('baseUrl', newBaseUrl); }); + }); - test('should use old base url', () => { + describe('no base URL is given, should use new base URL', () => { + beforeEach(() => { uid2.init({ - cookiePath: cookiePath, + callback: callback, + identity: identity, + baseUrl: baseUrl, + useCookie: true, }); + uid2.init({ + cookiePath: '/', + }); + }); + + test('should use old base url', () => { const configCookie = getConfigCookie(); - expect(configCookie).toHaveProperty('baseUrl', oldBaseUrl); + expect(configCookie).toHaveProperty('baseUrl', baseUrl); }); }); describe('new identity provided but expired', () => { - const newIdentity = makeIdentity({ refresh_expires: Date.now() - 100000 }); + const newIdentity = makeIdentity({ + advertising_token: 'new_test_advertising_token', + identity_expires: Date.now() - 100000, + }); const useCookie = true; beforeEach(() => { @@ -299,18 +313,17 @@ describe('multiple init calls', () => { test('should set value to old identity', () => { expect(getUid2(useCookie).advertising_token).toBe(identity.advertising_token); }); - test('should set refresh timer once', () => { - expect(setTimeout).toHaveBeenCalledTimes(1); - expect(clearTimeout).not.toHaveBeenCalled(); - }); - test('old ideneity should be in available state', () => { + test('old identity should be in available state', () => { (expect(uid2) as any).toBeInAvailableState(identity.advertising_token); }); }); describe('new identity provided but expires before old identity', () => { - const oldIdentity = makeIdentity({ refresh_expires: Date.now() + 5000 }); - const newIdentity = makeIdentity({ refresh_expires: Date.now() + 100000 }); + const oldIdentity = makeIdentity({ identity_expires: Date.now() + 10000 }); + const newIdentity = makeIdentity({ + advertising_token: 'new_test_advertising_token', + identity_expires: Date.now() + 5000, + }); const useCookie = true; beforeEach(() => { @@ -329,17 +342,16 @@ describe('multiple init calls', () => { test('should set value', () => { expect(getUid2(useCookie).advertising_token).toBe(oldIdentity.advertising_token); }); - test('should set refresh timer', () => { - expect(setTimeout).toHaveBeenCalledTimes(1); - expect(clearTimeout).not.toHaveBeenCalled(); - }); test('should be in available state', () => { (expect(uid2) as any).toBeInAvailableState(oldIdentity.advertising_token); }); }); describe('new identity provided and expires after old identity', () => { - const newIdentity = makeIdentity(); + const newIdentity = makeIdentity({ + advertising_token: 'new_test_advertising_token', + identity_expires: Date.now() + 300000, + }); const useCookie = true; beforeEach(() => { @@ -358,17 +370,16 @@ describe('multiple init calls', () => { test('should set value', () => { expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); }); - test('should set refresh timer', () => { - expect(setTimeout).toHaveBeenCalledTimes(1); - expect(clearTimeout).not.toHaveBeenCalled(); - }); test('should be in available state', () => { (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); }); }); describe('new identity provided and use cookie is false', () => { - const newIdentity = makeIdentity(); + const newIdentity = makeIdentity({ + advertising_token: 'new_test_advertising_token', + identity_expires: Date.now() + 300000, + }); const useCookie = false; beforeEach(() => { @@ -387,10 +398,6 @@ describe('multiple init calls', () => { test('should set value', () => { expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); }); - test('should set refresh timer', () => { - expect(setTimeout).toHaveBeenCalledTimes(1); - expect(clearTimeout).not.toHaveBeenCalled(); - }); test('should be in available state', () => { (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); }); diff --git a/src/sdkBase.ts b/src/sdkBase.ts index 4591fa8..0441c42 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -78,7 +78,7 @@ export abstract class SdkBase { return this._initComplete; } - public setInitComplete(isInitComplete: boolean) { + private setInitComplete(isInitComplete: boolean) { this._initComplete = isInitComplete; } @@ -196,75 +196,45 @@ export abstract class SdkBase { } if (this.isInitialized()) { - this.setInitComplete(false); - const previousOpts = { ...this._opts }; - let shouldUpdateConfig = false; - let shouldUpdateIdentityValue = false; - - if (opts.cookieDomain && opts.cookieDomain != this._opts.cookieDomain) { - shouldUpdateConfig = true; - shouldUpdateIdentityValue = true; - this._opts.cookieDomain = opts.cookieDomain; - this._logger.log('cookie domain updated'); - } + Object.assign(this._opts, opts); - if (opts.cookiePath && opts.cookiePath !== this._opts.cookiePath) { - shouldUpdateConfig = true; - shouldUpdateIdentityValue = true; - this._opts.cookiePath = opts.cookiePath; - this._logger.log('cookie path updated'); - } - - if (opts.baseUrl && opts.baseUrl !== this._opts.baseUrl) { - shouldUpdateConfig = true; + if (opts.baseUrl && opts.baseUrl !== previousOpts.baseUrl) { this._apiClient?.updateBaseUrl(opts.baseUrl); - this._opts.baseUrl = opts.baseUrl; this._logger.log('BaseUrl updated for ApiClient'); } - if (opts.identity && opts.identity.identity_expires > Date.now()) { + if (opts.identity) { if ( - !this._opts.identity || - opts.identity.identity_expires > this._opts.identity.identity_expires + !previousOpts.identity || + opts.identity.identity_expires > previousOpts.identity.identity_expires ) { - const validatedIdentity = this.validateAndSetIdentity(opts.identity); - if (validatedIdentity && !isOptoutIdentity(validatedIdentity)) - this.triggerRefreshOrSetTimer(validatedIdentity); - this._opts.identity = opts.identity; + this.handleNewIdentity(opts.identity); this._logger.log('new identity set'); } else { + this._opts.identity = previousOpts.identity; this._logger.log('new identity not set because expires before current identity'); } } - if (opts.useCookie !== undefined && this._opts.useCookie !== opts.useCookie) { - shouldUpdateConfig = true; - shouldUpdateIdentityValue = true; - this._storageManager?.updateUseCookie(opts.useCookie); - this._opts.useCookie = opts.useCookie; - this._logger.log('new use cookie variable, updated store config and storage manager '); - } - - if (opts.refreshRetryPeriod && this._opts.refreshRetryPeriod !== opts.refreshRetryPeriod) { - this._opts.refreshRetryPeriod = opts.refreshRetryPeriod; + if (opts.refreshRetryPeriod && previousOpts.refreshRetryPeriod !== opts.refreshRetryPeriod) { this.setRefreshTimer(); this._logger.log('new refresh period set and refresh timer set'); } - if (opts.callback && opts.callback !== this._opts.callback) { + if (opts.callback && opts.callback !== previousOpts.callback) { this._initCallbackManager?.addInitCallback(opts.callback); if (this._opts.identity) this.validateAndSetIdentity(this._opts.identity); - this._opts.callback = opts.callback; this._logger.log('init callback added to list'); } - if (shouldUpdateIdentityValue) { - this._storageManager?.updateValue(this._opts, this._product.cookieName, previousOpts); - } - if (shouldUpdateConfig) { - updateConfig(this._opts, this._product, previousOpts); - } + updateConfig(this._opts, this._product, previousOpts); + this._storageManager = new StorageManager( + this._opts, + this._product.cookieName, + this._product.localStorageKey + ); + this._storageManager?.updateValue(this._opts, this._product.cookieName, previousOpts); } else { storeConfig(opts, this._product); this._opts = opts; @@ -285,9 +255,7 @@ export abstract class SdkBase { } else { identity = this._storageManager.loadIdentityWithFallback(); } - const validatedIdentity = this.validateAndSetIdentity(identity); - if (validatedIdentity && !isOptoutIdentity(validatedIdentity)) - this.triggerRefreshOrSetTimer(validatedIdentity); + this.handleNewIdentity(identity); } this.setInitComplete(true); @@ -428,6 +396,12 @@ export abstract class SdkBase { } } + private handleNewIdentity(identity: Identity | OptoutIdentity | null) { + const validatedIdentity = this.validateAndSetIdentity(identity); + if (validatedIdentity && !isOptoutIdentity(validatedIdentity)) + this.triggerRefreshOrSetTimer(validatedIdentity); + } + private _refreshTimerId: ReturnType | null = null; private setRefreshTimer() { diff --git a/src/storageManager.ts b/src/storageManager.ts index 5998906..4e4803b 100644 --- a/src/storageManager.ts +++ b/src/storageManager.ts @@ -37,7 +37,7 @@ export class StorageManager { public updateValue(opts: SdkOptions, cookieName: string, previousOpts: SdkOptions) { if (opts.identity) { if (previousOpts.useCookie === true) { - this._cookieManager.removeCookie(); + this._cookieManager.removeCookie(previousOpts); } else if (!previousOpts || previousOpts.useCookie === false) { this._localStorageManager.removeValue(); } @@ -71,12 +71,12 @@ export class StorageManager { this._opts.useCookie === false && this._localStorageManager.loadIdentityFromLocalStorage() ) { - this._cookieManager.removeCookie(); + this._cookieManager.removeCookie(this._opts); } } public removeValues() { - this._cookieManager.removeCookie(); + this._cookieManager.removeCookie(this._opts); this._localStorageManager.removeValue(); } } From 573fcfc735e8e1e6515e45c089c56b076877b692 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Mon, 19 Aug 2024 12:19:14 -0600 Subject: [PATCH 20/23] changed init callback tests --- src/integrationTests/options.test.ts | 41 +++++++++++++++++++--------- src/sdkBase.ts | 4 --- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/integrationTests/options.test.ts b/src/integrationTests/options.test.ts index 9a9c466..51ffc73 100644 --- a/src/integrationTests/options.test.ts +++ b/src/integrationTests/options.test.ts @@ -498,7 +498,11 @@ describe('multiple init calls', () => { }); }); - describe('adding a callback when no callbacks exist before', () => { + describe('setting a new identity and make sure callback is called', () => { + const newIdentity = makeIdentity({ + advertising_token: 'new_advertising_token', + identity_expires: Date.now() + 300000, + }); beforeEach(() => { uid2.init({ identity: identity, @@ -506,19 +510,30 @@ describe('multiple init calls', () => { cookiePath: cookiePath, refreshRetryPeriod: 12345, useCookie: true, + callback: callback, }); uid2.init({ useCookie: false, - callback: callback, + identity: newIdentity, }); }); test('should contain one init callback', () => { - const initCallbacks = uid2.getInitCallbacks(); - expect(initCallbacks).toEqual([callback]); + expect(callback).toHaveBeenCalled(); }); }); - describe('adding multiple callbacks that are different', () => { + describe('adding multiple callbacks and then setting new identity', () => { + const newIdentity = makeIdentity({ + advertising_token: 'new_advertising_token', + identity_expires: Date.now() + 300000, + }); + const callback2 = jest.fn(() => { + return 'testing one'; + }); + const callback3 = jest.fn(() => { + return 'testing two'; + }); + beforeEach(() => { uid2.init({ callback: callback, @@ -529,19 +544,19 @@ describe('multiple init calls', () => { useCookie: false, }); uid2.init({ - callback: jest.fn(() => { - return 'testing one'; - }), + callback: callback2, }); uid2.init({ - callback: jest.fn(() => { - return 'testing two'; - }), + callback: callback3, + }); + uid2.init({ + identity: newIdentity, }); }); test('should contain only one init callback function', () => { - const initCallbacks = uid2.getInitCallbacks(); - expect(initCallbacks?.length).toEqual(3); + expect(callback).toHaveBeenCalled(); + expect(callback2).toHaveBeenCalled(); + expect(callback3).toHaveBeenCalled(); }); }); }); diff --git a/src/sdkBase.ts b/src/sdkBase.ts index 0441c42..dee3892 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -137,10 +137,6 @@ export abstract class SdkBase { return this._tokenPromiseHandler.createMaybeDeferredPromise(token ?? null); } - public getInitCallbacks() { - return this._initCallbackManager?.getInitCallbacks(); - } - /** * Deprecated */ From 37087297a9a50da7d80e5281457fd4e15e27e281 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Tue, 20 Aug 2024 13:04:59 -0600 Subject: [PATCH 21/23] updated some tests --- src/integrationTests/options.test.ts | 39 ---------------------------- src/sdkBase.ts | 29 ++++++++++----------- 2 files changed, 13 insertions(+), 55 deletions(-) diff --git a/src/integrationTests/options.test.ts b/src/integrationTests/options.test.ts index 51ffc73..e45fc0d 100644 --- a/src/integrationTests/options.test.ts +++ b/src/integrationTests/options.test.ts @@ -225,32 +225,6 @@ describe('multiple init calls', () => { const cookiePath = '/test/'; const cookieDomain = 'uidapi.com'; - describe('when nothing has changed', () => { - beforeEach(() => { - uid2.init({ - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - uid2.init({ - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - uid2.init({ - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - }); - }); - test('should return next two init calls without changing anything', () => { - expect(getUid2LocalStorage().advertising_token).toBe(identity.advertising_token); - let storageConfig = getConfigStorage(); - expect(storageConfig).toBeInstanceOf(Object); - expect(storageConfig).toHaveProperty('cookiePath', cookiePath); - }); - }); - describe('new base URL is given', () => { const oldBaseUrl = baseUrl; const newBaseUrl = 'http://example'; @@ -310,9 +284,6 @@ describe('multiple init calls', () => { identity: newIdentity, }); }); - test('should set value to old identity', () => { - expect(getUid2(useCookie).advertising_token).toBe(identity.advertising_token); - }); test('old identity should be in available state', () => { (expect(uid2) as any).toBeInAvailableState(identity.advertising_token); }); @@ -338,10 +309,6 @@ describe('multiple init calls', () => { identity: newIdentity, }); }); - - test('should set value', () => { - expect(getUid2(useCookie).advertising_token).toBe(oldIdentity.advertising_token); - }); test('should be in available state', () => { (expect(uid2) as any).toBeInAvailableState(oldIdentity.advertising_token); }); @@ -367,9 +334,6 @@ describe('multiple init calls', () => { }); }); - test('should set value', () => { - expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); - }); test('should be in available state', () => { (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); }); @@ -395,9 +359,6 @@ describe('multiple init calls', () => { }); }); - test('should set value', () => { - expect(getUid2(useCookie).advertising_token).toBe(newIdentity.advertising_token); - }); test('should be in available state', () => { (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); }); diff --git a/src/sdkBase.ts b/src/sdkBase.ts index dee3892..6940d8c 100644 --- a/src/sdkBase.ts +++ b/src/sdkBase.ts @@ -200,16 +200,19 @@ export abstract class SdkBase { this._logger.log('BaseUrl updated for ApiClient'); } - if (opts.identity) { - if ( - !previousOpts.identity || - opts.identity.identity_expires > previousOpts.identity.identity_expires - ) { - this.handleNewIdentity(opts.identity); - this._logger.log('new identity set'); - } else { - this._opts.identity = previousOpts.identity; - this._logger.log('new identity not set because expires before current identity'); + if (opts.callback && opts.callback !== previousOpts.callback) { + this._initCallbackManager?.addInitCallback(opts.callback); + this._logger.log('init callback added to list'); + } + + const useNewIdentity = + opts.identity && + (!previousOpts.identity || + opts.identity.identity_expires > previousOpts.identity.identity_expires); + if (useNewIdentity || opts.callback) { + let identity = useNewIdentity ? opts.identity : previousOpts.identity ?? null; + if (identity) { + this.handleNewIdentity(identity); } } @@ -218,12 +221,6 @@ export abstract class SdkBase { this._logger.log('new refresh period set and refresh timer set'); } - if (opts.callback && opts.callback !== previousOpts.callback) { - this._initCallbackManager?.addInitCallback(opts.callback); - if (this._opts.identity) this.validateAndSetIdentity(this._opts.identity); - this._logger.log('init callback added to list'); - } - updateConfig(this._opts, this._product, previousOpts); this._storageManager = new StorageManager( this._opts, From 85d925d54f7ecba779ba810ac6bb346b0c9959e2 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Tue, 20 Aug 2024 13:46:53 -0600 Subject: [PATCH 22/23] added a data driven test case --- src/integrationTests/options.test.ts | 203 ++++++++++++--------------- 1 file changed, 90 insertions(+), 113 deletions(-) diff --git a/src/integrationTests/options.test.ts b/src/integrationTests/options.test.ts index e45fc0d..5d4bace 100644 --- a/src/integrationTests/options.test.ts +++ b/src/integrationTests/options.test.ts @@ -246,7 +246,7 @@ describe('multiple init calls', () => { }); }); - describe('no base URL is given, should use new base URL', () => { + describe('no base URL is given on second init call', () => { beforeEach(() => { uid2.init({ callback: callback, @@ -265,103 +265,72 @@ describe('multiple init calls', () => { }); }); - describe('new identity provided but expired', () => { - const newIdentity = makeIdentity({ - advertising_token: 'new_test_advertising_token', - identity_expires: Date.now() - 100000, - }); - const useCookie = true; - - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - useCookie: useCookie, - }); - uid2.init({ - identity: newIdentity, - }); - }); - test('old identity should be in available state', () => { - (expect(uid2) as any).toBeInAvailableState(identity.advertising_token); - }); - }); - - describe('new identity provided but expires before old identity', () => { - const oldIdentity = makeIdentity({ identity_expires: Date.now() + 10000 }); - const newIdentity = makeIdentity({ - advertising_token: 'new_test_advertising_token', - identity_expires: Date.now() + 5000, - }); - const useCookie = true; - - beforeEach(() => { - uid2.init({ - callback: callback, - identity: oldIdentity, - baseUrl: baseUrl, - cookiePath: cookiePath, - useCookie: useCookie, - }); - uid2.init({ - identity: newIdentity, - }); - }); - test('should be in available state', () => { - (expect(uid2) as any).toBeInAvailableState(oldIdentity.advertising_token); - }); - }); - - describe('new identity provided and expires after old identity', () => { - const newIdentity = makeIdentity({ - advertising_token: 'new_test_advertising_token', - identity_expires: Date.now() + 300000, - }); - const useCookie = true; - - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - useCookie: useCookie, - }); - uid2.init({ - identity: newIdentity, - }); - }); - - test('should be in available state', () => { - (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); - }); - }); - - describe('new identity provided and use cookie is false', () => { - const newIdentity = makeIdentity({ - advertising_token: 'new_test_advertising_token', - identity_expires: Date.now() + 300000, - }); - const useCookie = false; - - beforeEach(() => { - uid2.init({ - callback: callback, - identity: identity, - baseUrl: baseUrl, - cookiePath: cookiePath, - useCookie: useCookie, - }); - uid2.init({ - identity: newIdentity, - }); - }); - - test('should be in available state', () => { - (expect(uid2) as any).toBeInAvailableState(newIdentity.advertising_token); - }); + const identityTestCases = [ + { + oldIdentity: identity, + newIdentity: makeIdentity({ + advertising_token: 'new_test_advertising_token', + identity_expires: Date.now() - 100000, + }), + expectedIdentity: identity, + useCookie: true, + description: 'new identity provided but expired', + }, + { + oldIdentity: makeIdentity({ identity_expires: Date.now() + 10000 }), + newIdentity: makeIdentity({ + advertising_token: 'new_test_advertising_token', + identity_expires: Date.now() + 5000, + }), + expectedIdentity: makeIdentity({ identity_expires: Date.now() + 10000 }), + useCookie: true, + description: 'new identity provided but expires before old identity', + }, + { + oldIdentity: identity, + newIdentity: makeIdentity({ + advertising_token: 'new_test_advertising_token', + identity_expires: Date.now() + 300000, + }), + expectedIdentity: makeIdentity({ + advertising_token: 'new_test_advertising_token', + identity_expires: Date.now() + 300000, + }), + useCookie: true, + description: 'new identity provided and expires after old identity', + }, + { + oldIdentity: identity, + newIdentity: makeIdentity({ + advertising_token: 'new_test_advertising_token', + identity_expires: Date.now() + 300000, + }), + expectedIdentity: makeIdentity({ + advertising_token: 'new_test_advertising_token', + identity_expires: Date.now() + 300000, + }), + useCookie: false, + description: 'new identity provided with useCookie is false', + }, + ]; + + describe('testing how identity changes with multiple init calls', () => { + test.each(identityTestCases)( + '$description', + ({ oldIdentity, newIdentity, expectedIdentity, useCookie }) => { + uid2.init({ + callback: callback, + identity: oldIdentity, + baseUrl: baseUrl, + cookiePath: cookiePath, + useCookie: useCookie, + }); + uid2.init({ + identity: newIdentity, + }); + (expect(uid2) as any).toBeInAvailableState(expectedIdentity.advertising_token); + } + ); }); describe('new cookie path', () => { @@ -459,11 +428,7 @@ describe('multiple init calls', () => { }); }); - describe('setting a new identity and make sure callback is called', () => { - const newIdentity = makeIdentity({ - advertising_token: 'new_advertising_token', - identity_expires: Date.now() + 300000, - }); + describe('make sure when identity and callback are sent together, that callback is called with identity', () => { beforeEach(() => { uid2.init({ identity: identity, @@ -473,13 +438,13 @@ describe('multiple init calls', () => { useCookie: true, callback: callback, }); - uid2.init({ - useCookie: false, - identity: newIdentity, - }); }); test('should contain one init callback', () => { - expect(callback).toHaveBeenCalled(); + expect(callback).toHaveBeenLastCalledWith( + expect.objectContaining({ + advertising_token: identity.advertising_token, + }) + ); }); }); @@ -489,10 +454,10 @@ describe('multiple init calls', () => { identity_expires: Date.now() + 300000, }); const callback2 = jest.fn(() => { - return 'testing one'; + return 'testing two'; }); const callback3 = jest.fn(() => { - return 'testing two'; + return 'testing three'; }); beforeEach(() => { @@ -515,9 +480,21 @@ describe('multiple init calls', () => { }); }); test('should contain only one init callback function', () => { - expect(callback).toHaveBeenCalled(); - expect(callback2).toHaveBeenCalled(); - expect(callback3).toHaveBeenCalled(); + expect(callback).toHaveBeenLastCalledWith( + expect.objectContaining({ + advertising_token: newIdentity.advertising_token, + }) + ); + expect(callback2).toHaveBeenLastCalledWith( + expect.objectContaining({ + advertising_token: newIdentity.advertising_token, + }) + ); + expect(callback3).toHaveBeenLastCalledWith( + expect.objectContaining({ + advertising_token: newIdentity.advertising_token, + }) + ); }); }); }); From 330e09b9b1e0b47a2c52a129f6cf13bd93b2fe16 Mon Sep 17 00:00:00 2001 From: Ashley Smith Date: Thu, 22 Aug 2024 09:10:33 -0600 Subject: [PATCH 23/23] no longer needed updateusecookie --- src/storageManager.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/storageManager.ts b/src/storageManager.ts index 4e4803b..3f69eb5 100644 --- a/src/storageManager.ts +++ b/src/storageManager.ts @@ -46,10 +46,6 @@ export class StorageManager { } } - public updateUseCookie(useCookie: boolean) { - this._opts.useCookie = useCookie; - } - public setOptout() { const expiry = Date.now() + 72 * 60 * 60 * 1000; // 3 days - need to pick something const optout: OptoutIdentity = {