diff --git a/test/src/config/utils.js b/test/src/config/utils.js index 1e9a13f5b..1f48146f6 100644 --- a/test/src/config/utils.js +++ b/test/src/config/utils.js @@ -627,6 +627,21 @@ var pluses = /\+/g, }, hasIdentityCallInflightReturned = () => !mParticle.getInstance()?._Store?.identityCallInFlight, hasConfigurationReturned = () => !!mParticle.getInstance()?._Store?.configurationLoaded, + setupLoggerSpy = () => { + const loggerSpy = { + verbose: sinon.spy(), + warning: sinon.spy(), + error: sinon.spy(), + }; + window.mParticle.config.logger = loggerSpy; + window.mParticle.config.logLevel = 'verbose'; + return loggerSpy; + }, + hasIdentityResponseParsed = (loggerSpy) => { + return () => loggerSpy?.verbose?.getCalls()?.some(call => + call.args[0] === 'Successfully parsed Identity Response' + ); + }, getBeaconBatch = async function(beaconSpy, callIndex = 0) { const beaconCall = beaconSpy.getCall(callIndex); expect(beaconCall, 'Expected beacon call to exist').to.exist; @@ -681,11 +696,13 @@ var TestsCore = { waitForCondition: waitForCondition, fetchMockSuccess: fetchMockSuccess, hasIdentifyReturned: hasIdentifyReturned, - hasIdentityCallInflightReturned, - hasConfigurationReturned, getBeaconBatch: getBeaconBatch, setupFakeTimers: setupFakeTimers, triggerVisibilityHidden: triggerVisibilityHidden, + hasIdentityCallInflightReturned, + hasConfigurationReturned, + setupLoggerSpy, + hasIdentityResponseParsed, }; export default TestsCore; \ No newline at end of file diff --git a/test/src/tests-identities-attributes.ts b/test/src/tests-identities-attributes.ts index 256d91847..fde385b72 100644 --- a/test/src/tests-identities-attributes.ts +++ b/test/src/tests-identities-attributes.ts @@ -10,17 +10,18 @@ import Utils from './config/utils'; import { AllUserAttributes, UserAttributesValue } from '@mparticle/web-sdk'; import { UserAttributes } from '../../src/identity-user-interfaces'; import { Batch, CustomEvent, UserAttributeChangeEvent } from '@mparticle/event-models'; -import { IMParticleInstanceManager, SDKProduct } from '../../src/sdkRuntimeModels'; +import { IMParticleInstanceManager } from '../../src/sdkRuntimeModels'; const { waitForCondition, fetchMockSuccess, - hasIdentifyReturned, - hasIdentityCallInflightReturned, + hasIdentifyReturned, + hasIdentityResponseParsed, findEventFromRequest, findBatch, getLocalStorage, MockForwarder, - getIdentityEvent + getIdentityEvent, + setupLoggerSpy } = Utils; declare global { @@ -53,11 +54,15 @@ const BAD_USER_ATTRIBUTE_KEY_AS_ARRAY = ([ const BAD_USER_ATTRIBUTE_LIST_VALUE = (1234 as unknown) as UserAttributesValue[]; -describe('identities and attributes', function() { +describe.only('identities and attributes', function() { + let loggerSpy; let beforeEachCallbackCalled = false; let hasBeforeEachCallbackReturned; beforeEach(function() { + mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; + fetchMockSuccess(urls.identify, { mpid: testMPID, is_logged_in: false }); @@ -82,7 +87,6 @@ describe('identities and attributes', function() { }); it('should set user attribute', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -104,7 +108,6 @@ describe('identities and attributes', function() { }); it('should set user attribute be case insensitive', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -140,7 +143,6 @@ describe('identities and attributes', function() { }); it('should set multiple user attributes with setUserAttributes', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -165,7 +167,6 @@ describe('identities and attributes', function() { }); it('should remove user attribute', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -183,7 +184,6 @@ describe('identities and attributes', function() { }); it('should remove user attribute case insensitive', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -383,8 +383,6 @@ describe('identities and attributes', function() { }); it('should set user attribute list', async () => { - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); mParticle.Identity.getCurrentUser().setUserAttributeList('numbers', [ @@ -409,8 +407,6 @@ describe('identities and attributes', function() { }); it('should set user attribute list case insensitive', async () => { - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); mParticle.Identity.getCurrentUser().setUserAttributeList('numbers', [ @@ -463,8 +459,6 @@ describe('identities and attributes', function() { it('should make a copy of user attribute list', async () => { const list = [1, 2, 3, 4, 5]; - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -489,8 +483,6 @@ describe('identities and attributes', function() { }); it('should remove all user attributes', async () => { - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); mParticle.Identity.getCurrentUser().setUserAttributeList('numbers', [ @@ -513,7 +505,6 @@ describe('identities and attributes', function() { }); it('should get user attribute lists', async () => { - mParticle._resetForTests(MPConfig); mParticle.init(apiKey, window.mParticle.config); @@ -535,7 +526,6 @@ describe('identities and attributes', function() { }); it('should copy when calling get user attribute lists', async () => { - mParticle._resetForTests(MPConfig); mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -557,7 +547,6 @@ describe('identities and attributes', function() { }); it('should copy when calling get user attributes', async () => { - mParticle._resetForTests(MPConfig); mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); mParticle.Identity.getCurrentUser().setUserAttribute('gender', 'male'); @@ -581,8 +570,6 @@ describe('identities and attributes', function() { }); it('should get all user attributes', async () => { - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); mParticle.Identity.getCurrentUser().setUserAttribute('test', '123'); @@ -598,7 +585,6 @@ describe('identities and attributes', function() { }); it('should not set user attribute list if value is not array', async () => { - mParticle._resetForTests(MPConfig); mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); mParticle.Identity.getCurrentUser().setUserAttributeList( @@ -709,8 +695,6 @@ describe('identities and attributes', function() { }); it('should send user attribute change requests when setting new attributes', async () => { - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); // set a new attribute, age @@ -823,8 +807,6 @@ describe('identities and attributes', function() { }); it('should send user attribute change requests for the MPID it is being set on', async () => { - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -918,9 +900,12 @@ describe('identities and attributes', function() { }); it('should send user identity change requests when setting new identities on new users', async () => { + // Clear out before each init call + await waitForCondition(hasBeforeEachCallbackReturned); + mParticle._resetForTests(MPConfig); - fetchMock.resetHistory(); + loggerSpy = setupLoggerSpy(); window.mParticle.config.identifyRequest = { userIdentities: { @@ -929,7 +914,7 @@ describe('identities and attributes', function() { }; mParticle.config.flags.eventBatchingIntervalMillis = 5000 mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned); + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); mParticle.upload(); expect( JSON.parse(`${fetchMock.lastOptions().body}`).user_identities @@ -954,12 +939,9 @@ describe('identities and attributes', function() { customerid: 'customerid1', }, }; + loggerSpy.verbose.resetHistory(); mParticle.Identity.login(loginUser); - await waitForCondition(() => { - return ( - mParticle.Identity.getCurrentUser()?.getMPID() === 'anotherMPID' - ); - }); + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); let body = JSON.parse(`${fetchMock.lastOptions().body}`); // should be the new MPID @@ -999,16 +981,13 @@ describe('identities and attributes', function() { }, }; - fetchMockSuccess('https://identity.mparticle.com/v1/anotherMPID/modify', { - mpid: 'anotherMPID', is_logged_in: true - }); + fetchMockSuccess('https://identity.mparticle.com/v1/anotherMPID/modify', { + mpid: 'anotherMPID', is_logged_in: true + }); + loggerSpy.verbose.resetHistory(); mParticle.Identity.modify(modifyUser); - await waitForCondition(() => { - return ( - mParticle.getInstance()._Store.identityCallInFlight === false - ); - }); + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); const body2 = JSON.parse(`${fetchMock.lastOptions().body}`); expect(body2.mpid).to.equal('anotherMPID'); expect(body2.user_identities).to.have.property( @@ -1039,12 +1018,9 @@ describe('identities and attributes', function() { fetchMock.resetHistory(); + loggerSpy.verbose.resetHistory(); mParticle.Identity.modify(modifyUser2); - await waitForCondition(() => { - return ( - mParticle.getInstance()._Store.identityCallInFlight === false - ); - }); + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); const body3 = JSON.parse(`${fetchMock.lastOptions().body}`); expect(body3.mpid).to.equal('anotherMPID'); @@ -1073,12 +1049,9 @@ describe('identities and attributes', function() { mpid: 'mpid2', is_logged_in: false }); + loggerSpy.verbose.resetHistory(); mParticle.Identity.logout(logoutUser); - await waitForCondition(() => { - return ( - mParticle.Identity.getCurrentUser()?.getMPID() === 'mpid2' - ); - }); + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); // Calls are for logout and UIC expect(fetchMock.calls().length).to.equal(2); const body4 = JSON.parse(`${fetchMock.lastOptions().body}`); @@ -1106,11 +1079,12 @@ describe('identities and attributes', function() { }); it('should order user identity change events before logging any events', async () => { - mParticle._resetForTests(MPConfig); - fetchMock.resetHistory(); - // Clear out before each init call await waitForCondition(hasBeforeEachCallbackReturned); + + mParticle._resetForTests(MPConfig); + fetchMock.resetHistory(); + loggerSpy = setupLoggerSpy(); window.mParticle.config.identifyRequest = { userIdentities: { @@ -1120,7 +1094,7 @@ describe('identities and attributes', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned); + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); mParticle.logEvent('Test Event 1'); mParticle.logEvent('Test Event 2'); @@ -1169,12 +1143,12 @@ describe('identities and attributes', function() { }); it('should order user identity change events before logging any events that are in the ready queue', async () => { - - mParticle._resetForTests(MPConfig); - fetchMock.resetHistory(); - // Clear out before each init call await waitForCondition(hasBeforeEachCallbackReturned); + + mParticle._resetForTests(MPConfig); + fetchMock.resetHistory(); + loggerSpy = setupLoggerSpy(); window.mParticle.config.identifyRequest = { userIdentities: { @@ -1190,7 +1164,7 @@ describe('identities and attributes', function() { expect(mParticle.getInstance()._preInit.readyQueue.length).to.equal(3); - await waitForCondition(hasIdentityCallInflightReturned); + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); expect(fetchMock.calls().length).to.equal(7); @@ -1235,8 +1209,13 @@ describe('identities and attributes', function() { }); it('should send historical UIs on batches when MPID changes', async () => { + // Clear out before each init call + await waitForCondition(hasBeforeEachCallbackReturned); + mParticle._resetForTests(MPConfig); - + fetchMock.resetHistory(); + loggerSpy = setupLoggerSpy(); + window.mParticle.config.identifyRequest = { userIdentities: { email: 'initial@gmail.com', @@ -1250,7 +1229,7 @@ describe('identities and attributes', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned); + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); fetchMockSuccess(urls.login, { mpid: 'testMPID', is_logged_in: true }); @@ -1261,13 +1240,11 @@ describe('identities and attributes', function() { }, }; + loggerSpy.verbose.resetHistory(); mParticle.Identity.login(loginUser); - await waitForCondition(() => { - return ( - mParticle.getInstance()._Store.identityCallInFlight === false - ); - }); + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); + let batch = JSON.parse(`${fetchMock.lastOptions().body}`); expect(batch.mpid).to.equal(testMPID); expect(batch.user_identities).to.have.property( @@ -1289,13 +1266,9 @@ describe('identities and attributes', function() { mpid: 'mpid2', is_logged_in: false }); + loggerSpy.verbose.resetHistory(); mParticle.Identity.logout(logoutUser); - - await waitForCondition(() => { - return ( - mParticle.Identity.getCurrentUser()?.getMPID() === 'mpid2' - ); - }); + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); batch = JSON.parse(`${fetchMock.lastOptions().body}`); expect(batch.mpid).to.equal('mpid2'); expect(batch.user_identities).to.have.property('other', 'other1'); @@ -1309,13 +1282,10 @@ describe('identities and attributes', function() { mpid: 'testMPID', is_logged_in: true }); + loggerSpy.verbose.resetHistory(); mParticle.Identity.login(loginUser); - await waitForCondition(() => { - return ( - mParticle.getInstance()._Store.identityCallInFlight === false - ); - }); + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); // switching back to logged in user should not result in any UIC events expect(fetchMock.calls().length).to.equal(1); @@ -1336,8 +1306,6 @@ describe('identities and attributes', function() { ); }); it('should not send user attribute change requests when user attribute already set with same value with false values', async () => { - mParticle._resetForTests(MPConfig); - window.mParticle.config.flags = { EventBatchingIntervalMillis: 0, }; @@ -1433,8 +1401,6 @@ describe('identities and attributes', function() { }); it('should send user attribute change event when setting different falsey values', async () => { - mParticle._resetForTests(MPConfig); - window.mParticle.config.flags = { EventBatchingIntervalMillis: 0, }; diff --git a/test/src/tests-identity.ts b/test/src/tests-identity.ts index 5aeb627d0..429c174da 100644 --- a/test/src/tests-identity.ts +++ b/test/src/tests-identity.ts @@ -40,6 +40,8 @@ const { MockForwarder, waitForCondition, hasIdentityCallInflightReturned, + setupLoggerSpy, + hasIdentityResponseParsed, } = Utils; const { HTTPCodes } = Constants; @@ -89,8 +91,9 @@ const fetchMockSuccess = (url: string, body: any = {}, headers: any = {}) => { ); }; -describe('identity', function() { +describe.only('identity', function() { let clock; + let loggerSpy; let hasIdentifyReturned; let hasIdentifyReturnedWithEmail; let hasLoginReturned; @@ -99,7 +102,9 @@ describe('identity', function() { let hasBeforeEachCallbackReturned beforeEach(function() { + mParticle._resetForTests(MPConfig); delete mParticle.config.useCookieStorage; + fetchMock.config.overwriteRoutes = true; fetchMockSuccess(urls.events); fetchMockSuccess(urls.identify, { context: null, @@ -144,13 +149,11 @@ describe('identity', function() { }; hasBeforeEachCallbackReturned = () => beforeEachCallbackCalled; - }); afterEach(function () { fetchMock.restore(); beforeEachCallbackCalled = false; - mParticle._resetForTests(MPConfig); if (clock && clock) { clock.runAll(); // ensures all timers are complete from previous tests } @@ -174,7 +177,7 @@ describe('identity', function() { }, }); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); // Calls should be expected // 1. Identify @@ -216,7 +219,7 @@ describe('identity', function() { is_logged_in: false, }); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); mParticle.Identity.logout(); @@ -250,7 +253,7 @@ describe('identity', function() { }); it('should contain login request', async () => { - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); fetchMockSuccess(urls.login, { mpid: testMPID, @@ -268,7 +271,7 @@ describe('identity', function() { }, }); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); // Calls that should be expected: // 1. Identify @@ -316,7 +319,7 @@ describe('identity', function() { ], }); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); mParticle.Identity.modify({ userIdentities: { email: 'test@email.com', @@ -368,7 +371,7 @@ describe('identity', function() { let data: IIdentityAPIRequestData; - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); mParticle.Identity.identify({ userIdentities: { @@ -376,7 +379,7 @@ describe('identity', function() { }, }); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); // 4 Calls should be expected // 1. Identify @@ -410,7 +413,7 @@ describe('identity', function() { }); it('should strip falsey values from identify request', async () => { - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); const identityApiData = { userIdentities: { @@ -427,7 +430,7 @@ describe('identity', function() { mParticle.Identity.identify(identityApiData as unknown as IdentityApiData); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); const firstCall = fetchMock.calls()[0]; expect(firstCall[0].split('/')[4]).to.equal('identify'); @@ -468,7 +471,7 @@ describe('identity', function() { }); it('should strip falsey values from login request', async () => { - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); const identityApiData = { userIdentities: { @@ -495,7 +498,7 @@ describe('identity', function() { mParticle.Identity.login(identityApiData as unknown as IdentityApiData); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); const firstCall = fetchMock.calls()[0]; expect(firstCall[0].split('/')[4]).to.equal('login'); @@ -526,7 +529,7 @@ describe('identity', function() { }); it('should strip falsey values from logout request', async () => { - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); const identityApiData = { userIdentities: { @@ -553,7 +556,7 @@ describe('identity', function() { mParticle.Identity.logout(identityApiData as unknown as IdentityApiData); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); const firstCall = fetchMock.calls()[0]; expect(firstCall[0].split('/')[4]).to.equal('logout'); @@ -584,7 +587,7 @@ describe('identity', function() { }); it('should strip falsey values from modify request', async () => { - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); const identityApiData = { userIdentities: { @@ -610,10 +613,9 @@ describe('identity', function() { mParticle.Identity.modify(identityApiData as unknown as IdentityApiData); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); const firstCall = fetchMock.calls()[0]; - debugger expect(firstCall[0].split('/')[5]).to.equal('modify'); const data = JSON.parse(firstCall[1].body as unknown as string) as IIdentityAPIModifyRequestData; @@ -643,7 +645,6 @@ describe('identity', function() { describe('privacy flags', function() { beforeEach(function() { - mParticle._resetForTests(MPConfig); mParticle.config.flags.cacheIdentity = 'True'; localStorage.clear(); }); @@ -671,10 +672,10 @@ describe('identity', function() { }); }); - // https://go.mparticle.com/work/SQDSDKS-6849 - // This test passes with no issue when it is run on its own, but fails when tests-forwarders.js are also ran. it('should respect consent rules on consent-change', async () => { + await waitForCondition(hasIdentityCallInflightReturned); mParticle._resetForTests(MPConfig); + loggerSpy = setupLoggerSpy(); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder('MockForwarder1'); mockForwarder.register(window.mParticle.config); @@ -718,7 +719,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition( () => mParticle.Identity.getCurrentUser()?.getMPID() === 'MPID1') + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); let activeForwarders = mParticle.getInstance()._getActiveForwarders(); expect(activeForwarders.length).to.equal(0); @@ -739,9 +740,10 @@ describe('identity', function() { is_logged_in: false, }); + loggerSpy.verbose.resetHistory(); mParticle.Identity.login(); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); activeForwarders = mParticle.getInstance()._getActiveForwarders(); expect(activeForwarders.length).to.equal(0); @@ -760,7 +762,7 @@ describe('identity', function() { describe('cookies', function () { it('should store all MPIDs associated with a sessionId, then clear MPIDs from currentSessionMPIDs when a new session starts', async () => { - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); fetchMockSuccess(urls.login, { mpid: 'logged-in-user', @@ -774,7 +776,7 @@ describe('identity', function() { }; mParticle.Identity.login(userIdentities1); - await waitForCondition(hasLoginReturned) + await waitForCondition(hasLoginReturned); const localStorageDataBeforeSessionEnd = mParticle .getInstance() @@ -791,7 +793,7 @@ describe('identity', function() { mParticle.logEvent('hi'); mParticle.Identity.login(userIdentities1); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); const localStorageAfterLoggingEvent = mParticle .getInstance() @@ -800,6 +802,7 @@ describe('identity', function() { }); it('localStorage - should switch user cookies to new mpid details from cookies when a new mpid is provided', async () => { + await waitForCondition(hasIdentityCallInflightReturned); mParticle._resetForTests(MPConfig); window.mParticle.config.useCookieStorage = false; @@ -807,6 +810,8 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); + await waitForCondition(hasIdentifyReturned); + const cookies1 = mParticle.getInstance()._Persistence.getLocalStorage(); cookies1.cu.should.equal(testMPID); cookies1[testMPID].should.have.property('csd'); @@ -823,7 +828,9 @@ describe('identity', function() { }; mParticle.Identity.login(userIdentities1); - await waitForCondition(hasLoginReturned) + + await waitForCondition(hasLoginReturned); + const cookiesAfterMPIDChange = mParticle .getInstance() ._Persistence.getLocalStorage(); @@ -861,7 +868,8 @@ describe('identity', function() { }); }); - it('cookies - should switch user cookies to new mpid details from cookies when a new mpid is provided', async () => { + it('should switch user cookies to new mpid details from cookies when a new mpid is provided', async () => { + await waitForCondition(hasIdentityCallInflightReturned); mParticle._resetForTests(MPConfig); mParticle.config.useCookieStorage = true; @@ -869,7 +877,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); const cookiesAfterInit = findCookie(); cookiesAfterInit.should.have.properties('gs', 'cu', testMPID); @@ -904,7 +912,7 @@ describe('identity', function() { mParticle.Identity.login(userIdentities1); - await waitForCondition(hasLoginReturned) + await waitForCondition(hasLoginReturned); const cookiesAfterMPIDChange = findCookie(); cookiesAfterMPIDChange.should.have.properties([ @@ -1367,40 +1375,40 @@ describe('identity', function() { const identityAPIRequest = BAD_USER_IDENTITIES_AS_STRING; mParticle.Identity.login(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as an array', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_ARRAY; mParticle.Identity.login(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as a null', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_NULL; mParticle.Identity.login(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as undefined', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_UNDEFINED; mParticle.Identity.login(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as a boolean', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_BOOLEAN; mParticle.Identity.login(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid callback is set', async () => { @@ -1413,8 +1421,8 @@ describe('identity', function() { mParticle.Identity.login(identityRequest, badCallback); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); }); @@ -1428,40 +1436,40 @@ describe('identity', function() { const identityAPIRequest = BAD_USER_IDENTITIES_AS_STRING; mParticle.Identity.logout(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as array', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_ARRAY; mParticle.Identity.logout(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as a null', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_NULL; mParticle.Identity.logout(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as undefined', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_UNDEFINED; mParticle.Identity.logout(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as boolean', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_BOOLEAN; mParticle.Identity.logout(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid callback is sent', async () => { @@ -1474,8 +1482,8 @@ describe('identity', function() { mParticle.Identity.logout(identityRequest, badCallback); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); }); @@ -1490,40 +1498,40 @@ describe('identity', function() { debugger mParticle.Identity.modify(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as an array', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_ARRAY; mParticle.Identity.modify(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as a null', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_NULL; mParticle.Identity.modify(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as a undefined', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_UNDEFINED; mParticle.Identity.modify(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as a boolean', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_BOOLEAN; mParticle.Identity.modify(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid callback is set', async () => { @@ -1536,8 +1544,8 @@ describe('identity', function() { mParticle.Identity.modify(identityRequest, badCallback); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); }); @@ -1551,40 +1559,40 @@ describe('identity', function() { const identityAPIRequest = BAD_USER_IDENTITIES_AS_STRING; mParticle.Identity.identify(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as an array', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_ARRAY; mParticle.Identity.identify(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as a null', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_NULL; mParticle.Identity.identify(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as a undefined', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_UNDEFINED; mParticle.Identity.identify(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid request is sent as a boolean', async () => { const identityAPIRequest = BAD_USER_IDENTITIES_AS_BOOLEAN; mParticle.Identity.identify(identityAPIRequest); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); it('should not make a request when an invalid callback is set', async () => { @@ -1597,8 +1605,8 @@ describe('identity', function() { mParticle.Identity.identify(identityRequest, badCallback); - await waitForCondition(hasIdentityCallInflightReturned) - expect(fetchMock.calls().length).to.equal(0); + await waitForCondition(hasIdentityCallInflightReturned); + expect(fetchMock.calls().length).to.equal(0); }); }); @@ -1709,39 +1717,38 @@ describe('identity', function() { ], }); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); fetchMock.resetHistory(); mParticle.Identity.modify(identityAPIData); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); // 1st call is modify, 2nd call is the UIC event - console.log('fetchMock.calls()', fetchMock.calls()); - expect(fetchMock.calls().length).to.equal(2); + expect(fetchMock.calls().length).to.equal(2); - const modifyCall = fetchMock.calls()[0]; - expect(modifyCall[0].split('/')[5]).to.equal('modify'); + const modifyCall = fetchMock.calls()[0]; + expect(modifyCall[0].split('/')[5]).to.equal('modify'); - const data: IIdentityAPIModifyRequestData = JSON.parse(modifyCall[1].body as unknown as string); + const data: IIdentityAPIModifyRequestData = JSON.parse(modifyCall[1].body as unknown as string); - expect(data.identity_changes.length).to.equal(1); - expect(data.identity_changes[0]).to.have.keys( - 'old_value', - 'new_value', - 'identity_type' - ); - expect(data.identity_changes[0]).to.have.keys( - 'old_value', - 'new_value', - 'identity_type' - ); + expect(data.identity_changes.length).to.equal(1); + expect(data.identity_changes[0]).to.have.keys( + 'old_value', + 'new_value', + 'identity_type' + ); + expect(data.identity_changes[0]).to.have.keys( + 'old_value', + 'new_value', + 'identity_type' + ); }); it('ensure that automatic identify is not called more than once.', async () => { mParticle._resetForTests(MPConfig); const spy = sinon.spy(); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); mParticle.config.identityCallback = spy; fetchMockSuccess(urls.identify, { @@ -1753,37 +1760,53 @@ describe('identity', function() { await waitForCondition(() => { return mParticle.Identity.getCurrentUser()?.getMPID() === 'otherMPID'; - }) + }); spy.calledOnce.should.be.ok(); mParticle.startNewSession(); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); spy.calledOnce.should.be.ok(); }); it('queue events when MPID is 0, and then flush events once MPID changes', async () => { + await waitForCondition(hasIdentityCallInflightReturned); mParticle._resetForTests(MPConfig); + loggerSpy = setupLoggerSpy(); + fetchMock.resetHistory(); - fetchMockSuccess( - urls.identify, - { - status: 400, - body: JSON.stringify({}), - } - ); + // HTTP Bad Request results in an MPID of 0 + fetchMock.post(urls.identify, { + status: HTTP_BAD_REQUEST, + body: { + Errors: [ + { + message: 'Bad Request', + code: 'BAD_REQUEST' + }, + ], + ErrorCode: 'BAD_REQUEST', + StatusCode: HTTP_BAD_REQUEST, + RequestId: '123', + }, + }, { + overwriteRoutes: true, + }); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); + + expect(mParticle.Identity.getCurrentUser()).to.be.null; + + const identifyCall = fetchMock.calls().find(call => call[0].includes('/identify')); + expect(identifyCall).to.be.ok; mParticle.logEvent('Test Event 1'); - // There should be 3 calls here: + // There should be 1 call here: // 1. Identify (from init) - // 2. AST - // 3. Session start - // The event should not be sent because the MPID is 0 - expect(fetchMock.calls().length).to.equal(3); + // AST, session start, and logEvent are all queued since MPID is 0 + expect(fetchMock.calls().length).to.equal(1); let testEvent1 = findEventFromRequest( fetchMock.calls(), @@ -1798,18 +1821,20 @@ describe('identity', function() { }); mParticle.logEvent('Test Event 2'); + loggerSpy.verbose.resetHistory(); mParticle.Identity.login(); - await waitForCondition(hasLoginReturned) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); // server requests will now have the following events: - // 1. Identify (from init) - // 2. AST - // 3. Session start - // 4. Test1, - // 5. Login + // 1. Identify + // 2. Login + // 3. AST + // 4. Session start + // 5. Test1, // 6. Test2 expect(fetchMock.calls().length).to.equal(6); + fetchMock.calls().forEach(call => console.log('call', call[0])) testEvent1 = findEventFromRequest( fetchMock.calls(), @@ -1831,18 +1856,17 @@ describe('identity', function() { 'session_start' ); - const loginCall = fetchMock.calls()[3]; + const loginCall = fetchMock.calls()[1]; expect(testEvent1).to.be.ok; expect(testEvent2).to.be.ok; expect(ASTEvent).to.be.ok; expect(sessionStartEvent).to.be.ok; + expect(loginCall).to.be.ok; expect(loginCall[0].split('/')[4]).to.equal('login'); }); it('getUsers should return all mpids available in local storage', async () => { - mParticle._resetForTests(MPConfig); - const userIdentities1: IdentityApiData = { userIdentities: { customerid: 'foo1', @@ -1863,7 +1887,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); // get user 1 into cookies fetchMockSuccess(urls.login, { @@ -1873,7 +1897,7 @@ describe('identity', function() { mParticle.Identity.login(userIdentities1); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); // get user 2 into cookies fetchMockSuccess(urls.login, { @@ -1883,7 +1907,7 @@ describe('identity', function() { mParticle.Identity.login(userIdentities2); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); // get user 3 into cookies fetchMockSuccess(urls.login, { @@ -1893,7 +1917,7 @@ describe('identity', function() { mParticle.Identity.login(userIdentities3); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); // init again using user 1 fetchMockSuccess(urls.login, { @@ -1903,7 +1927,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(() => mParticle.Identity?.getUsers().length === 4) + await waitForCondition(() => mParticle.Identity?.getUsers().length === 4); const users = mParticle.Identity.getUsers(); // This includes the original, starting user, in addition to the 3 added above expect(users.length).to.equal(4); @@ -1919,8 +1943,6 @@ describe('identity', function() { }); it('should update its own cookies, not any other mpids when initializing with a different set of credentials', async () => { - mParticle._resetForTests(MPConfig); - const user1 = { userIdentities: { customerid: 'customerid1', @@ -1944,7 +1966,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); // get user 1 into cookies fetchMockSuccess(urls.login, { @@ -1954,7 +1976,7 @@ describe('identity', function() { mParticle.Identity.login(user1); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.Identity.getCurrentUser().setUserAttribute('user', 'user1'); @@ -1966,7 +1988,7 @@ describe('identity', function() { mParticle.Identity.login(user2); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.Identity.getCurrentUser().setUserAttribute('user', 'user2'); @@ -1978,7 +2000,7 @@ describe('identity', function() { mParticle.Identity.login(user3); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.Identity.getCurrentUser().setUserAttribute('user', 'user3'); @@ -1990,7 +2012,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); const localStorage = mParticle .getInstance() @@ -2047,7 +2069,9 @@ describe('identity', function() { }); it("should find the related MPID's cookies when given a UI with fewer IDs when passed to login, logout, and identify, and then log events with updated cookies", async () => { + await waitForCondition(hasIdentityCallInflightReturned); mParticle._resetForTests(MPConfig); + loggerSpy = setupLoggerSpy(); fetchMock.restore(); const user1: IdentityApiData = { userIdentities: { @@ -2085,14 +2109,23 @@ describe('identity', function() { ], }); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); + + loggerSpy.verbose.resetHistory(); mParticle.Identity.modify(user1modified); // Should contain the following calls: // 1 for the initial identify // 3 for the events (Session Start, UAT and UIC) // 1 for the modify // 1 for the UIC event - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(() => { + const currentUser = mParticle.Identity.getCurrentUser(); + const userIdentities = currentUser?.getUserIdentities()?.userIdentities; + return userIdentities && + userIdentities.customerid === 'customerid1' && + userIdentities.email === 'email2@test.com'; + }); + expect(fetchMock.calls().length).to.equal(6); // This will add a new UAC Event to the call @@ -2120,11 +2153,12 @@ describe('identity', function() { fetchMockSuccess(urls.logout, { mpid: 'logged-out-user', is_logged_in: true, - }); + }); + loggerSpy.verbose.resetHistory(); mParticle.Identity.logout(user2); - await waitForCondition(hasLogOutReturned) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); // This will add the following new calls: // 1 for the logout @@ -2145,13 +2179,11 @@ describe('identity', function() { fetchMockSuccess(urls.login, { mpid: 'testMPID', is_logged_in: true, - }); + }); + loggerSpy.verbose.resetHistory(); mParticle.Identity.login(user1); - await waitForCondition(() => { - return mParticle.Identity.getCurrentUser().getMPID() === 'testMPID'; - }) - + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); // This will add the following new calls: // 1 for the login // 1 for Test Event 3 @@ -2167,9 +2199,10 @@ describe('identity', function() { }); }); - it('should add new MPIDs to cookie structure when initializing new identity requests, returning an existing mpid when reinitializing with a previous identity', async () => { + it('should add new MPIDs to cookie structure when initializing new with a previous identity', async () => { + await waitForCondition(hasIdentityCallInflightReturned); mParticle._resetForTests(MPConfig); - + loggerSpy = setupLoggerSpy(); const user1 = { userIdentities: { customerid: '1', @@ -2198,7 +2231,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); const user1UIs = mParticle.Identity.getCurrentUser().getUserIdentities(); @@ -2209,9 +2242,10 @@ describe('identity', function() { is_logged_in: true, }); + loggerSpy.verbose.resetHistory(); mParticle.Identity.login(user2); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); const user2UIs = mParticle.Identity.getCurrentUser().getUserIdentities(); user2UIs.userIdentities.customerid.should.equal('2'); @@ -2221,9 +2255,10 @@ describe('identity', function() { is_logged_in: true, }); + loggerSpy.verbose.resetHistory(); mParticle.Identity.login(user3); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); const user3UIs = mParticle.Identity.getCurrentUser().getUserIdentities(); user3UIs.userIdentities.customerid.should.equal('3'); @@ -2233,9 +2268,10 @@ describe('identity', function() { is_logged_in: true, }); + loggerSpy.verbose.resetHistory(); mParticle.Identity.login(user4); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); const user4UIs = mParticle.Identity.getCurrentUser().getUserIdentities(); user4UIs.userIdentities.customerid.should.equal('4'); @@ -2245,9 +2281,10 @@ describe('identity', function() { is_logged_in: true, }); + loggerSpy.verbose.resetHistory(); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); const user5 = mParticle.Identity.getCurrentUser(); user5.getUserIdentities().userIdentities.customerid.should.equal('1'); @@ -2265,7 +2302,7 @@ describe('identity', function() { it('should not send requests to the server with invalid userIdentity values', async () => { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); fetchMock.resetHistory(); @@ -2366,7 +2403,7 @@ describe('identity', function() { callback ); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); expect(result, identityMethod).to.be.ok; expect( result.httpCode, @@ -2386,7 +2423,7 @@ describe('identity', function() { validUserIdentities.forEach(async(goodIdentities) => { mParticle.Identity.modify(goodIdentities, callback); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); expect(result, identityMethod).to.be.ok; @@ -2432,11 +2469,11 @@ describe('identity', function() { is_logged_in: false, }); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); mParticle.Identity.login(user); - await waitForCondition(hasLoginReturned) + await waitForCondition(hasLoginReturned); const userIdentities1 = mParticle.Identity.getCurrentUser().getUserIdentities(); @@ -2444,7 +2481,7 @@ describe('identity', function() { mParticle.Identity.logout(); - await waitForCondition(hasLogOutReturned) + await waitForCondition(hasLogOutReturned); const userIdentities2 = mParticle.Identity.getCurrentUser().getUserIdentities(); @@ -2482,15 +2519,15 @@ describe('identity', function() { } ); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); mParticle.Identity.login(user); - await waitForCondition(hasLoginReturned) + await waitForCondition(hasLoginReturned); mParticle.Identity.modify(modifiedUser); await waitForCondition(() => { return mParticle.Identity.getCurrentUser()?.getUserIdentities().userIdentities['customerid'] === 'customerId2'; - }) + }); const cookie = mParticle.getInstance()._Persistence.getLocalStorage(); cookie['logged-in-user'].ui[1].should.equal('customerId2'); @@ -2642,6 +2679,7 @@ describe('identity', function() { }; mParticle.Identity.login(user2); + await waitForCondition(hasIdentityCallInflightReturned); await waitForCondition(() => mParticle.Identity.getCurrentUser().getMPID() === 'otherMPID'); @@ -2681,6 +2719,7 @@ describe('identity', function() { }; mParticle.Identity.login(user3); + await waitForCondition(hasIdentityCallInflightReturned); await waitForCondition(() => mParticle.Identity.getCurrentUser().getMPID() === 'otherMPID2'); @@ -2697,7 +2736,7 @@ describe('identity', function() { it('should return an empty array when no cart products exist', async () => { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); const user1 = { userIdentities: { customerid: 'customerId1', @@ -2711,7 +2750,7 @@ describe('identity', function() { mParticle.Identity.login(user1); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); const products = mParticle.Identity.getCurrentUser() .getCart() @@ -2723,7 +2762,7 @@ describe('identity', function() { it('should make a request when copyUserAttributes is included on the identity request', async () => { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); const identityAPIRequest1 = { userIdentities: { @@ -2742,7 +2781,7 @@ describe('identity', function() { mParticle.Identity.logout(identityAPIRequest1); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); // This should have a call for the logout and UIC expect(fetchMock.calls().length).to.equal(2); @@ -2762,7 +2801,7 @@ describe('identity', function() { mParticle.Identity.login(identityAPIRequest1); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); expect(fetchMock.calls().length).to.equal(1); @@ -2781,7 +2820,7 @@ describe('identity', function() { mParticle.Identity.modify(identityAPIRequest1); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); expect(fetchMock.calls().length).to.equal(1); @@ -2792,9 +2831,6 @@ describe('identity', function() { }); it('should trigger the identifyCallback when a successful identify call is sent', async () => { - // MP.sessionID does not exist yet because we perform an mParticle._resetForTests(MPConfig); - mParticle._resetForTests(MPConfig); - let mpid; fetchMockSuccess(urls.identify, { @@ -2809,16 +2845,15 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); expect(mpid).to.equal('MPID1'); }); it('should trigger the identityCallback before eventQueue is flushed', async () => { + await waitForCondition(hasBeforeEachCallbackReturned); mParticle._resetForTests(MPConfig); - await waitForCondition(hasBeforeEachCallbackReturned) - fetchMock.resetHistory(); fetchMockSuccess(urls.identify, { @@ -2844,7 +2879,7 @@ describe('identity', function() { const identifyCall = fetchMock.lastCall(); expect(identifyCall[0].split('/')[4]).to.equal('identify'); - await waitForCondition(() => callbackCalled) + await waitForCondition(() => callbackCalled); // Force an upload so we can verify the correct events have fired mParticle.upload(); @@ -2873,7 +2908,6 @@ describe('identity', function() { }); it('should still trigger the identifyCallback when no identify request is sent because there are already cookies', async () => { - mParticle._resetForTests(MPConfig); const les = new Date().getTime(); const cookies = "{'gs':{'ie':1|'dt':'test_key'|'cgid':'886e874b-862b-4822-a24a-1146cd057101'|'das':'62c91b8d-fef6-44ea-b2cc-b55714b0d827'|'csm':'WyJ0ZXN0TVBJRCJd'|'sid':'2535f9ed-ab19-4a7c-9eeb-ce4e41e0cb06'|'les': " + @@ -2889,7 +2923,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); // Should contain: // 1 for the Identify Request // 1 for the AST @@ -2906,7 +2940,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); // the server request is the AST, there is no request to Identity fetchMock.calls().length.should.equal(1); @@ -2942,9 +2976,10 @@ describe('identity', function() { }); it('identifyCallback response should have a getUser function on the result object', async () => { - let result; + await waitForCondition(hasIdentityCallInflightReturned); mParticle._resetForTests(MPConfig); - + let result; + loggerSpy = setupLoggerSpy(); fetchMockSuccess(urls.identify, { mpid: 'MPID1', is_logged_in: false, @@ -2957,7 +2992,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); result.should.have.property('getUser'); @@ -2968,10 +3003,9 @@ describe('identity', function() { describe('identityCallback responses', function () { it('should have a getUser function on identify result object', async () => { + const loggerSpy = Utils.setupLoggerSpy(); let result; - mParticle._resetForTests(MPConfig); - mParticle.config.identityCallback = function(resp) { resp.getUser().setUserAttribute('attr', 'value'); result = resp; @@ -2985,9 +3019,7 @@ describe('identity', function() { // Init fires an identify call mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(() => { - return mParticle.Identity.getCurrentUser()?.getMPID() === 'MPID1'; - }) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); result.should.have.properties('body', 'httpCode', 'getUser'); result.httpCode.should.equal(200); @@ -3004,11 +3036,10 @@ describe('identity', function() { }); it('should have a getUser function on login result object', async () => { + loggerSpy = setupLoggerSpy(); let result let loginResult; - mParticle._resetForTests(MPConfig); - mParticle.config.identityCallback = function(resp) { resp.getUser().setUserAttribute('attr', 'value'); result = resp; @@ -3026,18 +3057,17 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(() => { - return mParticle.Identity.getCurrentUser()?.getMPID() === 'MPID1'; - }) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); const identityRequest = { userIdentities: { customerid: 'test123' } }; function loginCallback(result) { loginResult = result; } + loggerSpy.verbose.resetHistory(); mParticle.Identity.login(identityRequest, loginCallback); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); loginResult .getUser() @@ -3051,10 +3081,9 @@ describe('identity', function() { }); it('should have a getUser function on logout result object', async () => { + loggerSpy = setupLoggerSpy(); let result; - let logoutResult; - - mParticle._resetForTests(MPConfig); + let logoutResult; mParticle.config.identityCallback = function(resp) { resp.getUser().setUserAttribute('attr', 'value'); @@ -3073,18 +3102,17 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(() => { - return mParticle.Identity.getCurrentUser()?.getMPID() === 'MPID1'; - }) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); const identityRequest = { userIdentities: { customerid: 'test123' } }; function logoutCallback(result) { logoutResult = result; } + loggerSpy.verbose.resetHistory(); mParticle.Identity.logout(identityRequest, logoutCallback); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); logoutResult .getUser() @@ -3098,11 +3126,12 @@ describe('identity', function() { }); it('should have a getUser function on modify result object', async () => { + await waitForCondition(hasIdentityCallInflightReturned); + mParticle._resetForTests(MPConfig); + loggerSpy = setupLoggerSpy(); let result let modifyResult; - mParticle._resetForTests(MPConfig); - mParticle.config.identityCallback = function(resp) { resp.getUser().setUserAttribute('attr', 'value'); result = resp; @@ -3113,25 +3142,24 @@ describe('identity', function() { is_logged_in: false, }); - fetchMockSuccess(urls.modify, { + fetchMockSuccess("https://identity.mparticle.com/v1/MPID1/modify", { mpid: 'MPID1', is_logged_in: false, }); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(() => { - return mParticle.Identity.getCurrentUser()?.getMPID() === 'MPID1'; - }) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); const identityRequest = { userIdentities: { customerid: 'test123' } }; function modifyCallback(result) { modifyResult = result; } + loggerSpy.verbose.resetHistory(); mParticle.Identity.modify(identityRequest, modifyCallback); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); modifyResult .getUser() @@ -3146,12 +3174,13 @@ describe('identity', function() { }); it('should call identify when there is an active session but no current user', async () => { + await waitForCondition(hasIdentityCallInflightReturned); + mParticle._resetForTests(MPConfig); + loggerSpy = setupLoggerSpy(); // this broken cookie state occurs when an initial identify request is made, fails, and the // client had no programmatic handling of a failed identify request mParticle._resetForTests(MPConfig); - await waitForCondition(hasIdentityCallInflightReturned) - fetchMockSuccess(urls.identify, { mpid: 'MPID1', is_logged_in: false, @@ -3167,7 +3196,7 @@ describe('identity', function() { fetchMock.resetHistory(); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); let cookies = mParticle.getInstance()._Persistence.getPersistence(); cookies.should.have.property('gs'); @@ -3181,9 +3210,10 @@ describe('identity', function() { }, }; fetchMock.resetHistory(); + loggerSpy.verbose.resetHistory(); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(() => mParticle.Identity.getCurrentUser()?.getMPID() === 'MPID1') + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); cookies = mParticle.getInstance()._Persistence.getPersistence(); cookies.should.have.property('gs'); @@ -3192,8 +3222,6 @@ describe('identity', function() { }); it('Users should have firstSeenTime and lastSeenTime', async () => { - mParticle._resetForTests(MPConfig); - fetchMockSuccess(urls.identify, { mpid: 'MPID1', is_logged_in: false, @@ -3203,7 +3231,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); // NOTE: Use sinon to "lock" in the current time for testing purposes const now = new Date(); @@ -3225,8 +3253,6 @@ describe('identity', function() { }); it('firstSeenTime should stay the same for a user', async () => { - mParticle._resetForTests(MPConfig); - // We can't use sinon.useFakeTimers() because it will affect the async // nature of the tests, so we will just save a timestamp to compare for // later @@ -3241,7 +3267,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); let currentUser = mParticle.Identity.getCurrentUser(); currentUser.should.not.equal(null); @@ -3263,8 +3289,9 @@ describe('identity', function() { fetchMock.resetHistory(); mParticle.Identity.login(userIdentities1); + await waitForCondition(hasIdentityCallInflightReturned); - await waitForCondition(() => mParticle.Identity.getCurrentUser().getMPID() === 'MPID1') + await waitForCondition(() => mParticle.Identity.getCurrentUser().getMPID() === 'MPID1'); const nowAfterLogin = new Date(); @@ -3291,8 +3318,9 @@ describe('identity', function() { fetchMock.resetHistory(); mParticle.Identity.login(); + await waitForCondition(hasIdentityCallInflightReturned); - await waitForCondition(() => mParticle.Identity.getCurrentUser().getMPID() === testMPID) + await waitForCondition(() => mParticle.Identity.getCurrentUser().getMPID() === testMPID); currentUser = mParticle.Identity.getCurrentUser(); expect(currentUser.getMPID()).to.equal(testMPID); @@ -3301,8 +3329,6 @@ describe('identity', function() { }); it('list returned by Identity.getUsers() should be sorted by lastSeenTime, with nulls last', async () => { - mParticle._resetForTests(MPConfig); - const cookies = JSON.stringify({ gs: { sid: 'fst Test', @@ -3342,7 +3368,6 @@ describe('identity', function() { it('does not error when simultaneous identity calls are out', async () => { const errorMessages = []; - mParticle._resetForTests(MPConfig); mParticle.config.logger = { error: function(msg) { errorMessages.push(msg); @@ -3360,8 +3385,6 @@ describe('identity', function() { }); it('Startup identity callback should include getPreviousUser()', async () => { - mParticle._resetForTests(MPConfig); - const cookies = JSON.stringify({ gs: { sid: 'test', @@ -3387,7 +3410,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); expect(identityResult.getUser().getMPID()).to.equal('testMPID'); expect(identityResult.getPreviousUser()).to.not.equal(null); @@ -3396,9 +3419,7 @@ describe('identity', function() { ); }); - it('Identity callback should include getPreviousUser()', async () => { - mParticle._resetForTests(MPConfig); - + it('Identity callback should include getPreviousUser()', async () => { const cookies = JSON.stringify({ testMPID: { lst: 200, @@ -3413,7 +3434,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); fetchMockSuccess(urls.login, { mpid: testMPID, @@ -3436,10 +3457,9 @@ describe('identity', function() { }); it('should return the correct user for Previous User', async () => { - mParticle._resetForTests(MPConfig); let callbackCalled = false; - await waitForCondition(hasBeforeEachCallbackReturned) + await waitForCondition(hasBeforeEachCallbackReturned); const cookies = JSON.stringify({ gs: { @@ -3475,14 +3495,14 @@ describe('identity', function() { let identityResult; - await waitForCondition(() => mParticle.Identity.getCurrentUser()?.getMPID() === '1') + await waitForCondition(() => mParticle.Identity.getCurrentUser()?.getMPID() === '1'); mParticle.Identity.identify(EmptyUserIdentities, function(result) { identityResult = result; callbackCalled = true; }); - await waitForCondition(() => callbackCalled) + await waitForCondition(() => callbackCalled); identityResult .getUser() .getMPID() @@ -3716,8 +3736,6 @@ describe('identity', function() { }); it('should properly create AliasRequest', async () => { - mParticle._resetForTests(MPConfig); - const cookies = JSON.stringify({ gs: { sid: 'fst Test', @@ -3734,7 +3752,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); // Mock clock so we can use simple integers for time clock = sinon.useFakeTimers(); @@ -3755,8 +3773,6 @@ describe('identity', function() { }); it('should fill in missing fst and lst in createAliasRequest', async () => { - mParticle._resetForTests(MPConfig); - const cookies = JSON.stringify({ gs: { sid: 'fst Test', @@ -3773,7 +3789,7 @@ describe('identity', function() { setCookie(workspaceCookieName, cookies); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); // Mock clock so we can use simple integers for time clock = sinon.useFakeTimers(); @@ -3797,8 +3813,6 @@ describe('identity', function() { }); it('should fix startTime when default is outside max window create AliasRequest', async () => { - mParticle._resetForTests(MPConfig); - const millisPerDay = 24 * 60 * 60 * 1000; const cookies = JSON.stringify({ gs: { @@ -3818,7 +3832,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); clock = sinon.useFakeTimers(); clock.tick(millisPerDay * 2); @@ -3872,7 +3886,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); // Mock clock so we can use simple integers for time clock = sinon.useFakeTimers(); @@ -3903,7 +3917,6 @@ describe('identity', function() { }); it("alias request should have environment 'development' when isDevelopmentMode is true", async () => { - mParticle._resetForTests(MPConfig); window.mParticle.config.isDevelopmentMode = true; fetchMock.post(urls.alias, HTTP_ACCEPTED); @@ -3928,11 +3941,9 @@ describe('identity', function() { }); it('should set isFirtRun to false after an app is initialized', async () => { - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._Store.isFirstRun.should.equal(false); @@ -3943,15 +3954,13 @@ describe('identity', function() { mParticle.Identity.login({ userIdentities: { customerid: 'abc' } }); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); const ls = mParticle.getInstance()._Persistence.getLocalStorage(); ls['testMPID'].lst.should.not.equal(null); }); it('should send back an httpCode of -1 when there is a no coverage (http code returns 0)', async () => { - mParticle._resetForTests(MPConfig); - let result; function identityCallback(response) { @@ -3969,7 +3978,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); result.httpCode.should.equal(-1); @@ -3981,15 +3990,13 @@ describe('identity', function() { }); it('should use the custom device id in known_identities when passed via setDeviceId', async () => { - mParticle._resetForTests(MPConfig); - fetchMockSuccess(urls.identify, { body: null }); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); expect(fetchMock.calls().length).to.equal(1); const firstCall = fetchMock.calls()[0]; expect(firstCall[0].split('/')[4]).to.equal('identify'); @@ -4007,7 +4014,7 @@ describe('identity', function() { mParticle.Identity.login({ userIdentities: { customerid: 'test' } }); - await waitForCondition(hasLoginReturned) + await waitForCondition(hasLoginReturned); // Should include two more calls: Login and UIC expect(fetchMock.calls().length).to.equal(2); @@ -4019,8 +4026,6 @@ describe('identity', function() { }); it('should use the custom device id in known_identities when set via mParticle.config', async () => { - mParticle._resetForTests(MPConfig); - // Resets fetchMock so we can isolate calls for this tests fetchMock.restore(); @@ -4050,10 +4055,9 @@ describe('identity', function() { // Set the Max Age to be 1 second in the future for testing const X_MP_MAX_AGE = '1'; - mParticle._resetForTests(MPConfig); fetchMock.resetHistory(); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); fetchMockSuccess( urls.identify, { @@ -4082,7 +4086,7 @@ describe('identity', function() { mParticle.Identity.getCurrentUser()?.getUserIdentities() ?.userIdentities?.email === 'test@gmail.com' ); - }) + }); const now = new Date(); const idCache: IdentityCache = JSON.parse( localStorage.getItem('mprtcl-v4_abcdef-id-cache') @@ -4113,7 +4117,6 @@ describe('identity', function() { it('should not call identify if no identities have changed within the expiration time', async () => { const X_MP_MAX_AGE = '1'; - mParticle._resetForTests(MPConfig); fetchMockSuccess(urls.identify, { mpid: testMPID, @@ -4136,7 +4139,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); // Just make sure calls were actually made expect(fetchMock.calls().length).to.greaterThanOrEqual(1); @@ -4148,7 +4151,7 @@ describe('identity', function() { const callback = sinon.spy(); mParticle.Identity.identify(identities, callback); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); expect(fetchMock.calls().length).to.equal(0); // callback still gets called even if the identity call is not made` @@ -4160,8 +4163,6 @@ describe('identity', function() { let callbackCalled = false; - mParticle._resetForTests(MPConfig); - fetchMockSuccess(urls.identify, { mpid: testMPID, is_logged_in: false, @@ -4182,7 +4183,7 @@ describe('identity', function() { mParticle.config.flags.cacheIdentity = 'True'; mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); const initialIdentityCall = fetchMock.calls()[0]; expect(initialIdentityCall[0].split('/')[4]).to.equal('identify'); @@ -4201,7 +4202,7 @@ describe('identity', function() { clock.restore(); - await waitForCondition(() => callbackCalled) + await waitForCondition(() => callbackCalled); expect(fetchMock.calls().length).to.equal(1); const duplicateIdentityCall = fetchMock.calls()[0]; @@ -4215,8 +4216,6 @@ describe('identity', function() { let callbackCalled = false; - mParticle._resetForTests(MPConfig); - fetchMockSuccess(urls.identify, { mpid: testMPID, is_logged_in: true, @@ -4244,7 +4243,7 @@ describe('identity', function() { mParticle.config.flags.cacheIdentity = 'True'; mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); fetchMock.resetHistory(); @@ -4253,8 +4252,9 @@ describe('identity', function() { }; mParticle.Identity.login(identities, callback); + await waitForCondition(hasIdentityCallInflightReturned); - await waitForCondition(() => mParticle.Identity?.getCurrentUser()?.getMPID() === testMPID) + await waitForCondition(() => mParticle.Identity?.getCurrentUser()?.getMPID() === testMPID); // Just make sure calls were actually made expect(fetchMock.calls().length).to.greaterThanOrEqual(1); @@ -4269,7 +4269,7 @@ describe('identity', function() { await waitForCondition(() => { return callbackCalled; - }) + }); expect(fetchMock.calls().length).to.equal(0); @@ -4282,8 +4282,6 @@ describe('identity', function() { let callbackCalled = false; - mParticle._resetForTests(MPConfig); - fetchMockSuccess(urls.identify, { mpid: testMPID, is_logged_in: true, @@ -4312,7 +4310,7 @@ describe('identity', function() { mParticle.config.flags.cacheIdentity = 'True'; mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); const initialIdentityCall = fetchMock.calls()[0]; expect(initialIdentityCall[0].split('/')[4]).to.equal('identify'); @@ -4325,7 +4323,7 @@ describe('identity', function() { mParticle.Identity.login(identities, callback); - await waitForCondition(() => callbackCalled) + await waitForCondition(() => callbackCalled); // Just make sure calls were actually made expect(fetchMock.calls().length).to.greaterThanOrEqual(1); @@ -4344,7 +4342,7 @@ describe('identity', function() { clock.restore(); - await waitForCondition(() => callbackCalled) + await waitForCondition(() => callbackCalled); expect(fetchMock.calls().length).to.equal(1); const secondLoginCall = fetchMock.calls()[0]; @@ -4355,7 +4353,6 @@ describe('identity', function() { it('should clear cache when modify is called', async () => { const X_MP_MAX_AGE = '1'; - mParticle._resetForTests(MPConfig); fetchMockSuccess(urls.identify, { mpid: testMPID, @@ -4389,7 +4386,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); const idCache = localStorage.getItem('mprtcl-v4_abcdef-id-cache'); expect(idCache).to.be.ok; @@ -4400,7 +4397,7 @@ describe('identity', function() { }, }); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); const secondIdCache = localStorage.getItem( 'mprtcl-v4_abcdef-id-cache' ); @@ -4410,7 +4407,6 @@ describe('identity', function() { it('should clear cache when logout is called', async () => { const X_MP_MAX_AGE = '1'; - mParticle._resetForTests(MPConfig); fetchMockSuccess(urls.identify, { mpid: testMPID, @@ -4440,14 +4436,14 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); let idCache = localStorage.getItem('mprtcl-v4_abcdef-id-cache'); expect(idCache).to.be.ok; mParticle.Identity.logout(); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); let secondIdCache = localStorage.getItem( 'mprtcl-v4_abcdef-id-cache' @@ -4463,7 +4459,6 @@ describe('identity', function() { const testRoktMPID = 'rokt-user'; beforeEach(function() { - mParticle._resetForTests(MPConfig); fetchMock.resetHistory(); roktConfig = { @@ -4482,6 +4477,9 @@ describe('identity', function() { }); it('should set currentUser once the email is positively identified', async () => { + await waitForCondition(hasIdentityCallInflightReturned); + mParticle._resetForTests(MPConfig); + loggerSpy = setupLoggerSpy(); fetchMockSuccess(urls.identify, { mpid: testRoktMPID, is_logged_in: false, @@ -4492,19 +4490,21 @@ describe('identity', function() { mParticle.init(apiKey, { ...window.mParticle.config, kitConfigs: [roktConfig] }); - await waitForCondition(() => hasIdentifyReturned(testRoktMPID)); + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); const mpInstance = mParticle.getInstance(); mpInstance._RoktManager.attachKit(roktKit); + fetchMock.resetHistory(); + loggerSpy.verbose.resetHistory(); mParticle.Identity.identify({ userIdentities: { email: testRoktEmail, }, }); - await waitForCondition(() => hasIdentifyReturnedWithEmail(testRoktEmail)); + await waitForCondition(hasIdentityResponseParsed(loggerSpy)); expect(mpInstance._RoktManager['currentUser']).to.not.be.null; expect(mpInstance._RoktManager['currentUser'].getUserIdentities().userIdentities.email).to.equal(testRoktEmail); @@ -4530,7 +4530,7 @@ describe('identity', function() { mParticle.init(apiKey, { ...window.mParticle.config, kitConfigs: [roktConfig] }); - await waitForCondition(hasIdentityCallInflightReturned); + await waitForCondition(hasIdentityCallInflightReturned); const mpInstance = mParticle.getInstance(); @@ -4600,7 +4600,7 @@ describe('identity', function() { it("should deprecate the user's cart", async () => { mParticle.init(apiKey, window.mParticle.config); const bond = sinon.spy(mParticle.getInstance().Logger, 'warning'); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); mParticle .getInstance() .Identity.getCurrentUser() @@ -4619,7 +4619,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); const bond = sinon.spy(mParticle.getInstance().Logger, 'warning'); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); const product: SDKProduct = mParticle.eCommerce.createProduct( 'iPhone', @@ -4648,7 +4648,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); const bond = sinon.spy(mParticle.getInstance().Logger, 'warning'); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); const product: SDKProduct = mParticle.eCommerce.createProduct( 'iPhone', @@ -4676,7 +4676,7 @@ describe('identity', function() { it('should deprecate clear', async () => { mParticle.init(apiKey, window.mParticle.config); const bond = sinon.spy(mParticle.getInstance().Logger, 'warning'); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); mParticle .getInstance() .Identity.getCurrentUser() @@ -4699,7 +4699,7 @@ describe('identity', function() { mParticle.init(apiKey, window.mParticle.config); const bond = sinon.spy(mParticle.getInstance().Logger, 'warning'); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); mParticle .getInstance() diff --git a/test/src/tests-identityApiClient.ts b/test/src/tests-identityApiClient.ts index 9b7247972..4dc5f2550 100644 --- a/test/src/tests-identityApiClient.ts +++ b/test/src/tests-identityApiClient.ts @@ -32,7 +32,7 @@ declare global { const mParticle = window.mParticle; -describe('Identity Api Client', () => { +describe.only('Identity Api Client', () => { describe('#sendIdentityRequest', () => { const identityRequest: IIdentityAPIRequestData = { client_sdk: { @@ -690,13 +690,15 @@ describe('Identity Api Client', () => { const aliasUrl = 'https://jssdks.mparticle.com/v1/identity/test_key/Alias'; beforeEach(function() { + mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; fetchMockSuccess(urls.events); mParticle.init(apiKey, window.mParticle.config); }); afterEach(function() { fetchMock.restore(); - mParticle._resetForTests(MPConfig); + sinon.restore(); }); it('should have just an httpCode on the result passed to the callback on a 200', async () => {