diff --git a/test/src/config/utils.js b/test/src/config/utils.js index 2580710a..1f48146f 100644 --- a/test/src/config/utils.js +++ b/test/src/config/utils.js @@ -10,6 +10,8 @@ import { das, } from './constants'; import fetchMock from 'fetch-mock/esm/client'; +import sinon from 'sinon'; +import { expect } from 'chai'; var pluses = /\+/g, decoded = function decoded(s) { @@ -624,7 +626,50 @@ var pluses = /\+/g, return window.mParticle.Identity.getCurrentUser()?.getMPID() === _mpid; }, hasIdentityCallInflightReturned = () => !mParticle.getInstance()?._Store?.identityCallInFlight, - hasConfigurationReturned = () => !!mParticle.getInstance()?._Store?.configurationLoaded; + 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; + + const blob = beaconCall.args[1]; + expect(blob).to.be.instanceof(Blob); + + const reader = new FileReader(); + const blobContent = await new Promise((resolve) => { + reader.onload = () => resolve(reader.result); + reader.readAsText(blob); + }); + + return JSON.parse(blobContent); + }, + setupFakeTimers = function(now) { + return sinon.useFakeTimers({ + now: now || Date.now(), + shouldAdvanceTime: true + }); + }, + triggerVisibilityHidden = function() { + Object.defineProperty(document, 'visibilityState', { + configurable: true, + get: () => 'hidden' + }); + document.dispatchEvent(new Event('visibilitychange')); + }; var TestsCore = { findCookie: findCookie, @@ -651,8 +696,13 @@ var TestsCore = { waitForCondition: waitForCondition, fetchMockSuccess: fetchMockSuccess, hasIdentifyReturned: hasIdentifyReturned, + 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-apiClient.ts b/test/src/tests-apiClient.ts index 614045fb..6082dc93 100644 --- a/test/src/tests-apiClient.ts +++ b/test/src/tests-apiClient.ts @@ -14,14 +14,11 @@ const mParticle = window.mParticle; describe('Api Client', () => { beforeEach(() => { - mParticle.init(apiKey, mParticle.config); - }); - - afterEach(() => { mParticle._resetForTests(MPConfig); + mParticle.init(apiKey, mParticle.config); }); - it('should update queued events with latest user info', done => { + it('should update queued events with latest user info', () => { const event = { messageType: Types.MessageType.PageEvent, name: 'foo page', @@ -30,10 +27,11 @@ describe('Api Client', () => { customFlags: { 'foo-flag': 'foo-flag-val' }, }; - expect(mParticle.getInstance()._Store).to.be.ok; - let sdkEvent1 = mParticle - .getInstance() - ._ServerModel.createEventObject(event); + const mpInstance = mParticle.getInstance(); + expect(mpInstance._Store).to.be.ok; + + const sdkEvent1 = mpInstance._ServerModel.createEventObject(event); + const sdkEvent2 = mpInstance._ServerModel.createEventObject(event); expect(sdkEvent1).to.be.ok; expect(sdkEvent1.MPID).equal(null); @@ -41,70 +39,48 @@ describe('Api Client', () => { expect(sdkEvent1.UserIdentities).equal(null); expect(sdkEvent1.ConsentState).equal(null); - let sdkEvent2 = mParticle - .getInstance() - ._ServerModel.createEventObject(event); - expect(sdkEvent2).to.be.ok; expect(sdkEvent2.MPID).equal(null); expect(sdkEvent2.UserAttributes).equal(null); expect(sdkEvent2.UserIdentities).equal(null); expect(sdkEvent2.ConsentState).equal(null); - const consentState = mParticle - .getInstance() - .Consent.createConsentState(); + const consentState = mpInstance.Consent.createConsentState(); consentState.addGDPRConsentState( 'foo', - mParticle - .getInstance() - .Consent.createGDPRConsent( - true, - 10, - 'foo document', - 'foo location', - 'foo hardware id' - ) + mpInstance.Consent.createGDPRConsent( + true, + 10, + 'foo document', + 'foo location', + 'foo hardware id' + ) ); - mParticle.getInstance().Identity.getCurrentUser = () => { - return { - getUserIdentities: () => { - return { - userIdentities: { - customerid: '1234567', - email: 'foo-email', - other: 'foo-other', - other2: 'foo-other2', - other3: 'foo-other3', - other4: 'foo-other4', - }, - }; - }, - getAllUserAttributes: () => { - return { - 'foo-user-attr': 'foo-attr-value', - 'foo-user-attr-list': ['item1', 'item2'], - }; + const mockUser = { + getUserIdentities: () => ({ + userIdentities: { + customerid: '1234567', + email: 'foo-email', + other: 'foo-other', + other2: 'foo-other2', + other3: 'foo-other3', + other4: 'foo-other4', }, - getMPID: () => { - return '98765'; - }, - getConsentState: () => { - return consentState; - }, - } as IMParticleUser; - }; + }), + getAllUserAttributes: () => ({ + 'foo-user-attr': 'foo-attr-value', + 'foo-user-attr-list': ['item1', 'item2'], + }), + getMPID: () => '98765', + getConsentState: () => consentState, + } as IMParticleUser; - mParticle - .getInstance() - ._APIClient.appendUserInfoToEvents( - mParticle.Identity.getCurrentUser(), - [sdkEvent1, sdkEvent2] - ); + + mpInstance._APIClient.appendUserInfoToEvents(mockUser, [sdkEvent1, sdkEvent2]); expect(sdkEvent1.UserIdentities.length).to.equal(6); - expect(Object.keys(sdkEvent2.UserAttributes).length).to.equal(2); + expect(Object.keys(sdkEvent1.UserAttributes).length).to.equal(2); expect(sdkEvent1.MPID).to.equal('98765'); expect(sdkEvent1.ConsentState).to.not.equal(null); @@ -112,7 +88,5 @@ describe('Api Client', () => { expect(Object.keys(sdkEvent2.UserAttributes).length).to.equal(2); expect(sdkEvent2.MPID).to.equal('98765'); expect(sdkEvent2.ConsentState).to.not.equal(null); - - done(); }); }); \ No newline at end of file diff --git a/test/src/tests-audience-manager.ts b/test/src/tests-audience-manager.ts index c7302bd6..9bee9a8e 100644 --- a/test/src/tests-audience-manager.ts +++ b/test/src/tests-audience-manager.ts @@ -1,7 +1,7 @@ import sinon from 'sinon'; import fetchMock from 'fetch-mock/esm/client'; import { expect } from 'chai'; -import { urls, apiKey, testMPID } from './config/constants'; +import { urls, apiKey, testMPID, MPConfig } from './config/constants'; import Constants from '../../src/constants'; import { IMParticleInstanceManager, SDKLoggerApi } from '../../src/sdkRuntimeModels'; import AudienceManager, { @@ -21,21 +21,11 @@ declare global { const userAudienceUrl = `https://${Constants.DefaultBaseUrls.userAudienceUrl}${apiKey}/audience`; describe('AudienceManager', () => { - before(function() { - fetchMock.restore(); - sinon.restore(); - }); - - beforeEach(function() { - fetchMock.restore(); - + beforeEach(() => { + window.mParticle._resetForTests(MPConfig); fetchMockSuccess(urls.identify, { mpid: testMPID, is_logged_in: false }); - - window.mParticle.config.flags = { - eventBatchingIntervalMillis: 1000, - }; }); afterEach(() => { @@ -59,12 +49,16 @@ describe('AudienceManager', () => { }); describe('#sendGetUserAudienceRequest', () => { - const newLogger = new Logger(window.mParticle.config); - const audienceManager = new AudienceManager( - Constants.DefaultBaseUrls.userAudienceUrl, - apiKey, - newLogger - ); + let newLogger: SDKLoggerApi; + let audienceManager: AudienceManager; + beforeEach(() => { + newLogger = new Logger(window.mParticle.config); + audienceManager = new AudienceManager( + Constants.DefaultBaseUrls.userAudienceUrl, + apiKey, + newLogger + ); + }); const audienceMembershipServerResponse: IAudienceMembershipsServerResponse = { ct: 1710441407914, @@ -135,15 +129,15 @@ describe('AudienceManager', () => { }; const expectedAudienceMembership2: IAudienceMemberships = { - currentAudienceMemberships: [ - { - audience_id: 9876, - }, - { - audience_id: 5432, - }, - ] - }; + currentAudienceMemberships: [ + { + audience_id: 9876, + }, + { + audience_id: 5432, + }, + ] + }; fetchMock.get(newMPIDAudienceEndpoint, { status: 200, diff --git a/test/src/tests-batchUploader.ts b/test/src/tests-batchUploader.ts index 64106060..37e3d1c5 100644 --- a/test/src/tests-batchUploader.ts +++ b/test/src/tests-batchUploader.ts @@ -13,7 +13,14 @@ import _BatchValidator from '../../src/mockBatchCreator'; import Logger from '../../src/logger.js'; import { event0, event1, event2, event3 } from '../fixtures/events'; import fetchMock from 'fetch-mock/esm/client'; -const { fetchMockSuccess, waitForCondition, hasIdentifyReturned } = Utils; +const { + fetchMockSuccess, + waitForCondition, + hasIdentifyReturned, + getBeaconBatch, + setupFakeTimers, + triggerVisibilityHidden +} = Utils; declare global { interface Window { @@ -29,7 +36,7 @@ describe('batch uploader', () => { let clock; let beaconSpy; beforeEach(() => { - fetchMock.restore(); + window.mParticle._resetForTests(MPConfig); fetchMock.config.overwriteRoutes = true; fetchMockSuccess(urls.identify, { mpid: testMPID, @@ -42,85 +49,46 @@ describe('batch uploader', () => { }); afterEach(() => { + beaconSpy?.restore(); + sinon.restore(); fetchMock.restore(); window.localStorage.clear(); + window.sessionStorage.clear(); }); // https://go.mparticle.com/work/ describe('AST background events fired during page events', () => { describe('should not fire AST background events if flag is astBackgroundEvents "False"', () => { beforeEach(() => { + clock = setupFakeTimers(); window.mParticle.config.flags.astBackgroundEvents = "False" }); + afterEach(() => { - delete window.mParticle.config.flags.astBackgroundEvents; - if (clock) { - clock.restore(); - } - if (beaconSpy) { - beaconSpy.restore(); - } + clock.restore(); }); it('should not have an AST of background event when visibility changes', async () => { window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); - - const now = Date.now(); - clock = sinon.useFakeTimers({ - now: now, - shouldAdvanceTime: true - }); - // Add a regular event first to ensure we have something in the queue window.mParticle.logEvent('Test Event'); // Mock navigator.sendBeacon beaconSpy = sinon.spy(navigator, 'sendBeacon'); - // Trigger visibility change - Object.defineProperty(document, 'visibilityState', { - configurable: true, - get: () => 'hidden' - }); - document.dispatchEvent(new Event('visibilitychange')); - - // Run all pending promises - await Promise.resolve(); + triggerVisibilityHidden(); // Verify that beacon was called expect(beaconSpy.calledOnce, 'Expected beacon to be called once').to.be.true; - // Get the beacon call data - const beaconCall = beaconSpy.getCall(0); - expect(beaconCall, 'Expected beacon call to exist').to.exist; - - // Get the Blob from the beacon call - const blob = beaconCall.args[1]; - expect(blob).to.be.instanceof(Blob); - - // Read the Blob content - const reader = new FileReader(); - const blobContent = await new Promise((resolve) => { - reader.onload = () => resolve(reader.result); - reader.readAsText(blob); - }); - // Parse the beacon data which is a batch - const batch = JSON.parse(blobContent as string); + const batch = await getBeaconBatch(beaconSpy); expect(batch.events, 'Expected beacon data to have events').to.exist; - expect(batch.events.length, 'Expected beacon data to have at least one event').to.equal(3); - const event1 = batch.events[0]; - const event2 = batch.events[1]; - const event3 = batch.events[2]; - - console.log(event1.event_type); - console.log(event1.event_type); - console.log(event1.event_type); - console.log(event1.event_type); + expect(batch.events.length, 'Expected beacon data to have at least one event').to.equal(3); + const [event1, event2, event3] = batch.events; expect(event1.event_type).to.equal('session_start'); - expect(event2.event_type).to.equal('application_state_transition'); expect(event2.event_type).to.equal('application_state_transition'); expect(event2.data.application_transition_type).to.equal('application_initialized'); expect(event3.event_type).to.equal('custom_event'); @@ -130,64 +98,28 @@ describe('batch uploader', () => { describe('should fire AST background events if flag is astBackgroundEvents "True"', () => { beforeEach(() => { window.mParticle.config.flags.astBackgroundEvents = "True" + clock = setupFakeTimers(); }); afterEach(() => { - delete window.mParticle.config.flags.astBackgroundEvents; - if (clock) { - clock.restore(); - } - if (beaconSpy) { - beaconSpy.restore(); - } + clock.restore(); }); it('should add application state transition event when visibility changes to hidden', async () => { window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); - - const now = Date.now(); - clock = sinon.useFakeTimers({ - now: now, - shouldAdvanceTime: true - }); - // Add a regular event first to ensure we have something in the queue window.mParticle.logEvent('Test Event'); - // Mock navigator.sendBeacon beaconSpy = sinon.spy(navigator, 'sendBeacon'); - // Trigger visibility change - Object.defineProperty(document, 'visibilityState', { - configurable: true, - get: () => 'hidden' - }); - document.dispatchEvent(new Event('visibilitychange')); - - // Run all pending promises - await Promise.resolve(); + triggerVisibilityHidden(); // Verify that beacon was called expect(beaconSpy.calledOnce, 'Expected beacon to be called once').to.be.true; - // Get the beacon call data - const beaconCall = beaconSpy.getCall(0); - expect(beaconCall, 'Expected beacon call to exist').to.exist; - - // Get the Blob from the beacon call - const blob = beaconCall.args[1]; - expect(blob).to.be.instanceof(Blob); - - // Read the Blob content - const reader = new FileReader(); - const blobContent = await new Promise((resolve) => { - reader.onload = () => resolve(reader.result); - reader.readAsText(blob); - }); - // Parse the beacon data which is a batch - const batch = JSON.parse(blobContent as string); + const batch = await getBeaconBatch(beaconSpy); expect(batch.events, 'Expected beacon data to have events').to.exist; expect(batch.events.length, 'Expected beacon data to have at least one event').to.be.greaterThan(0); @@ -204,12 +136,6 @@ describe('batch uploader', () => { window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); - const now = Date.now(); - clock = sinon.useFakeTimers({ - now: now, - shouldAdvanceTime: true - }); - // Log a regular event window.mParticle.logEvent('Test Event'); @@ -228,30 +154,13 @@ describe('batch uploader', () => { const pagehideEvent = new Event('pagehide', { cancelable: true }); window.dispatchEvent(pagehideEvent); - // Run all pending promises - await Promise.resolve(); clock.runAll(); // Verify that beacon was called expect(beaconSpy.calledOnce, 'Expected beacon to be called once').to.be.true; - // Get the beacon call data - const beaconCall = beaconSpy.getCall(0); - expect(beaconCall, 'Expected beacon call to exist').to.exist; - - // Get the Blob from the beacon call - const blob = beaconCall.args[1]; - expect(blob).to.be.instanceof(Blob); - - // Read the Blob content - const reader = new FileReader(); - const blobContent = await new Promise((resolve) => { - reader.onload = () => resolve(reader.result); - reader.readAsText(blob); - }); - // Parse the beacon data which is a batch - const batch = JSON.parse(blobContent as string); + const batch = await getBeaconBatch(beaconSpy); const events = batch.events; // The application state transition event should be the last event @@ -298,46 +207,19 @@ describe('batch uploader', () => { const user = window.mParticle.Identity.getCurrentUser(); user.setConsentState(consentState); - const now = Date.now(); - clock = sinon.useFakeTimers({ - now: now, - shouldAdvanceTime: true - }); - // Mock navigator.sendBeacon beaconSpy = sinon.spy(navigator, 'sendBeacon'); // Trigger visibility change - Object.defineProperty(document, 'visibilityState', { - configurable: true, - get: () => 'hidden' - }); - document.dispatchEvent(new Event('visibilitychange')); + triggerVisibilityHidden(); - // Run all pending promises - await Promise.resolve(); clock.runAll(); // Verify that beacon was called expect(beaconSpy.calledOnce, 'Expected beacon to be called once').to.be.true; - // Get the beacon call data - const beaconCall = beaconSpy.getCall(0); - expect(beaconCall, 'Expected beacon call to exist').to.exist; - - // Get the Blob from the beacon call - const blob = beaconCall.args[1]; - expect(blob).to.be.instanceof(Blob); - - // Read the Blob content - const reader = new FileReader(); - const blobContent = await new Promise((resolve) => { - reader.onload = () => resolve(reader.result); - reader.readAsText(blob); - }); - // Parse the beacon data which is a batch - const batch = JSON.parse(blobContent as string); + const batch = await getBeaconBatch(beaconSpy); expect(batch.user_identities.email).to.equal('test@test.com'); expect(batch.user_attributes.foo).to.equal('value'); expect(batch.application_info.application_name).to.equal('Test App'); @@ -417,46 +299,18 @@ describe('batch uploader', () => { const user = window.mParticle.Identity.getCurrentUser(); user.setConsentState(consentState); - const now = Date.now(); - clock = sinon.useFakeTimers({ - now: now, - shouldAdvanceTime: true - }); - // Mock navigator.sendBeacon beaconSpy = sinon.spy(navigator, 'sendBeacon'); // Trigger visibility change - Object.defineProperty(document, 'visibilityState', { - configurable: true, - get: () => 'hidden' - }); - document.dispatchEvent(new Event('visibilitychange')); - - // Run all pending promises - await Promise.resolve(); + triggerVisibilityHidden(); clock.runAll(); // Verify that beacon was called expect(beaconSpy.calledOnce, 'Expected beacon to be called once').to.be.true; - // Get the beacon call data - const beaconCall = beaconSpy.getCall(0); - expect(beaconCall, 'Expected beacon call to exist').to.exist; - - // Get the Blob from the beacon call - const blob = beaconCall.args[1]; - expect(blob).to.be.instanceof(Blob); - - // Read the Blob content - const reader = new FileReader(); - const blobContent = await new Promise((resolve) => { - reader.onload = () => resolve(reader.result); - reader.readAsText(blob); - }); - // Parse the beacon data which is a batch - const batch = JSON.parse(blobContent as string); + const batch = await getBeaconBatch(beaconSpy); expect(batch.user_identities.email).to.equal('test@test.com'); expect(batch.user_attributes.foo).to.equal('value'); expect(batch.application_info.application_name).to.equal('Test App'); @@ -500,82 +354,34 @@ describe('batch uploader', () => { }); describe('AST Debouncing events', () => { - beforeEach(async () => { - // Set up mParticle config with the feature flag enabled - window.mParticle.config = { - ...window.mParticle.config, - flags: { - ...window.mParticle.config.flags, - astBackgroundEvents: "True" - } - }; - await Promise.resolve() + beforeEach(() => { + window.mParticle.config.flags.astBackgroundEvents = "True"; + clock = setupFakeTimers(); }); afterEach(() => { - if (window.mParticle.config.flags) { - delete window.mParticle.config.flags.astBackgroundEvents; - } - if (clock) { - clock.restore(); - } - if (beaconSpy) { - beaconSpy.restore(); - } + clock.restore(); }); it('should only fire a single AST when another visibility event happens within the debounce time window', async () => { - window.mParticle._resetForTests(window.mParticle.config); - window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); - const now = Date.now(); - clock = sinon.useFakeTimers({ - now: now, - shouldAdvanceTime: true - }); - // Add a regular event first to ensure we have something in the queue window.mParticle.logEvent('Test Event'); - // Mock navigator.sendBeacon beaconSpy = sinon.spy(navigator, 'sendBeacon'); // Trigger visibility change - Object.defineProperty(document, 'visibilityState', { - configurable: true, - get: () => 'hidden' - }); - - document.dispatchEvent(new Event('visibilitychange')); - - // Run all pending promises - await Promise.resolve(); - // clock.runAll(); + triggerVisibilityHidden(); expect(beaconSpy.calledOnce, 'Expected beacon to be called once').to.be.true; - // Get the beacon call data - const beaconCall = beaconSpy.getCall(0); - expect(beaconCall, 'Expected beacon call to exist').to.exist; - - // Get the Blob from the beacon call - const blob = beaconCall.args[1]; - expect(blob).to.be.instanceof(Blob); - - // Read the Blob content - const reader = new FileReader(); - const blobContent = await new Promise((resolve) => { - reader.onload = () => resolve(reader.result); - reader.readAsText(blob); - }); - // Parse the beacon data which is a batch - const batch = JSON.parse(blobContent as string); - expect(batch.events, 'Expected beacon data to have events').to.exist; - expect(batch.events.length, 'Expected beacon data to have at least one event').to.be.greaterThan(0); + const batch = await getBeaconBatch(beaconSpy); + expect(batch.events).to.exist; + expect(batch.events.length).to.be.greaterThan(0); // Verify the AST event properties const lastEvent = batch.events[batch.events.length - 1]; @@ -586,60 +392,30 @@ describe('batch uploader', () => { clock.tick(500); document.dispatchEvent(new Event('visibilitychange')); - // Run all pending promises - await Promise.resolve(); - expect(beaconSpy.calledOnce, 'Expected beacon to be called twice').to.be.true; }); it('should fire multiple ASTs when another visibility event happens outside the debounce time window', async () => { + clock.restore(); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); - const now = Date.now(); - clock = sinon.useFakeTimers({ - now: now, - shouldAdvanceTime: true - }); - + clock = setupFakeTimers(); // Add a regular event first to ensure we have something in the queue window.mParticle.logEvent('Test Event'); - // Mock navigator.sendBeacon beaconSpy = sinon.spy(navigator, 'sendBeacon'); // Trigger visibility change - Object.defineProperty(document, 'visibilityState', { - configurable: true, - get: () => 'hidden' - }); - document.dispatchEvent(new Event('visibilitychange')); - - // Run all pending promises - await Promise.resolve(); + triggerVisibilityHidden(); // Verify that beacon was called expect(beaconSpy.calledOnce, 'Expected beacon to be called once').to.be.true; - // Get the beacon call data - const beaconCall = beaconSpy.getCall(0); - expect(beaconCall, 'Expected beacon call to exist').to.exist; - - // Get the Blob from the beacon call - const blob = beaconCall.args[1]; - expect(blob).to.be.instanceof(Blob); - - // Read the Blob content - const reader = new FileReader(); - const blobContent = await new Promise((resolve) => { - reader.onload = () => resolve(reader.result); - reader.readAsText(blob); - }); - // Parse the beacon data which is a batch - const batch = JSON.parse(blobContent as string); - expect(batch.events, 'Expected beacon data to have events').to.exist; - expect(batch.events.length, 'Expected beacon data to have at least one event').to.be.greaterThan(0); + const batch = await getBeaconBatch(beaconSpy); + expect(batch.events).to.exist; + expect(batch.events.length).to.be.greaterThan(0); // Verify the AST event properties const lastEvent = batch.events[batch.events.length - 1]; @@ -647,14 +423,9 @@ describe('batch uploader', () => { expect(lastEvent.event_type).to.equal('application_state_transition'); expect(lastEvent.data.application_transition_type).to.equal('application_background'); - expect(beaconSpy.calledOnce, 'Expected beacon to be called once').to.be.true; - // Clean up clock.tick(1500); document.dispatchEvent(new Event('visibilitychange')); - // Run all pending promises - await Promise.resolve(); - expect(beaconSpy.calledTwice, 'Expected beacon to be called twice').to.be.true; }); }) @@ -662,7 +433,6 @@ describe('batch uploader', () => { describe('Unit Tests', () => { describe('#queueEvent', () => { it('should add events to the Pending Events Queue', async () => { - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -700,8 +470,6 @@ describe('batch uploader', () => { }); it('should reject batches without events', async () => { - window.mParticle._resetForTests(MPConfig); - window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -717,7 +485,6 @@ describe('batch uploader', () => { }); it('should add events in the order they are received', async () => { - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -990,24 +757,10 @@ describe('batch uploader', () => { }); describe('Offline Storage Feature Flag', () => { - beforeEach(() => { - fetchMockSuccess(urls.identify, { - mpid: testMPID, - is_logged_in: false, - }); - - window.sessionStorage.clear(); - }); - afterEach(() => { - sinon.restore(); - }); - it('should use local storage when enabled', async () => { window.mParticle.config.flags = { offlineStorage: '100', }; - window.mParticle._resetForTests(MPConfig); - window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -1059,11 +812,6 @@ describe('batch uploader', () => { }); it('should not use local storage when disabled', async () => { - window.mParticle.config.flags = { - // offlineStorage: '0', // Defaults to 0, but test if not included, just in case - }; - - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -1125,7 +873,6 @@ describe('batch uploader', () => { const eventStorageKey = 'mprtcl-v4_abcdef-events'; const batchStorageKey = 'mprtcl-v4_abcdef-batches'; - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -1167,24 +914,11 @@ describe('batch uploader', () => { offlineStorage: '100', ...enableBatchingConfigFlags, }; - - fetchMockSuccess(urls.identify, { - mpid: testMPID, - is_logged_in: false, - }); - - window.sessionStorage.clear(); - window.localStorage.clear(); - }); - - afterEach(() => { - sinon.restore(); }); it('should store events in Session Storage in order of creation', async () => { const eventStorageKey = 'mprtcl-v4_abcdef-events'; - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -1220,7 +954,6 @@ describe('batch uploader', () => { fetchMock.post(urls.events, 200); - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -1253,7 +986,6 @@ describe('batch uploader', () => { // Batch Queue should be empty because batch successfully uploaded expect(uploader.batchesQueuedForProcessing.length).to.equal(0); - clock.restore(); }); it('should save batches in sequence to Local Storage when an HTTP 500 error is encountered', async () => { @@ -1261,7 +993,6 @@ describe('batch uploader', () => { fetchMock.post(urls.events, 500); - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -1313,7 +1044,6 @@ describe('batch uploader', () => { fetchMock.post(urls.events, 429); - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -1328,8 +1058,6 @@ describe('batch uploader', () => { // Manually initiate the upload process - turn event into batches and upload the batch await window.mParticle.getInstance()._APIClient.uploader.prepareAndUpload(); - clock.restore(); - expect(window.localStorage.getItem(batchStorageKey)).to.be.ok; const storedBatches: Batch[] = JSON.parse( @@ -1365,7 +1093,6 @@ describe('batch uploader', () => { fetchMock.post(urls.events, 401); - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -1408,7 +1135,6 @@ describe('batch uploader', () => { overwriteRoutes: false, }); // Set up SDK and Uploader - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); const mpInstance = window.mParticle.getInstance(); @@ -1507,15 +1233,8 @@ describe('batch uploader', () => { const batchStorageKey = 'mprtcl-v4_abcdef-batches'; - fetchMock.restore(); - fetchMockSuccess(urls.identify, { - mpid: testMPID, - is_logged_in: false, - }); - fetchMock.post(urls.events, 200); // Set up SDK and Uploader - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -1651,11 +1370,6 @@ describe('batch uploader', () => { describe('noFunctional', () => { const eventStorageKey = 'mprtcl-v4_abcdef-events'; const batchStorageKey = 'mprtcl-v4_abcdef-batches'; - beforeEach(() => { - window.mParticle._resetForTests(MPConfig); - window.localStorage.clear(); - window.sessionStorage.clear(); - }); it('should store batches in session storage when noFunctional is false by default', async () => { window.mParticle.config.flags = { diff --git a/test/src/tests-batchUploader_2.ts b/test/src/tests-batchUploader_2.ts index 5c32551e..69642a83 100644 --- a/test/src/tests-batchUploader_2.ts +++ b/test/src/tests-batchUploader_2.ts @@ -18,10 +18,9 @@ const enableBatchingConfigFlags = { }; describe('batch uploader', () => { - let mockServer; let clock; - beforeEach(() => { + window.mParticle._resetForTests(MPConfig); fetchMock.restore(); fetchMock.config.overwriteRoutes = true; fetchMockSuccess(urls.identify, { @@ -37,26 +36,16 @@ describe('batch uploader', () => { }); describe('Upload Workflow', () => { - beforeEach(() => { - }); - - afterEach(() => { - fetchMock.restore(); - }); it('should organize events in the order they are processed and maintain that order when uploading', async () => { // Batches should be uploaded in the order they were created to prevent // any potential corruption. - fetchMock.post(urls.events, 200); - fetchMock.config.overwriteRoutes = true; - window.mParticle.config.flags = { ...enableBatchingConfigFlags, }; - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); - + await waitForCondition(hasIdentifyReturned); window.mParticle.logEvent('Test Event 0'); @@ -123,7 +112,6 @@ describe('batch uploader', () => { ...enableBatchingConfigFlags, }; - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); // Generates Batch 1 with Session Start + AST @@ -222,7 +210,6 @@ describe('batch uploader', () => { ...enableBatchingConfigFlags, }; - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); // Generates Batch 1 with Session Start + AST diff --git a/test/src/tests-batchUploader_3.ts b/test/src/tests-batchUploader_3.ts index a7ef2202..ede678d6 100644 --- a/test/src/tests-batchUploader_3.ts +++ b/test/src/tests-batchUploader_3.ts @@ -14,6 +14,7 @@ declare global { describe('batch uploader', () => { beforeEach(() => { + window.mParticle._resetForTests(MPConfig); fetchMock.restore(); fetchMock.config.overwriteRoutes = true; fetchMockSuccess(urls.identify, { @@ -38,7 +39,6 @@ describe('batch uploader', () => { }); it('should use custom v3 endpoint', async () => { - window.mParticle._resetForTests(MPConfig); fetchMock.resetHistory(); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -59,7 +59,6 @@ describe('batch uploader', () => { }); it('should have latitude/longitude for location when batching', async () => { - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -75,7 +74,6 @@ describe('batch uploader', () => { }); it('should force uploads when using public `upload`', async () => { - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -100,9 +98,7 @@ describe('batch uploader', () => { }); it('should force uploads when a commerce event is called', async () => { - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned); window.mParticle.logEvent('Test Event'); @@ -124,8 +120,6 @@ describe('batch uploader', () => { }); it('should return pending uploads if a 500 is returned', async function() { - window.mParticle._resetForTests(MPConfig); - fetchMock.post(urls.events, 500); window.mParticle.init(apiKey, window.mParticle.config); @@ -157,9 +151,7 @@ describe('batch uploader', () => { }); it('should send source_message_id with events to v3 endpoint', async () => { - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned); window.mParticle.logEvent('Test Event'); @@ -175,7 +167,6 @@ describe('batch uploader', () => { }); it('should send user-defined SourceMessageId events to v3 endpoint', async () => { - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -207,9 +198,6 @@ describe('batch uploader', () => { // the previous session ID because the identity call back fired // before the session logic that determines if a new session should // start. - - window.mParticle._resetForTests(MPConfig); - window.mParticle.config.identityCallback = function(result) { let currentUser = result.getUser() if (currentUser) { diff --git a/test/src/tests-batchUploader_4.ts b/test/src/tests-batchUploader_4.ts index d8040ad9..91285de9 100644 --- a/test/src/tests-batchUploader_4.ts +++ b/test/src/tests-batchUploader_4.ts @@ -19,6 +19,7 @@ describe('batch uploader', () => { let mockServer; beforeEach(() => { + window.mParticle._resetForTests(MPConfig); fetchMock.restore(); fetchMock.config.overwriteRoutes = true; fetchMockSuccess(urls.identify, { @@ -57,13 +58,11 @@ describe('batch uploader', () => { }); afterEach(() => { - window.mParticle._resetForTests(MPConfig); window.fetch = fetch; sinon.restore(); }); it('should use custom v3 endpoint', async () => { - window.mParticle._resetForTests(MPConfig); mockServer.requests = []; window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -83,8 +82,6 @@ describe('batch uploader', () => { }); it('should force uploads when using public `upload`', async () => { - window.mParticle._resetForTests(MPConfig); - window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -106,8 +103,6 @@ describe('batch uploader', () => { }); it('should trigger an upload of batch when a commerce event is called', async () => { - window.mParticle._resetForTests(MPConfig); - window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -130,7 +125,6 @@ describe('batch uploader', () => { }); it('should trigger an upload of batch when a UIC occurs', async () => { - window.mParticle._resetForTests(MPConfig); // include an identify request so that it creates a UIC window.mParticle.config.identifyRequest = { userIdentities: { @@ -162,8 +156,6 @@ describe('batch uploader', () => { // Web SDK update // TODO: https://go.mparticle.com/work/SQDSDKS-5891 it('should NOT trigger an upload of batch when a UAC occurs', async () => { - window.mParticle._resetForTests(MPConfig); - window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -195,8 +187,6 @@ describe('batch uploader', () => { }); it('should return pending uploads if a 500 is returned', async () => { - window.mParticle._resetForTests(MPConfig); - mockServer.respondWith(urls.events, [ 500, {}, @@ -204,7 +194,6 @@ describe('batch uploader', () => { ]); window.mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned); window.mParticle.logEvent('Test Event'); @@ -229,8 +218,6 @@ describe('batch uploader', () => { }); it('should add a modified boolean of true to a batch that has been modified via a config.onCreateBatch call', async () => { - window.mParticle._resetForTests(MPConfig); - window.mParticle.config.onCreateBatch = function (batch: Batch) { return batch }; @@ -247,8 +234,6 @@ describe('batch uploader', () => { }); it('should respect rules for the batch modification', async () => { - window.mParticle._resetForTests(MPConfig); - window.mParticle.config.onCreateBatch = function (batch) { batch.events.map(event => { if (event.event_type === "custom_event") { @@ -259,7 +244,6 @@ describe('batch uploader', () => { }; window.mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned); window.mParticle.logEvent('Test Event'); @@ -275,14 +259,11 @@ describe('batch uploader', () => { }); it('should add a modified boolean of true to a batch that has been modified via a config.onCreateBatch call', async () => { - window.mParticle._resetForTests(MPConfig); - window.mParticle.config.onCreateBatch = function (batch: Batch) { return undefined; }; window.mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned); window.mParticle.logEvent('Test Event'); diff --git a/test/src/tests-beaconUpload.ts b/test/src/tests-beaconUpload.ts index 5fb33d6e..4c6d765b 100644 --- a/test/src/tests-beaconUpload.ts +++ b/test/src/tests-beaconUpload.ts @@ -7,7 +7,7 @@ import { batch1, batch2, batch3 } from '../fixtures/batches'; import _BatchValidator from '../../src/mockBatchCreator'; import Utils from './config/utils'; import { IMParticleInstanceManager } from '../../src/sdkRuntimeModels'; -const { findEventFromRequest, findBatch, waitForCondition, fetchMockSuccess, hasIdentifyReturned } = Utils; +const { waitForCondition, fetchMockSuccess, hasIdentifyReturned, triggerVisibilityHidden } = Utils; declare global { interface Window { @@ -22,13 +22,10 @@ const enableBatchingConfigFlags = { describe('Beacon Upload', () => { - before(function() { - fetchMock.restore(); - sinon.restore(); - }); + beforeEach(() => { + window.mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; - beforeEach(function() { - fetchMock.restore(); fetchMockSuccess(urls.identify, { mpid: testMPID, is_logged_in: false, @@ -43,53 +40,43 @@ describe('Beacon Upload', () => { afterEach(() => { sinon.restore(); fetchMock.restore(); + window.sessionStorage.clear(); + window.localStorage.clear(); }); it('should trigger beacon on page visibilitychange events', async () => { - window.mParticle._resetForTests(MPConfig); - const bond = sinon.spy(navigator, 'sendBeacon'); window.mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned); - // visibility change is a document property, not window - document.dispatchEvent(new Event('visibilitychange')); + triggerVisibilityHidden(); - bond.called.should.eql(true); - bond.lastCall.args[0].should.eql(urls.events); + expect(bond.called).to.be.true; + expect(bond.lastCall.args[0]).to.equal(urls.events); }); it('should trigger beacon on page beforeunload events', async () => { - window.mParticle._resetForTests(MPConfig); - const bond = sinon.spy(navigator, 'sendBeacon'); window.mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned); - // karma fails if onbeforeunload is not set to null window.onbeforeunload = null; window.dispatchEvent(new Event('beforeunload')); - bond.called.should.eql(true); - bond.getCalls()[0].args[0].should.eql(urls.events); + expect(bond.called).to.be.true; + expect(bond.firstCall.args[0]).to.equal(urls.events); }); it('should trigger beacon on pagehide events', async () => { - window.mParticle._resetForTests(MPConfig); - const bond = sinon.spy(navigator, 'sendBeacon'); window.mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned); window.dispatchEvent(new Event('pagehide')); - bond.called.should.eql(true); - bond.getCalls()[0].args[0].should.eql(urls.events); - - (typeof bond.getCalls()[0].args[1]).should.eql('object'); + expect(bond.called).to.be.true; + expect(bond.firstCall.args[0]).to.equal(urls.events); + expect(bond.firstCall.args[1]).to.be.instanceof(Blob); }); describe('Offline Storage Enabled', () => { @@ -98,24 +85,12 @@ describe('Beacon Upload', () => { offlineStorage: '100', ...enableBatchingConfigFlags, }; - - fetchMockSuccess(urls.identify, { - mpid: testMPID, - is_logged_in: false, - }); - - window.sessionStorage.clear(); - window.localStorage.clear(); - }); - - afterEach(() => { - fetchMock.restore(); }); it('`visibilitychange` should purge events and batches from Offline Storage after dispatch', async () => { const eventStorageKey = 'mprtcl-v4_abcdef-events'; const batchStorageKey = 'mprtcl-v4_abcdef-batches'; - window.mParticle._resetForTests(MPConfig); + window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -123,52 +98,24 @@ describe('Beacon Upload', () => { const uploader = mpInstance._APIClient.uploader; // Add batches to queue so we can confirm they are purged later - uploader.batchesQueuedForProcessing.push(batch1); - uploader.batchesQueuedForProcessing.push(batch2); - uploader.batchesQueuedForProcessing.push(batch3); + uploader.batchesQueuedForProcessing.push(batch1, batch2, batch3); uploader.queueEvent(event0); - expect( - window.sessionStorage.getItem(eventStorageKey), - 'Stored Events should exist' - ).to.be.ok; - - expect( - JSON.parse(window.sessionStorage.getItem(eventStorageKey)) - .length, - 'Events should be populated before Before Dispatch' - ).to.equal(3); - - expect( - uploader.batchesQueuedForProcessing.length, - 'Batch Queue be populated before dispatch' - ).to.equal(3); - - // Dispatching event will trigger upload process - // visibility change is a document property, not window - document.dispatchEvent(new Event('visibilitychange')); - - expect( - window.sessionStorage.getItem(eventStorageKey), - 'Events should be empty after dispatch' - ).to.equal(''); - - expect( - window.localStorage.getItem(batchStorageKey), - 'Batches should be empty after dispatch' - ).to.equal(null); - - expect( - uploader.batchesQueuedForProcessing.length, - 'Batch Queue should be empty after dispatch' - ).to.equal(0); + expect(window.sessionStorage.getItem(eventStorageKey), 'Stored Events should exist').to.be.ok; + expect(JSON.parse(window.sessionStorage.getItem(eventStorageKey)).length, 'Events should be populated before dispatch').to.equal(3); + expect(uploader.batchesQueuedForProcessing.length, 'Batch Queue should be populated before dispatch').to.equal(3); + + triggerVisibilityHidden(); + + expect(window.sessionStorage.getItem(eventStorageKey), 'Events should be empty after dispatch').to.equal(''); + expect(window.localStorage.getItem(batchStorageKey), 'Batches should be empty after dispatch').to.equal(null); + expect(uploader.batchesQueuedForProcessing.length, 'Batch Queue should be empty after dispatch').to.equal(0); }); it('`beforeunload` should purge events and batches from Offline Storage after dispatch', async () => { const eventStorageKey = 'mprtcl-v4_abcdef-events'; const batchStorageKey = 'mprtcl-v4_abcdef-batches'; - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -176,52 +123,25 @@ describe('Beacon Upload', () => { const uploader = mpInstance._APIClient.uploader; // Add batches to queue so we can confirm they are purged later - uploader.batchesQueuedForProcessing.push(batch1); - uploader.batchesQueuedForProcessing.push(batch2); - uploader.batchesQueuedForProcessing.push(batch3); - + uploader.batchesQueuedForProcessing.push(batch1, batch2, batch3); uploader.queueEvent(event0); - expect( - window.sessionStorage.getItem(eventStorageKey), - 'Stored Events should exist' - ).to.be.ok; - - expect( - JSON.parse(window.sessionStorage.getItem(eventStorageKey)) - .length, - 'Events should be populated before Before Dispatch' - ).to.equal(3); - - expect( - uploader.batchesQueuedForProcessing.length, - 'Batch Queue be populated before dispatch' - ).to.equal(3); - - // Dispatching event will trigger upload process + expect(window.sessionStorage.getItem(eventStorageKey), 'Stored Events should exist').to.be.ok; + expect(JSON.parse(window.sessionStorage.getItem(eventStorageKey)).length, 'Events should be populated before dispatch').to.equal(3); + expect(uploader.batchesQueuedForProcessing.length, 'Batch Queue should be populated before dispatch').to.equal(3); + + window.onbeforeunload = null; window.dispatchEvent(new Event('beforeunload')); - expect( - window.sessionStorage.getItem(eventStorageKey), - 'Events should be empty after dispatch' - ).to.equal(''); - - expect( - window.localStorage.getItem(batchStorageKey), - 'Batches should be empty after dispatch' - ).to.equal(null); - - expect( - uploader.batchesQueuedForProcessing.length, - 'Batch Queue should be empty after dispatch' - ).to.equal(0); + expect(window.sessionStorage.getItem(eventStorageKey), 'Events should be empty after dispatch').to.equal(''); + expect(window.localStorage.getItem(batchStorageKey), 'Batches should be empty after dispatch').to.equal(null); + expect(uploader.batchesQueuedForProcessing.length, 'Batch Queue should be empty after dispatch').to.equal(0); }); it('`pagehide` should purge events and batches from Offline Storage after dispatch', async () => { const eventStorageKey = 'mprtcl-v4_abcdef-events'; const batchStorageKey = 'mprtcl-v4_abcdef-batches'; - window.mParticle._resetForTests(MPConfig); window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -229,45 +149,18 @@ describe('Beacon Upload', () => { const uploader = mpInstance._APIClient.uploader; // Add batches to queue so we can confirm they are purged later - uploader.batchesQueuedForProcessing.push(batch1); - uploader.batchesQueuedForProcessing.push(batch2); - uploader.batchesQueuedForProcessing.push(batch3); - + uploader.batchesQueuedForProcessing.push(batch1, batch2, batch3); uploader.queueEvent(event0); - expect( - window.sessionStorage.getItem(eventStorageKey), - 'Stored Events should exist' - ).to.be.ok; + expect(window.sessionStorage.getItem(eventStorageKey), 'Stored Events should exist').to.be.ok; + expect(JSON.parse(window.sessionStorage.getItem(eventStorageKey)).length, 'Events should be populated before dispatch').to.equal(3); + expect(uploader.batchesQueuedForProcessing.length, 'Batch Queue should be populated before dispatch').to.equal(3); - expect( - JSON.parse(window.sessionStorage.getItem(eventStorageKey)) - .length, - 'Events should be populated before Before Dispatch' - ).to.equal(3); - - expect( - uploader.batchesQueuedForProcessing.length, - 'Batch Queue be populated before dispatch' - ).to.equal(3); - - // Dispatching event will trigger upload process window.dispatchEvent(new Event('pagehide')); - expect( - window.sessionStorage.getItem(eventStorageKey), - 'Events should be empty after dispatch' - ).to.equal(''); - - expect( - window.localStorage.getItem(batchStorageKey), - 'Batches should be empty after dispatch' - ).to.equal(null); - - expect( - uploader.batchesQueuedForProcessing.length, - 'Batch Queue should be empty after dispatch' - ).to.equal(0); + expect(window.sessionStorage.getItem(eventStorageKey), 'Events should be empty after dispatch').to.equal(''); + expect(window.localStorage.getItem(batchStorageKey), 'Batches should be empty after dispatch').to.equal(null); + expect(uploader.batchesQueuedForProcessing.length, 'Batch Queue should be empty after dispatch').to.equal(0); }); }); }); \ No newline at end of file diff --git a/test/src/tests-config-api-client.ts b/test/src/tests-config-api-client.ts index 29a8d62a..78430e78 100644 --- a/test/src/tests-config-api-client.ts +++ b/test/src/tests-config-api-client.ts @@ -24,17 +24,17 @@ describe('ConfigAPIClient', () => { let dataPlanResult: DataPlanResult; beforeEach(() => { - fetchMock.restore(); + window.mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; mockServer = sinon.createFakeServer(); mockServer.respondImmediately = true; sdkInitCompleteCallback = sinon.spy(); - window.mParticle._resetForTests(MPConfig); }); afterEach(() => { - mockServer.reset(); - fetchMock.restore(); sinon.restore(); + fetchMock.restore(); + mockServer.reset(); }); describe('with FetchUploader', () => { @@ -74,7 +74,7 @@ describe('ConfigAPIClient', () => { }); it('should return inital config fetch fails', async () => { - const config = { requestConfig: true }; + const config = { requestConfig: true } as SDKInitConfig; fetchMock.get(urls.config, { status: 400, }); @@ -134,10 +134,6 @@ describe('ConfigAPIClient', () => { }); }); - afterEach(() => { - fetchMock.restore(); - }); - it('appends data plan information to url', async () => { const config: Partial = { requestConfig: true, @@ -185,8 +181,10 @@ describe('ConfigAPIClient', () => { describe('with XHRUploader', () => { - var fetchHolder = window.fetch; + let fetchHolder: typeof window.fetch; + beforeEach(() => { + fetchHolder = window.fetch; delete window.fetch; }); @@ -231,7 +229,7 @@ describe('ConfigAPIClient', () => { }); it('should return inital config fetch fails', async () => { - const config = { requestConfig: true }; + const config = { requestConfig: true } as SDKInitConfig; mockServer.respondWith(urls.config, [400, {}, '']); const configAPIClient = new ConfigAPIClient( diff --git a/test/src/tests-consent.ts b/test/src/tests-consent.ts index 01322ec2..ad76e2eb 100644 --- a/test/src/tests-consent.ts +++ b/test/src/tests-consent.ts @@ -29,17 +29,18 @@ const mParticle = window.mParticle; describe('Consent', function() { beforeEach(function() { + mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; fetchMock.post(urls.events, 200); fetchMockSuccess(urls.identify, { mpid: testMPID, is_logged_in: false }); - mParticle.init(apiKey, window.mParticle.config); }); afterEach(function() { + sinon.restore(); fetchMock.restore(); - mParticle._resetForTests(MPConfig); }); it('Should not create consent object without consented boolean', () => { diff --git a/test/src/tests-cookie-syncing.ts b/test/src/tests-cookie-syncing.ts index 6f144795..6e13ce3b 100644 --- a/test/src/tests-cookie-syncing.ts +++ b/test/src/tests-cookie-syncing.ts @@ -41,6 +41,18 @@ describe('cookie syncing', function() { // tests have run const originalCreateElementFunction = window.document.createElement; + const MockUser = function() { + let consentState = null; + return { + setConsentState: function(state) { + consentState = state; + }, + getConsentState: function() { + return consentState; + }, + }; + }; + before(function() { // Mock the img create onload method // https://raminmousavi.medium.com/mock-img-element-in-jest-3341c495ca8b @@ -70,26 +82,22 @@ describe('cookie syncing', function() { }); beforeEach(function() { + mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; fetchMockSuccess(urls.identify, { mpid: testMPID, is_logged_in: false }); - fetchMock.post(urls.events, 200); - - mParticle.init(apiKey, window.mParticle.config); }); afterEach(function() { fetchMock.restore(); - mParticle._resetForTests(MPConfig); }); it('should sync cookies when there was not a previous cookie-sync', async () => { - mParticle._resetForTests(MPConfig); - window.mParticle.config.pixelConfigs = [pixelSettings]; mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); expect( mParticle.getInstance()._Store.pixelConfigurations.length @@ -99,8 +107,6 @@ describe('cookie syncing', function() { }); it('should sync cookies when current date is beyond the frequency cap and the MPID has not changed', async () => { - mParticle._resetForTests(MPConfig); - window.mParticle.config.pixelConfigs = [pixelSettings]; setLocalStorage(v4LSKey, { @@ -111,7 +117,7 @@ describe('cookie syncing', function() { ie: true, }); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); expect( mParticle.getInstance()._Store.pixelConfigurations.length @@ -124,14 +130,13 @@ describe('cookie syncing', function() { }); it('should not sync cookies when last date is within frequencyCap', async () => { - mParticle._resetForTests(MPConfig); - window.mParticle.config.pixelConfigs = [pixelSettings]; setLocalStorage(); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); + const data = mParticle.getInstance()._Persistence.getLocalStorage(); data[testMPID].csd.should.have.property( @@ -145,12 +150,11 @@ describe('cookie syncing', function() { }); it('should sync cookies when mpid changes', async () => { - mParticle._resetForTests(MPConfig); window.mParticle.config.pixelConfigs = [pixelSettings]; mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); const data1 = mParticle .getInstance() @@ -161,7 +165,7 @@ describe('cookie syncing', function() { }); mParticle.Identity.login(); - await waitForCondition(() => mParticle.Identity.getCurrentUser()?.getMPID() === 'otherMPID') + await waitForCondition(() => mParticle.Identity.getCurrentUser()?.getMPID() === 'otherMPID'); const data2 = mParticle .getInstance() ._Persistence.getLocalStorage(); @@ -185,12 +189,11 @@ describe('cookie syncing', function() { redirectUrl: '', }; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = true; window.mParticle.config.pixelConfigs = [pixelSettings]; mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); const data1 = mParticle .getInstance() @@ -215,12 +218,11 @@ describe('cookie syncing', function() { redirectUrl: '', }; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; window.mParticle.config.pixelConfigs = [pixelSettings]; mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); const data1 = mParticle .getInstance() @@ -232,7 +234,6 @@ describe('cookie syncing', function() { }) it('parse and capture pixel settings properly from backend', async () => { - mParticle._resetForTests(MPConfig); window.mParticle.config.requestConfig = true; // create some cookies mParticle.init(apiKey, window.mParticle.config); @@ -264,7 +265,7 @@ describe('cookie syncing', function() { body: JSON.stringify(forwarderConfigurationResult), }); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); // add pixels to preInitConfig mParticle.init(apiKey, window.mParticle.config); @@ -284,22 +285,8 @@ describe('cookie syncing', function() { const cookies = getLocalStorage(); Object.keys(cookies['MPID1'].csd).length.should.equal(1); }); - - const MockUser = function() { - let consentState = null; - return { - setConsentState: function(state) { - consentState = state; - }, - getConsentState: function() { - return consentState; - }, - }; - }; it('should perform a cookiesync when consent is not configured on the cookiesync setting', async () => { - mParticle._resetForTests(MPConfig); - pixelSettings.filteringConsentRuleValues = {} as unknown as IConsentRules; window.mParticle.config.pixelConfigs = [pixelSettings]; @@ -315,8 +302,6 @@ describe('cookie syncing', function() { }); it('should return false for isEnabledForUserConsent when consent is configured but no user is passed', async () => { - mParticle._resetForTests(MPConfig); - const enableCookieSync = true; const consented = false; @@ -341,7 +326,6 @@ describe('cookie syncing', function() { const includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = false; const userConsent = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const filteringConsentRuleValues = { @@ -375,7 +359,6 @@ describe('cookie syncing', function() { const includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = true; const userConsent = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const filteringConsentRuleValues = { includeOnMatch: includeOnMatch, @@ -409,7 +392,6 @@ describe('cookie syncing', function() { const includeOnMatch = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config const consented = false; const userConsent = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const filteringConsentRuleValues = { @@ -444,7 +426,6 @@ describe('cookie syncing', function() { const includeOnMatch = true; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = true; const userConsent = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const filteringConsentRuleValues = { @@ -478,7 +459,6 @@ describe('cookie syncing', function() { const includeOnMatch = true; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = true; const userConsented = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const filteringConsentRuleValues = { @@ -512,7 +492,6 @@ describe('cookie syncing', function() { const includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = false; const userConsented = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const filteringConsentRuleValues = { @@ -546,7 +525,6 @@ describe('cookie syncing', function() { const includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = true; const userConsented = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const filteringConsentRuleValues = { @@ -580,7 +558,6 @@ describe('cookie syncing', function() { const includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = false; const userConsented = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const filteringConsentRuleValues = { @@ -614,7 +591,6 @@ describe('cookie syncing', function() { const includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = false; const ccpaPresent = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const filteringConsentRuleValues = { @@ -647,7 +623,6 @@ describe('cookie syncing', function() { const includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = true; const ccpaPresent = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const filteringConsentRuleValues = { @@ -680,7 +655,6 @@ describe('cookie syncing', function() { const includeOnMatch = true; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = false; const ccpaPresent = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const filteringConsentRuleValues = { @@ -713,7 +687,6 @@ describe('cookie syncing', function() { const includeOnMatch = true; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = true; const ccpaPresent = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const filteringConsentRuleValues = { @@ -746,7 +719,6 @@ describe('cookie syncing', function() { const includeOnMatch = true; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = true; const ccpaPresent = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const filteringConsentRuleValues = { @@ -779,7 +751,6 @@ describe('cookie syncing', function() { const includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = true; const ccpaPresent = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const filteringConsentRuleValues = { @@ -812,7 +783,6 @@ describe('cookie syncing', function() { const includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = false; const ccpaPresent = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const filteringConsentRuleValues = { @@ -844,7 +814,6 @@ describe('cookie syncing', function() { it('should perform a cookie sync only after GDPR consent is given when consent is required - perform a cookie sync when accepting consent is required', async () => { const includeOnMatch = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config const consented = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; pixelSettings.filteringConsentRuleValues = { @@ -902,13 +871,10 @@ describe('cookie syncing', function() { cookieSyncLS.testMPID.should.have.property('csd'); cookieSyncLS.testMPID.csd.should.have.property(5); }); - - it('should perform a cookie sync only after GDPR consent is given when consent is required - perform a cookie sync when consent is rejected', async () => { - await waitForCondition(hasIdentifyReturned); - + + it('should perform a cookie sync only after GDPR consent is given when consent is required - perform a cookie sync when consent is rejected', async () => { const includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; pixelSettings.filteringConsentRuleValues = { @@ -925,8 +891,8 @@ describe('cookie syncing', function() { window.mParticle.config.pixelConfigs = [pixelSettings]; mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned); + const localStorage = mParticle .getInstance() ._Persistence.getLocalStorage(); @@ -970,7 +936,6 @@ describe('cookie syncing', function() { it('should perform a cookie sync only after CCPA consent is given when consent is required - perform a cookie sync when accepting consent is required', async () => { const includeOnMatch = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config const consented = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; pixelSettings.filteringConsentRuleValues = { @@ -1031,11 +996,8 @@ describe('cookie syncing', function() { }); it('should perform a cookie sync only after CCPA consent is given when consent is required - perform a cookie sync when consent is rejected', async () => { - await waitForCondition(hasIdentifyReturned); - const includeOnMatch = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; pixelSettings.filteringConsentRuleValues = { @@ -1052,8 +1014,8 @@ describe('cookie syncing', function() { window.mParticle.config.pixelConfigs = [pixelSettings]; mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned); + const localStorage = mParticle .getInstance() ._Persistence.getLocalStorage(); @@ -1098,7 +1060,6 @@ describe('cookie syncing', function() { const includeOnMatch = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config const consented = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; // pixelSetting1 has consent required, and so should only perform a cookiesync after consent is saved to the user @@ -1164,6 +1125,7 @@ describe('cookie syncing', function() { mParticle.Identity.getCurrentUser().setConsentState( trueConsentState ); + const newLocalStorage = mParticle .getInstance() ._Persistence.getLocalStorage(); diff --git a/test/src/tests-core-sdk.js b/test/src/tests-core-sdk.js index 6ed9de1f..43515cfc 100644 --- a/test/src/tests-core-sdk.js +++ b/test/src/tests-core-sdk.js @@ -22,6 +22,8 @@ const { describe('core SDK', function() { beforeEach(function() { + mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; fetchMock.post(urls.events, 200); fetchMockSuccess(urls.identify, { mpid: testMPID, @@ -31,7 +33,6 @@ describe('core SDK', function() { }); afterEach(function() { - mParticle._resetForTests(MPConfig); fetchMock.restore(); sinon.restore(); }); @@ -119,8 +120,6 @@ describe('core SDK', function() { it('should process ready queue when initialized', async () => { let readyFuncCalled = false; - mParticle._resetForTests(MPConfig); - mParticle.ready(function() { readyFuncCalled = true; }); @@ -149,7 +148,6 @@ describe('core SDK', function() { }); it('should get environment setting when set to `production`', () => { - mParticle._resetForTests(MPConfig); mParticle.init(apiKey, { ...window.mParticle.config, isDevelopmentMode: false, @@ -159,7 +157,6 @@ describe('core SDK', function() { }); it('should get environment setting when set to `development`', () => { - mParticle._resetForTests(MPConfig); mParticle.init(apiKey, { ...window.mParticle.config, isDevelopmentMode: true, @@ -169,7 +166,6 @@ describe('core SDK', function() { }); it('should get app version from config', () => { - mParticle._resetForTests(MPConfig); window.mParticle.config.appName = "testAppName"; mParticle.init(apiKey, window.mParticle.config); @@ -204,8 +200,6 @@ describe('core SDK', function() { it('should allow app name to be changed via setAppName', async () => { await waitForCondition(hasIdentifyReturned); - mParticle._resetForTests(MPConfig); - const newConfig = { ...window.mParticle.config, appName: 'OverrideTestName'}; mParticle.init(apiKey, newConfig); @@ -348,9 +342,7 @@ describe('core SDK', function() { it('should not generate a new device ID if a deviceId exists in localStorage', async () => { await waitForCondition(hasIdentifyReturned); - - mParticle._resetForTests(MPConfig); - + setLocalStorage(); mParticle.init(apiKey, window.mParticle.config); @@ -367,6 +359,7 @@ describe('core SDK', function() { }); it('will create a cgid when no previous cgid exists after initializing storage, and no sid', () => { + // Reset to clear the sid created by beforeEach's init() mParticle._resetForTests(MPConfig); mParticle.getInstance()._Store.storageName = Utils.workspaceCookieName; @@ -382,7 +375,6 @@ describe('core SDK', function() { it('creates a new session when elapsed time between actions is greater than session timeout', async () => { await waitForCondition(hasIdentifyReturned); - mParticle._resetForTests(MPConfig); mParticle.config.sessionTimeout = 1; mParticle.init(apiKey, window.mParticle.config); await waitForCondition(() => { @@ -407,7 +399,6 @@ describe('core SDK', function() { it('should end session when last event sent is outside of sessionTimeout', async () => { await waitForCondition(hasIdentifyReturned); - mParticle._resetForTests(MPConfig); mParticle.config.sessionTimeout = 1; mParticle.init(apiKey, window.mParticle.config); await waitForCondition(() => { @@ -441,7 +432,6 @@ describe('core SDK', function() { // This test mimics if another tab is open and events are sent, but previous tab's sessionTimeout is still ongoing await waitForCondition(hasIdentifyReturned); - mParticle._resetForTests(MPConfig); mParticle.config.sessionTimeout = 1; mParticle.init(apiKey, window.mParticle.config); await waitForCondition(() => { @@ -539,7 +529,6 @@ describe('core SDK', function() { it('should update session start date when session times out, then start a new one', async () => { await waitForCondition(hasIdentifyReturned); - mParticle._resetForTests(MPConfig); mParticle.config.sessionTimeout = 1; mParticle.init(apiKey, mParticle.config); @@ -691,8 +680,6 @@ describe('core SDK', function() { config.minWebviewBridgeVersion ); mp.SDKConfig.aliasMaxWindow.should.equal(config.aliasMaxWindow); - - mParticle._resetForTests(MPConfig); }); it('should use custom loggers when provided', async () => { @@ -820,8 +807,6 @@ describe('core SDK', function() { }); it('should use default urls if no custom urls are set in config object', () => { - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey, window.mParticle.config); mParticle.getInstance()._Store.SDKConfig.v1SecureServiceUrl.should.equal(Constants.DefaultBaseUrls.v1SecureServiceUrl); @@ -935,14 +920,12 @@ describe('core SDK', function() { }); it('should add onCreateBatch to _Store.SDKConfig if onCreateBatch is provide on mParticle.config object', () => { - window.mParticle._resetForTests(); mParticle.config.onCreateBatch = function(batch) { return batch}; mParticle.init(apiKey, mParticle.config); (typeof mParticle.getInstance()._Store.SDKConfig.onCreateBatch).should.equal('function'); }); it('should not add onCreateBatch to _Store.SDKConfig if it is not a function', () => { - window.mParticle._resetForTests(); mParticle.config.onCreateBatch = 'not a function'; mParticle.init(apiKey, mParticle.config); @@ -950,7 +933,6 @@ describe('core SDK', function() { }); it('should hit url with query parameter of env=1 for debug mode for forwarders', () => { - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = true; mParticle.config.requestConfig = true; fetchMock.resetHistory(); @@ -968,7 +950,6 @@ describe('core SDK', function() { }); it('should hit url with query parameter of env=0 for debug mode for forwarders', () => { - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; mParticle.config.requestConfig = true; @@ -986,7 +967,6 @@ describe('core SDK', function() { // TODO - there are no actual tests here....what's going on? it('should fetch from /config and keep everything properly on the store', async () => { - mParticle._resetForTests(MPConfig); const config = { appName: 'appNameTest', minWebviewBridgeVersion: 1, @@ -1010,9 +990,6 @@ describe('core SDK', function() { }); it('should initialize and log events even with a failed /config fetch and empty config', async () => { - // this instance occurs when self hosting and the user only passes an object into init - mParticle._resetForTests(MPConfig); - const config = { appName: 'appNameTest', minWebviewBridgeVersion: 1, @@ -1023,7 +1000,6 @@ describe('core SDK', function() { body: JSON.stringify({ config }), }); - fetchMock.config.overwriteRoutes = true; fetchMock.post(urls.identify, {status: 400, body: JSON.stringify('')}); // force config to be only requestConfig = true; @@ -1061,9 +1037,6 @@ describe('core SDK', function() { }); it('should initialize without a config object passed to init', async () => { - // this instance occurs when self hosting and the user only passes an object into init - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey); await waitForCondition(hasIdentityCallInflightReturned); @@ -1080,8 +1053,6 @@ describe('core SDK', function() { }); it('should remove localstorage when calling reset', () => { - mParticle._resetForTests(MPConfig); - window.mParticle.config.workspaceToken = 'defghi'; mParticle.init(apiKey, window.mParticle.config) let ls = localStorage.getItem('mprtcl-v4_defghi'); @@ -1094,8 +1065,6 @@ describe('core SDK', function() { }); it('should remove cookies when calling reset', () => { - mParticle._resetForTests(MPConfig); - window.mParticle.config.useCookieStorage = true; window.mParticle.config.workspaceToken = 'defghi'; mParticle.init(apiKey, window.mParticle.config) @@ -1112,7 +1081,6 @@ describe('core SDK', function() { }); it('should queue setCurrencyCode successfully when SDK is not yet initialized, and then later initialized', () => { - mParticle._resetForTests(MPConfig); // mock a non-initialized state mParticle.getInstance()._Store.isInitialized = false; @@ -1124,8 +1092,6 @@ describe('core SDK', function() { }); it('should set a device id when calling setDeviceId', async () => { - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentityCallInflightReturned); // this das should be the SDK auto generated one, which is 36 characters long @@ -1137,7 +1103,6 @@ describe('core SDK', function() { }); it('should set a device id when set on mParticle.config', () => { - mParticle._resetForTests(MPConfig); window.mParticle.config.deviceId = 'foo-guid'; mParticle.init(apiKey, window.mParticle.config); @@ -1145,8 +1110,6 @@ describe('core SDK', function() { }); it('should not set the wrapper sdk info in Store when mParticle._setWrapperSDKInfo() method is called if init not called', () => { - mParticle._resetForTests(MPConfig); - mParticle._setWrapperSDKInfo('flutter', '1.0.3'); mParticle.getInstance()._Store.wrapperSDKInfo.name.should.equal('none'); @@ -1155,8 +1118,6 @@ describe('core SDK', function() { }); it('should have the correct wrapper sdk info default values when init is called', () => { - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey, window.mParticle.config); mParticle.getInstance()._Store.wrapperSDKInfo.name.should.equal('none'); @@ -1165,8 +1126,6 @@ describe('core SDK', function() { }); it('should set the wrapper sdk info in Store when mParticle._setWrapperSDKInfo() method is called after init is called', async () => { - mParticle._resetForTests(MPConfig); - mParticle._setWrapperSDKInfo('flutter', '1.0.3'); mParticle.init(apiKey, window.mParticle.config); @@ -1178,8 +1137,6 @@ describe('core SDK', function() { }); it('should not set the wrapper sdk info in Store after it has previously been set', async () => { - mParticle._resetForTests(MPConfig); - mParticle._setWrapperSDKInfo('flutter', '1.0.3'); mParticle.init(apiKey, window.mParticle.config); diff --git a/test/src/tests-eCommerce.js b/test/src/tests-eCommerce.js index 08a2837d..78d951b8 100644 --- a/test/src/tests-eCommerce.js +++ b/test/src/tests-eCommerce.js @@ -12,19 +12,17 @@ describe('eCommerce', function() { beforeEach(function() { mParticle._resetForTests(MPConfig); delete mParticle._instances['default_instance']; + fetchMock.config.overwriteRoutes = true; fetchMock.post(urls.events, 200); - fetchMockSuccess(urls.identify, { mpid: testMPID, is_logged_in: false }); - - mParticle.init(apiKey, window.mParticle.config); }); afterEach(function() { fetchMock.restore(); - mParticle._resetForTests(MPConfig); + sinon.restore(); }); it('should create ecommerce product', () => { @@ -766,7 +764,6 @@ describe('eCommerce', function() { it('expand product purchase commerce event', async () => { await waitForCondition(hasIdentifyReturned); - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); const config1 = forwarderDefaultConfiguration('MockForwarder', 1); @@ -876,7 +873,6 @@ describe('eCommerce', function() { it('expand product refund commerce event', async () => { await waitForCondition(hasIdentifyReturned); - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); const config1 = forwarderDefaultConfiguration('MockForwarder', 1); @@ -948,7 +944,6 @@ describe('eCommerce', function() { it('expand non-plus-one-product commerce event', async () => { await waitForCondition(hasIdentifyReturned); - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); const config1 = forwarderDefaultConfiguration('MockForwarder', 1); @@ -1020,7 +1015,6 @@ describe('eCommerce', function() { it('expand checkout commerce event', async () => { await waitForCondition(hasIdentifyReturned); - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); const config1 = forwarderDefaultConfiguration('MockForwarder', 1); @@ -1097,7 +1091,6 @@ describe('eCommerce', function() { it('expand promotion commerce event', async () => { await waitForCondition(hasIdentifyReturned); - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); const config1 = forwarderDefaultConfiguration('MockForwarder', 1); @@ -1163,7 +1156,6 @@ describe('eCommerce', function() { it('expand impression commerce event', async () => { await waitForCondition(hasIdentifyReturned); - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); const config1 = forwarderDefaultConfiguration('MockForwarder', 1); @@ -1267,7 +1259,7 @@ describe('eCommerce', function() { }); it('should add customFlags to logPurchase events', async () => { - await waitForCondition(hasIdentifyReturned); + await waitForCondition(hasIdentifyReturned); const product = mParticle.eCommerce.createProduct('iPhone', 'sku1', 499); const transactionAttributes = mParticle.eCommerce.createTransactionAttributes( 'id1', @@ -1350,7 +1342,8 @@ describe('eCommerce', function() { }); it('should deprecate add', async () => { - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); + mParticle._resetForTests(MPConfig); const bond = sinon.spy(mParticle.getInstance().Logger, 'warning'); const product = mParticle.eCommerce.createProduct( diff --git a/test/src/tests-event-logging.js b/test/src/tests-event-logging.js index 83870572..efcbf157 100644 --- a/test/src/tests-event-logging.js +++ b/test/src/tests-event-logging.js @@ -25,7 +25,7 @@ describe('event logging', function() { afterEach(function() { fetchMock.restore(); - mParticle._resetForTests(MPConfig); + sinon.restore(); }); it('should log an event', async () => { @@ -814,7 +814,7 @@ describe('event logging', function() { }); it('should run the callback once when tracking fails', async () => { - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); const clock = sinon.useFakeTimers(); mParticle.init(apiKey, window.mParticle.config); @@ -823,7 +823,7 @@ describe('event logging', function() { return ( mParticle.getInstance()._Store.identityCallInFlight === false ); - }) + }); let successCallbackCalled = false; let numberTimesCalled = 0; diff --git a/test/src/tests-feature-flags.ts b/test/src/tests-feature-flags.ts index fa68b9ed..94aa3a1c 100644 --- a/test/src/tests-feature-flags.ts +++ b/test/src/tests-feature-flags.ts @@ -24,18 +24,18 @@ const hasIdentifyReturned = () => { describe('feature-flags', () => { describe('user audiences', () => { beforeEach(() => { + window.mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; fetchMock.post(urls.events, 200); - fetchMockSuccess(urls.identify, { mpid: testMPID, is_logged_in: false }); - window.mParticle.init(apiKey, window.mParticle.config); }); afterEach(() => { - sinon.restore(); fetchMock.restore(); + sinon.restore(); }); it('should not be able to access user audience API if feature flag is false', async () => { @@ -43,8 +43,6 @@ describe('feature-flags', () => { audienceAPI: 'False' }; - window.mParticle._resetForTests(MPConfig); - // initialize mParticle with feature flag window.mParticle.init(apiKey, window.mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -78,8 +76,6 @@ describe('feature-flags', () => { status: 200, body: JSON.stringify(audienceMembershipServerResponse) }); - - window.mParticle._resetForTests(MPConfig); window.mParticle.config.flags = { audienceAPI: 'True' @@ -125,7 +121,6 @@ describe('feature-flags', () => { captureIntegrationSpecificIds: 'True', captureIntegrationSpecificIdsV2: 'all' }; - window.mParticle._resetForTests(MPConfig); // initialize mParticle with feature flag window.mParticle.init(apiKey, window.mParticle.config); @@ -156,7 +151,6 @@ describe('feature-flags', () => { captureIntegrationSpecificIds: 'False', captureIntegrationSpecificIdsV2: 'none' }; - window.mParticle._resetForTests(MPConfig); // initialize mParticle with feature flag window.mParticle.init(apiKey, window.mParticle.config); diff --git a/test/src/tests-forwarders.ts b/test/src/tests-forwarders.ts index 6b3b22d1..d0903c9d 100644 --- a/test/src/tests-forwarders.ts +++ b/test/src/tests-forwarders.ts @@ -89,6 +89,7 @@ describe('forwarders', function() { beforeEach(function() { mParticle._resetForTests(MPConfig); delete mParticle._instances['default_instance']; + fetchMock.config.overwriteRoutes = true; fetchMock.post(urls.events, 200); mockServer = sinon.createFakeServer(); @@ -126,12 +127,11 @@ describe('forwarders', function() { afterEach(function() { fetchMock.restore(); + sinon.restore(); delete window.MockForwarder1; }); it('should add forwarders via dynamic script loading via the addForwarder method', () => { - mParticle._resetForTests(MPConfig); - const mockForwarder = new MockForwarder(); mParticle.addForwarder(mockForwarder); @@ -197,7 +197,6 @@ describe('forwarders', function() { it('should not permit forwarder if consent configured but there is no user.', () => { const enableForwarder = true; const consented = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -239,7 +238,6 @@ describe('forwarders', function() { const enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = false; const userConsent = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -284,7 +282,6 @@ describe('forwarders', function() { const enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = true; const userConsent = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -327,7 +324,6 @@ describe('forwarders', function() { const enableForwarder = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config const consented = false; const userConsent = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -369,7 +365,6 @@ describe('forwarders', function() { const enableForwarder = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config const consented = true; const userConsent = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -412,7 +407,6 @@ describe('forwarders', function() { const enableForwarder = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config const consented = true; const userConsent = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -455,7 +449,6 @@ describe('forwarders', function() { const enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = false; const userConsent = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -498,7 +491,6 @@ describe('forwarders', function() { const enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = true; const userConsent = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -541,7 +533,6 @@ describe('forwarders', function() { const enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consented = false; const userConsent = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -584,7 +575,6 @@ describe('forwarders', function() { const enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consentPresent = false; const userConsentPresent = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -630,7 +620,6 @@ describe('forwarders', function() { const enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consentPresent = true; const userConsentPresent = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -676,7 +665,6 @@ describe('forwarders', function() { const enableForwarder = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config const consentPresent = false; const userConsentPresent = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -723,7 +711,6 @@ describe('forwarders', function() { const enableForwarder = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config const consentPresent = true; const userConsentPresent = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -769,7 +756,6 @@ describe('forwarders', function() { const enableForwarder = true; // 'Only Forward' chosen in UI, 'includeOnMatch' in config const consentPresent = true; const userConsentPresent = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -815,7 +801,6 @@ describe('forwarders', function() { const enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consentPresent = false; const userConsentPresent = true; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -861,7 +846,6 @@ describe('forwarders', function() { const enableForwarder = false; // 'Do Not Forward' chosen in UI, 'includeOnMatch' in config const consentPresent = true; const userConsentPresent = false; - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -904,7 +888,6 @@ describe('forwarders', function() { }); it("does not initialize a forwarder when forwarder's isDebug != mParticle.isDevelopmentMode", () => { - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -924,7 +907,6 @@ describe('forwarders', function() { }); it('initializes a forwarder with isDebug = false && mParticle.config.isDevelopmentMode = false', () => { - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -944,7 +926,6 @@ describe('forwarders', function() { }); it('initializes a forwarder with isDebug = true && mParticle.config.isDevelopmentMode = true', () => { - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = true; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -961,7 +942,6 @@ describe('forwarders', function() { }); it('initializes forwarders when isDebug = mParticle.config.isDevelopmentMode', () => { - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -985,7 +965,6 @@ describe('forwarders', function() { }); it("sends events to forwarder when forwarder's isDebug = mParticle.config.isDevelopmentMode ", async () => { - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = true; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1005,7 +984,6 @@ describe('forwarders', function() { }); it('sends events to forwarder v1 endpoint when mParticle.config.isDevelopmentMode = config.isDebug = false', async () => { - mParticle._resetForTests(MPConfig); mParticle.config.isDevelopmentMode = false; const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1031,7 +1009,6 @@ describe('forwarders', function() { // https://go.mparticle.com/work/SQDSDKS-6850 it.skip('sends forwarding stats to v2 endpoint when featureFlag setting of batching is true', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); const config1 = forwarderDefaultConfiguration('MockForwarder', 1); @@ -1090,7 +1067,6 @@ describe('forwarders', function() { }); it('should not send forwarding stats to invisible forwarders', () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); const config1 = forwarderDefaultConfiguration('MockForwarder', 1); @@ -1115,7 +1091,6 @@ describe('forwarders', function() { }); it('should invoke forwarder opt out', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1133,7 +1108,6 @@ describe('forwarders', function() { }); it('should invoke forwarder setuserattribute', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1151,7 +1125,6 @@ describe('forwarders', function() { }); it('should invoke forwarder setuserattribute when calling setUserAttributeList', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1171,7 +1144,6 @@ describe('forwarders', function() { }); it('should invoke forwarder removeuserattribute', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1190,7 +1162,6 @@ describe('forwarders', function() { }); it('should filter user attributes from forwarder on log event', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1211,7 +1182,6 @@ describe('forwarders', function() { }); it('should filter user identities from forwarder on init and bring customerid as first ID', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1249,7 +1219,6 @@ describe('forwarders', function() { }); it('should filter user identities from forwarder on log event and bring customerid as first ID', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1288,7 +1257,6 @@ describe('forwarders', function() { }); it('should filter user attributes from forwarder on init, and on subsequent set attribute calls', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1322,7 +1290,6 @@ describe('forwarders', function() { }); it('should filter user attributes from forwarder on init, and on subsequent remove attribute calls', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1381,8 +1348,6 @@ describe('forwarders', function() { }); it('should filter event names', async () => { - mParticle._resetForTests(MPConfig); - const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1410,8 +1375,6 @@ describe('forwarders', function() { }); it('should filter page event names', async () => { - mParticle._resetForTests(MPConfig); - const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); const config1 = forwarderDefaultConfiguration('MockForwarder', 1); @@ -1431,8 +1394,6 @@ describe('forwarders', function() { }); it('should filter event attributes', async () => { - mParticle._resetForTests(MPConfig); - const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1463,8 +1424,6 @@ describe('forwarders', function() { }); it('should filter pageview attributes', async () => { - mParticle._resetForTests(MPConfig); - const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1503,7 +1462,6 @@ describe('forwarders', function() { }); it('should call logout on forwarder', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); const config1 = forwarderDefaultConfiguration('MockForwarder', 1); @@ -1528,7 +1486,6 @@ describe('forwarders', function() { it('should pass in app name to forwarder on initialize', async () => { mParticle.config.appName = 'Unit Tests'; - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); const config1 = forwarderDefaultConfiguration('MockForwarder', 1); @@ -1637,7 +1594,6 @@ describe('forwarders', function() { }); it('should pass filteredUser and filteredUserIdentities to onLoginComplete methods', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1676,7 +1632,6 @@ describe('forwarders', function() { }); it('should pass filteredUser and filteredUserIdentities to onLogoutComplete methods', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1716,7 +1671,6 @@ describe('forwarders', function() { }); it('should pass filteredUser and filteredUserIdentities to onModifyComplete methods', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1756,7 +1710,6 @@ describe('forwarders', function() { }); it('should not forward event if attribute forwarding rule is set', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1790,7 +1743,6 @@ describe('forwarders', function() { }); it('should forward event if event attribute forwarding rule is set and includeOnMatch is true', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1822,7 +1774,6 @@ describe('forwarders', function() { }); it('should not forward event if event attribute forwarding rule is set and includeOnMatch is true but attributes do not match', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1856,7 +1807,6 @@ describe('forwarders', function() { }); it('should not forward event if event attribute forwarding rule is set and includeOnMatch is false', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1891,7 +1841,6 @@ describe('forwarders', function() { }); it('should forward event if event attribute forwarding rule is set and includeOnMatch is false but attributes do not match', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1926,7 +1875,6 @@ describe('forwarders', function() { }); it('should send event to forwarder if filtering attribute and includingOnMatch is true', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1953,8 +1901,6 @@ describe('forwarders', function() { }); it('should not send event to forwarder if filtering attribute and includingOnMatch is false', async () => { - mParticle._resetForTests(MPConfig); - const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -2041,7 +1987,6 @@ describe('forwarders', function() { }); it('should send event to forwarder if there is no match and includeOnMatch = false', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -2069,7 +2014,6 @@ describe('forwarders', function() { }); it('should not send event to forwarder if there is no match and includeOnMatch = true', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -2109,7 +2053,7 @@ describe('forwarders', function() { window.mParticle.config.kitConfigs.push(config1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(() => window.mParticle.getInstance()?._Store?.identityCallInFlight === false); + await waitForCondition(() => window.mParticle.getInstance()?._Store?.identityCallInFlight === false); mParticle.Identity.getCurrentUser().setUserAttribute('Gender', 'Male'); @@ -2140,7 +2084,6 @@ describe('forwarders', function() { }); it('should send event to forwarder if the filterinUserAttribute object is invalid', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -2163,7 +2106,6 @@ describe('forwarders', function() { }); it('should call forwarder onUserIdentified method when identity is returned', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -2182,7 +2124,6 @@ describe('forwarders', function() { // https://go.mparticle.com/work/SQDSDKS-6850 it.skip('should queue forwarder stats reporting and send after 5 seconds if batching feature is true', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -2224,8 +2165,6 @@ describe('forwarders', function() { }); it('should initialize forwarders when a user is not logged in and excludeAnonymousUser=false', async () => { - mParticle._resetForTests(MPConfig); - const mockForwarder = new MockForwarder(); const mockForwarder2 = new MockForwarder('MockForwarder2', 2); @@ -2560,7 +2499,6 @@ describe('forwarders', function() { it.skip('integration test - should allow the user to configure the integrationDelayTimeout', async () => { // testing user-configured integrationDelayTimeout let clock = sinon.useFakeTimers(); - mParticle._resetForTests(MPConfig); mParticle.config.integrationDelayTimeout = 1000; mParticle._setIntegrationDelay(128, true); mParticle._setIntegrationDelay(24, false); @@ -2568,7 +2506,6 @@ describe('forwarders', function() { mParticle.init(apiKey, window.mParticle.config); await waitForCondition(() => { - console.log(window.mParticle.getInstance()?._Store?.identityCallInFlight) return ( window.mParticle.getInstance()?._Store?.identityCallInFlight === false ); @@ -2607,7 +2544,6 @@ describe('forwarders', function() { }); it('integration test - after an integration delay is set to false, should fire an event after the event timeout', async () => { - mParticle._resetForTests(MPConfig); // this code will be put in each forwarder as each forwarder is initialized mParticle._setIntegrationDelay(128, true); mParticle._setIntegrationDelay(24, false); @@ -2713,7 +2649,6 @@ describe('forwarders', function() { // This will pass when we add mpInstance._Store.isInitialized = true; to mp-instance before `processIdentityCallback` it('configures forwarders before events are logged via identify callback', async () => { - mParticle._resetForTests(MPConfig); window.mParticle.config.identifyRequest = { userIdentities: { google: 'google123', @@ -2752,8 +2687,6 @@ describe('forwarders', function() { }); it('should retain preInit.forwarderConstructors, and reinitialize forwarders after calling reset, then init', async () => { - mParticle._resetForTests(MPConfig); - const mockForwarder = new MockForwarder(); mParticle.addForwarder(mockForwarder); @@ -2810,8 +2743,6 @@ describe('forwarders', function() { }); it('should send user-defined SourceMessageId as part of event sent to forwarders via baseEvent', async () => { - mParticle._resetForTests(MPConfig); - const mockForwarder = new MockForwarder(); mParticle.addForwarder(mockForwarder); @@ -2838,8 +2769,6 @@ describe('forwarders', function() { }); it('should add a logger to forwarders', async () => { - mParticle._resetForTests(MPConfig); - const mockForwarder = new MockForwarder(); mParticle.addForwarder(mockForwarder); @@ -2865,8 +2794,6 @@ describe('forwarders', function() { describe('kits with suffixes', function() { it('should add forwarders with suffixes and initialize them accordingly if there is a coresponding kit config with the same suffix', () => { - mParticle._resetForTests(MPConfig); - const mockForwarder = new MockForwarder( 'ForwarderWithSuffixV3', 1, @@ -2896,8 +2823,6 @@ describe('forwarders', function() { }); it('should not add a forwarder with suffix if there is not a corresponding kit config with the same suffix', () => { - mParticle._resetForTests(MPConfig); - const mockForwarder = new MockForwarder( 'ForwarderWithSuffix', 1, @@ -2920,15 +2845,6 @@ describe('forwarders', function() { describe('side loaded kits', function() { describe('initialization', function() { - beforeEach(function() { - mParticle._resetForTests(MPConfig); - delete mParticle._instances['default_instance']; - }); - - afterEach(function() { - delete window.MockForwarder1; - fetchMock.restore(); - }); it('should add sideloaded kits to the active forwarders', function() { const sideloadedKit1 = new MockSideloadedKit( @@ -3102,13 +3018,6 @@ describe('forwarders', function() { mpSideloadedKit2 = new mParticle.MPSideloadedKit( sideloadedKit2 ); - mParticle._resetForTests(MPConfig); - delete mParticle._instances['default_instance']; - }); - - afterEach(function() { - delete window.MockForwarder1; - fetchMock.restore(); }); it('should filter event names out properly when set', async () => { @@ -3406,15 +3315,7 @@ describe('forwarders', function() { }); describe('forwarding', function() { - beforeEach(function() { - mParticle._resetForTests(MPConfig); - delete mParticle._instances['default_instance']; - }); - afterEach(function() { - delete window.MockForwarder1; - fetchMock.restore(); - }); it('should send event to sideloaded kits', async () => { const sideloadedKit1 = new MockSideloadedKit( diff --git a/test/src/tests-helpers.js b/test/src/tests-helpers.js index 17c601ca..0ef81211 100644 --- a/test/src/tests-helpers.js +++ b/test/src/tests-helpers.js @@ -3,8 +3,10 @@ import { apiKey, testMPID, mParticle, + MPConfig, } from './config/constants'; import sinon from 'sinon'; +import fetchMock from 'fetch-mock/esm/client'; import Utils from './config/utils'; const { waitForCondition, fetchMockSuccess, hasIdentityCallInflightReturned } = Utils; @@ -13,6 +15,9 @@ describe('helpers', function() { let sandbox; beforeEach(function() { + mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; + // Create a fresh sandbox for each test to avoid spy conflicts sandbox = sinon.createSandbox(); @@ -31,13 +36,14 @@ describe('helpers', function() { }); afterEach(function() { + fetchMock.restore(); // Restore all spies/stubs created by this test's sandbox if (sandbox) { sandbox.restore(); } }); - it('should correctly validate an attribute value', function(done) { + it('should correctly validate an attribute value', () => { const validatedString = mParticle .getInstance() ._Helpers.Validators.isValidAttributeValue('testValue1'); @@ -63,8 +69,6 @@ describe('helpers', function() { validatedObject.should.not.be.ok(); validatedArray.should.not.be.ok(); validatedUndefined.should.not.be.ok(); - - done(); }); it('should return event name in warning when sanitizing invalid attributes', async () => { @@ -80,7 +84,7 @@ describe('helpers', function() { ); }); - it('should return product name in warning when sanitizing invalid attributes', function(done) { + it('should return product name in warning when sanitizing invalid attributes', () => { const bond = sandbox.spy(mParticle.getInstance().Logger, 'warning'); mParticle.eCommerce.createProduct( 'productName', @@ -100,8 +104,6 @@ describe('helpers', function() { bond.getCalls()[0].args[0].should.eql( "For 'productName', the corresponding attribute value of 'invalidValue' must be a string, number, boolean, or null." ); - - done(); }); it('should return commerce event name in warning when sanitizing invalid attributes', async () => { @@ -123,7 +125,7 @@ describe('helpers', function() { ); }); - it('should correctly validate an identity request with copyUserAttribute as a key using any identify method', function(done) { + it('should correctly validate an identity request with copyUserAttribute as a key using any identify method', () => { const identityApiData = { userIdentities: { customerid: '123', @@ -147,11 +149,9 @@ describe('helpers', function() { logoutResult.valid.should.equal(true); loginResult.valid.should.equal(true); modifyResult.valid.should.equal(true); - - done(); }); - it('should correctly parse string or number', function(done) { + it('should correctly parse string or number', () => { const string = 'abc'; const number = 123; const object = {}; @@ -178,11 +178,9 @@ describe('helpers', function() { Should(objectResult).not.be.ok(); Should(arrayResult).not.be.ok(); Should(nullResult).not.be.ok(); - - done(); }); - it('should filterUserIdentities and include customerId as first in the array', function(done) { + it('should filterUserIdentities and include customerId as first in the array', () => { const filterList = [2, 4, 6, 8]; const userIdentitiesObject = { email: 'test@gmail.com', @@ -205,12 +203,10 @@ describe('helpers', function() { ); filteredIdentities[1].should.have.property('Type', 7); filteredIdentities[2].should.have.property('Identity', 'abc'); - filteredIdentities[2].should.have.property('Type', 0); - - done(); + filteredIdentities[2].should.have.property('Type', 0); }); - it('should return the appropriate boolean for if events should be delayed by an integration', function(done) { + it('should return the appropriate boolean for if events should be delayed by an integration', () => { const integrationDelays1 = { 128: false, 20: false, @@ -246,22 +242,18 @@ describe('helpers', function() { result2.should.equal(true); result3.should.equal(false); result4.should.equal(false); - - done(); }); - it('should return false if integration delay object is empty', function(done) { + it('should return false if integration delay object is empty', () => { const emptyIntegrationDelays = {}; const result1 = mParticle .getInstance() ._Helpers.isDelayedByIntegration(emptyIntegrationDelays); result1.should.equal(false); - - done(); }); - it('should return 0 when hashing undefined or null', function(done) { + it('should return 0 when hashing undefined or null', () => { mParticle.generateHash(undefined) .should.equal(0); mParticle.generateHash(null) @@ -269,11 +261,9 @@ describe('helpers', function() { (typeof mParticle.generateHash(false)).should.equal('number'); mParticle.generateHash(false) .should.not.equal(0); - - done(); }); - it('should generate random value', function(done) { + it('should generate random value', () => { let randomValue = mParticle.getInstance()._Helpers.generateUniqueId(); randomValue.should.be.ok(); window.crypto.getRandomValues = undefined; @@ -288,24 +278,19 @@ describe('helpers', function() { randomValue = mParticle.getInstance()._Helpers.generateUniqueId(); randomValue.should.be.ok(); - done(); }); - it('should create a storage name based on default mParticle storage version + apiKey if apiKey is passed in', function(done) { + it('should create a storage name based on default mParticle storage version + apiKey if apiKey is passed in', () => { const cookieName = mParticle .getInstance() ._Helpers.createMainStorageName(apiKey); cookieName.should.equal('mprtcl-v4_test_key'); - - done(); }); - it('should create a storage name based on default mParticle storage version if no apiKey is passed in', function(done) { + it('should create a storage name based on default mParticle storage version if no apiKey is passed in', () => { const cookieName = mParticle .getInstance() ._Helpers.createMainStorageName(); cookieName.should.equal('mprtcl-v4'); - - done(); }); }); \ No newline at end of file diff --git a/test/src/tests-identities-attributes.ts b/test/src/tests-identities-attributes.ts index 256d9184..928c066a 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 { @@ -54,10 +55,14 @@ const BAD_USER_ATTRIBUTE_KEY_AS_ARRAY = ([ const BAD_USER_ATTRIBUTE_LIST_VALUE = (1234 as unknown) as UserAttributesValue[]; describe('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 5aeb627d..ad52b9cb 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; @@ -91,6 +93,7 @@ const fetchMockSuccess = (url: string, body: any = {}, headers: any = {}) => { describe('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 9b724797..64e4e886 100644 --- a/test/src/tests-identityApiClient.ts +++ b/test/src/tests-identityApiClient.ts @@ -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 () => { diff --git a/test/src/tests-integration-capture.ts b/test/src/tests-integration-capture.ts index feb24d68..829d2841 100644 --- a/test/src/tests-integration-capture.ts +++ b/test/src/tests-integration-capture.ts @@ -26,6 +26,8 @@ const mParticle = window.mParticle as IMParticleInstanceManager; describe('Integration Capture', () => { beforeEach(async function() { mParticle._resetForTests(MPConfig); + fetchMock.restore(); + fetchMock.config.overwriteRoutes = true; fetchMock.post(urls.events, 200); delete mParticle._instances['default_instance']; fetchMockSuccess(urls.identify, { @@ -60,9 +62,8 @@ describe('Integration Capture', () => { }); afterEach(function() { - sinon.restore(); fetchMock.restore(); - mParticle._resetForTests(MPConfig); + sinon.restore(); deleteAllCookies(); }); @@ -139,6 +140,7 @@ describe('Integration Capture', () => { it('should add captured integrations to page view custom flags, prioritizing passed in custom flags', async () => { await waitForCondition(hasIdentifyReturned); + window.mParticle.logPageView( 'Test Page View', {'foo-attr': 'bar-attr'}, diff --git a/test/src/tests-kit-blocking.ts b/test/src/tests-kit-blocking.ts index 4f5eb72a..428e258f 100644 --- a/test/src/tests-kit-blocking.ts +++ b/test/src/tests-kit-blocking.ts @@ -27,6 +27,7 @@ describe('kit blocking', () => { } as KitBlockerDataPlan; beforeEach(function() { + window.mParticle._resetForTests(MPConfig); window.mParticle.config.dataPlan = { document: dataPlan as DataPlanResult }; @@ -35,6 +36,7 @@ describe('kit blocking', () => { afterEach(function() { sinon.restore(); + fetchMock.restore(); }); describe('kitBlocker', () => { @@ -512,6 +514,8 @@ describe('kit blocking', () => { describe('kit blocking - integration tests', () => { beforeEach(() => { + fetchMock.restore(); + fetchMock.config.overwriteRoutes = true; fetchMockSuccess(urls.identify, { mpid: testMPID, is_logged_in: false, @@ -531,8 +535,6 @@ describe('kit blocking', () => { let errorMessages = []; - window.mParticle._resetForTests(MPConfig); - let mockForwarder = new MockForwarder(); window.mParticle.addForwarder(mockForwarder); window.mParticle.config.logLevel = 'verbose'; @@ -1184,7 +1186,6 @@ describe('kit blocking', () => { let errorMessages = []; - window.mParticle._resetForTests(MPConfig); window.mParticle.config.logLevel = 'verbose'; window.mParticle.config.logger = { @@ -1200,7 +1201,6 @@ describe('kit blocking', () => { }); it('integration test - should prioritize data plan from config.dataPlanOptions over server provided data plan', async () => { - window.mParticle._resetForTests(MPConfig); let mockForwarder = new MockForwarder(); window.mParticle.addForwarder(mockForwarder); window.mParticle.config.kitConfigs.push(forwarderDefaultConfiguration('MockForwarder')); @@ -1250,7 +1250,6 @@ describe('kit blocking', () => { }); it('integration test - should block or unblock planned events', async () => { - window.mParticle._resetForTests(MPConfig); let mockForwarder = new MockForwarder(); window.mParticle.addForwarder(mockForwarder); @@ -1287,18 +1286,12 @@ describe('kit blocking', () => { }); describe('integration tests - self hosting set up', () => { - afterEach(function() { - fetchMock.restore(); - }); - it('should create a proper kitblocker on a self hosted set up', async () => { fetchMock.get(`${urls.config}&plan_id=robs_plan&plan_version=1`, { status: 200, body: JSON.stringify({ dataPlanResult: dataPlan }), }); - window.mParticle._resetForTests(MPConfig); - let mockForwarder = new MockForwarder(); window.mParticle.addForwarder(mockForwarder); //requestConfig = true indicates self hosted @@ -1332,8 +1325,6 @@ describe('kit blocking', () => { let errorMessages = []; - window.mParticle._resetForTests(MPConfig); - let mockForwarder = new MockForwarder(); window.mParticle.addForwarder(mockForwarder); @@ -1354,7 +1345,7 @@ describe('kit blocking', () => { } window.mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentifyReturned) + await waitForCondition(hasIdentifyReturned); errorMessages[0].should.equal(errorMessage); window.mParticle.config.requestConfig = false; diff --git a/test/src/tests-legacy-alias-requests.ts b/test/src/tests-legacy-alias-requests.ts index 10a7903c..cda19e0e 100644 --- a/test/src/tests-legacy-alias-requests.ts +++ b/test/src/tests-legacy-alias-requests.ts @@ -34,8 +34,10 @@ describe('legacy Alias Requests', function() { const originalFetch = window.fetch; beforeEach(function() { + mParticle._resetForTests(MPConfig); delete window.fetch; delete mParticle.config.useCookieStorage; + fetchMock.config.overwriteRoutes = true; mockServer = sinon.createFakeServer(); mockServer.respondImmediately = true; localStorage.clear(); @@ -62,7 +64,7 @@ describe('legacy Alias Requests', function() { afterEach(function() { mockServer.restore(); fetchMock.restore(); - mParticle._resetForTests(MPConfig); + sinon.restore(); clock.restore(); window.fetch = originalFetch; }); @@ -285,8 +287,6 @@ describe('legacy Alias Requests', function() { }); it('should properly create AliasRequest', () => { - mParticle._resetForTests(MPConfig); - const cookies = JSON.stringify({ gs: { sid: 'fst Test', @@ -323,8 +323,6 @@ describe('legacy Alias Requests', function() { }); it('should fill in missing fst and lst in createAliasRequest', () => { - mParticle._resetForTests(MPConfig); - const cookies = JSON.stringify({ gs: { sid: 'fst Test', @@ -365,8 +363,6 @@ describe('legacy Alias Requests', function() { }); it('should fix startTime when default is outside max window create AliasRequest', () => { - mParticle._resetForTests(MPConfig); - const millisPerDay = 24 * 60 * 60 * 1000; const cookies = JSON.stringify({ gs: { @@ -463,7 +459,6 @@ describe('legacy Alias Requests', function() { }); it("alias request should have environment 'development' when isDevelopmentMode is true", () => { - mParticle._resetForTests(MPConfig); window.mParticle.config.isDevelopmentMode = true; mockServer.respondWith(urls.alias, [HTTP_ACCEPTED, {}, JSON.stringify({})]); @@ -484,12 +479,10 @@ describe('legacy Alias Requests', function() { const request = mockServer.requests[0]; const requestBody = JSON.parse(request.requestBody); - expect(requestBody['environment']).to.equal('development');expect(requestBody.environment).to.equal('development'); + expect(requestBody.environment).to.equal('development'); }); it('should have default urls if no custom urls are set in config object, but use custom urls when they are set', () => { - mParticle._resetForTests(MPConfig); - window.mParticle.config.v3SecureServiceUrl = 'testtesttest-custom-v3secureserviceurl/v3/JS/'; window.mParticle.config.configUrl = diff --git a/test/src/tests-mParticleUser.js b/test/src/tests-mParticleUser.js index 97b4d81b..392ed6d0 100644 --- a/test/src/tests-mParticleUser.js +++ b/test/src/tests-mParticleUser.js @@ -14,6 +14,9 @@ const forwarderDefaultConfiguration = Utils.forwarderDefaultConfiguration, // https://go.mparticle.com/work/SQDSDKS-6508 describe('mParticleUser', function() { beforeEach(function() { + mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; + fetchMockSuccess(urls.identify, { mpid: 'identifyMPID', is_logged_in: false }); @@ -35,7 +38,6 @@ describe('mParticleUser', function() { }); it('should call forwarder onUserIdentified method with a filtered user identity list', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -74,7 +76,6 @@ describe('mParticleUser', function() { }); it('should call forwarder onUserIdentified method with a filtered user attributes list', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -116,7 +117,6 @@ describe('mParticleUser', function() { }); it('should call forwarder onIdentifyComplete', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -134,7 +134,6 @@ describe('mParticleUser', function() { }); it('should call forwarder onLoginComplete', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -168,7 +167,6 @@ describe('mParticleUser', function() { }); it('should call forwarder onLogoutComplete', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -202,7 +200,6 @@ describe('mParticleUser', function() { }); it('should call forwarder onModifyComplete method with the proper identity method passed through', async () => { - mParticle._resetForTests(MPConfig); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); diff --git a/test/src/tests-mockBatchCreator.ts b/test/src/tests-mockBatchCreator.ts index e9115460..e01f18cb 100644 --- a/test/src/tests-mockBatchCreator.ts +++ b/test/src/tests-mockBatchCreator.ts @@ -9,7 +9,7 @@ describe('Create a batch from a base event', () => { name: 'testEvent' } - it('creates a batch with base event ', done => { + it('creates a batch with base event ', () => { let batch = batchValidator.returnBatch(baseEvent); expect(batch).to.have.property('environment').equal('production'); @@ -52,7 +52,5 @@ describe('Create a batch from a base event', () => { batch = batchValidator.returnBatch(baseEvent); expect(batch.events[0].data).to.have.property('custom_flags'); expect(batch.events[0].data.custom_flags).to.have.property('flagFoo', 'flagBar'); - - done(); }); }); \ No newline at end of file diff --git a/test/src/tests-mparticle-instance-manager.ts b/test/src/tests-mparticle-instance-manager.ts index 977c2a39..17975b5a 100644 --- a/test/src/tests-mparticle-instance-manager.ts +++ b/test/src/tests-mparticle-instance-manager.ts @@ -229,6 +229,8 @@ describe('mParticle instance manager', () => { localStorage.removeItem('mprtcl-prodv4_wtTest3'); mParticle._resetForTests(MPConfig); + fetchMock.restore(); + fetchMock.config.overwriteRoutes = true; mockServer = sinon.createFakeServer(); mockServer.respondImmediately = true; @@ -291,6 +293,7 @@ describe('mParticle instance manager', () => { afterEach(function() { mockServer.restore(); fetchMock.restore(); + sinon.restore(); }); it('uses the correct instance name to identify an instance', async () => { @@ -326,73 +329,44 @@ describe('mParticle instance manager', () => { mParticle.getInstance('instance3')._Store .configurationLoaded === true ); - }) + }); + mParticle.getInstance('default_instance').logEvent('hi1'); mParticle.getInstance('instance2').logEvent('hi2'); mParticle.getInstance('instance3').logEvent('hi3'); - const instance1Event = returnEventForMPInstance( - fetchMock.calls(), - 'apiKey1', - 'hi1' - ); - expect(instance1Event).to.be.ok; + let instance1Event, instance2Event, instance3Event; + let instance1EventsFail1, instance1EventsFail2; + let instance2EventsFail1, instance2EventsFail2; + let instance3EventsFail1, instance3EventsFail2; - const instance2Event = returnEventForMPInstance( - fetchMock.calls(), - 'apiKey2', - 'hi2' - ); + await waitForCondition(() => { + instance1Event = returnEventForMPInstance(fetchMock.calls(), 'apiKey1', 'hi1'); + instance2Event = returnEventForMPInstance(fetchMock.calls(), 'apiKey2', 'hi2'); + instance3Event = returnEventForMPInstance(fetchMock.calls(), 'apiKey3', 'hi3'); + + instance1EventsFail1 = returnEventForMPInstance(fetchMock.calls(), 'apiKey1', 'hi2'); + instance1EventsFail2 = returnEventForMPInstance(fetchMock.calls(), 'apiKey1', 'hi3'); + instance2EventsFail1 = returnEventForMPInstance(fetchMock.calls(), 'apiKey2', 'hi1'); + instance2EventsFail2 = returnEventForMPInstance(fetchMock.calls(), 'apiKey2', 'hi3'); + instance3EventsFail1 = returnEventForMPInstance(fetchMock.calls(), 'apiKey3', 'hi1'); + instance3EventsFail2 = returnEventForMPInstance(fetchMock.calls(), 'apiKey3', 'hi2'); + + return instance1Event && instance2Event && instance3Event && + !instance1EventsFail1 && !instance1EventsFail2 && + !instance2EventsFail1 && !instance2EventsFail2 && + !instance3EventsFail1 && !instance3EventsFail2; + }); + + expect(instance1Event).to.be.ok; expect(instance2Event).to.be.ok; - - const instance3Event = returnEventForMPInstance( - fetchMock.calls(), - 'apiKey3', - 'hi3' - ); expect(instance3Event).to.be.ok; - const instance1EventsFail1 = returnEventForMPInstance( - fetchMock.calls(), - 'apiKey1', - 'hi2' - ); - expect(instance1EventsFail1).to.not.be.ok; - - const instance1EventsFail2 = returnEventForMPInstance( - fetchMock.calls(), - 'apiKey1', - 'hi3' - ); expect(instance1EventsFail2).to.not.be.ok; - - const instance2EventsFail1 = returnEventForMPInstance( - fetchMock.calls(), - 'apiKey2', - 'hi1' - ); expect(instance2EventsFail1).to.not.be.ok; - - const instance2EventsFail2 = returnEventForMPInstance( - fetchMock.calls(), - 'apiKey2', - 'hi3' - ); expect(instance2EventsFail2).to.not.be.ok; - - const instance3EventsFail1 = returnEventForMPInstance( - fetchMock.calls(), - 'apiKey3', - 'hi1' - ); expect(instance3EventsFail1).to.not.be.ok; - - const instance3EventsFail2 = returnEventForMPInstance( - fetchMock.calls(), - 'apiKey3', - 'hi2' - ); expect(instance3EventsFail2).to.not.be.ok; }); @@ -440,28 +414,23 @@ describe('mParticle instance manager', () => { 5 ); + await waitForCondition(hasConfigurationReturned); + mParticle - .getInstance() - .eCommerce.logPurchase(ta, [product1, product2]); + .getInstance() + .eCommerce.logPurchase(ta, [product1, product2]); - await waitForCondition(hasConfigurationReturned); + let instance1Event, instance2Event, instance3Event; - const instance1Event = returnEventForMPInstance( - fetchMock.calls(), - 'apiKey1', - 'purchase' - ); - let instance2Event = returnEventForMPInstance( - fetchMock.calls(), - 'apiKey2', - 'purchase' - ); - let instance3Event = returnEventForMPInstance( - fetchMock.calls(), - 'apiKey3', - 'purchase' - ); - instance1Event.should.be.ok(); + await waitForCondition(() => { + instance1Event = returnEventForMPInstance(fetchMock.calls(), 'apiKey1', 'purchase'); + instance2Event = returnEventForMPInstance(fetchMock.calls(), 'apiKey2', 'purchase'); + instance3Event = returnEventForMPInstance(fetchMock.calls(), 'apiKey3', 'purchase'); + + return instance1Event && !instance2Event && !instance3Event; + }); + + expect(instance1Event).to.be.ok; expect(instance2Event).to.not.be.ok; expect(instance3Event).to.not.be.ok; @@ -469,16 +438,11 @@ describe('mParticle instance manager', () => { .getInstance('instance2') .eCommerce.logPurchase(ta, [product1, product2]); - instance2Event = returnEventForMPInstance( - fetchMock.calls(), - 'apiKey2', - 'purchase' - ); - instance3Event = returnEventForMPInstance( - fetchMock.calls(), - 'apiKey3', - 'purchase' - ); + await waitForCondition(() => { + instance2Event = returnEventForMPInstance(fetchMock.calls(), 'apiKey2', 'purchase'); + instance3Event = returnEventForMPInstance(fetchMock.calls(), 'apiKey3', 'purchase'); + return instance2Event && !instance3Event; + }); expect(instance2Event).to.be.ok; expect(instance3Event).to.not.be.ok; @@ -487,11 +451,10 @@ describe('mParticle instance manager', () => { .getInstance('instance3') .eCommerce.logPurchase(ta, [product1, product2]); - instance3Event = returnEventForMPInstance( - fetchMock.calls(), - 'apiKey3', - 'purchase' - ); + await waitForCondition(() => { + instance3Event = returnEventForMPInstance(fetchMock.calls(), 'apiKey3', 'purchase'); + return instance3Event; + }); expect(instance3Event).to.be.ok; }); diff --git a/test/src/tests-native-sdk.js b/test/src/tests-native-sdk.js index a6801958..50bf8eb1 100644 --- a/test/src/tests-native-sdk.js +++ b/test/src/tests-native-sdk.js @@ -8,9 +8,12 @@ const getLocalStorage = Utils.getLocalStorage, HTTPCodes = Constants.HTTPCodes; describe('native-sdk methods', function() { + beforeEach(function() { + mParticle._resetForTests(MPConfig); + }); + describe('Helper methods', function() { beforeEach(function() { - mParticle._resetForTests(MPConfig); delete window.mParticleAndroid_bridgeName_v2; delete window.webkit; delete window.mParticle.uiwebviewBridgeName; @@ -33,16 +36,14 @@ describe('native-sdk methods', function() { delete mParticle.isIOS; }); - it('isBridgeV2Available returns false if no bridges exist on window', function(done) { + it('isBridgeV2Available returns false if no bridges exist on window', () => { mParticle .getInstance() ._NativeSdkHelpers.isBridgeV2Available('bridgeName') .should.equal(false); - - done(); }); - it('isBridgeV2Available returns true if iOS bridge messageHandler bridge exists on window', function(done) { + it('isBridgeV2Available returns true if iOS bridge messageHandler bridge exists on window', () => { mParticle .getInstance() ._NativeSdkHelpers.isBridgeV2Available('bridgeName') @@ -58,11 +59,9 @@ describe('native-sdk methods', function() { ._NativeSdkHelpers.isBridgeV2Available('bridgeName') .should.equal(true); delete window.webkit; - - done(); }); - it('isBridgeV2Available returns true if iOS bridge nonMessageHandler bridge exists on window', function(done) { + it('isBridgeV2Available returns true if iOS bridge nonMessageHandler bridge exists on window', () => { mParticle .getInstance() ._NativeSdkHelpers.isBridgeV2Available('bridgeName') @@ -74,11 +73,9 @@ describe('native-sdk methods', function() { ._NativeSdkHelpers.isBridgeV2Available('bridgeName') .should.equal(true); delete window.webkit; - - done(); }); - it('isBridgeV2Available returns true if Android bridge exists on window', function(done) { + it('isBridgeV2Available returns true if Android bridge exists on window', () => { mParticle .getInstance() ._NativeSdkHelpers.isBridgeV2Available('bridgeName') @@ -89,12 +86,9 @@ describe('native-sdk methods', function() { ._NativeSdkHelpers.isBridgeV2Available('bridgeName') .should.equal(true); delete window.mParticleAndroid_bridgeName_v2; - - done(); }); - it('isWebviewEnabled returns true if there is no v2Bridge, and minWebviewBridgeVersion is 1, and v1 bridge is available', function(done) { - mParticle._resetForTests(MPConfig); + it('isWebviewEnabled returns true if there is no v2Bridge, and minWebviewBridgeVersion is 1, and v1 bridge is available', () => { window.mParticle.config.minWebviewBridgeVersion = 1; mParticle.config.isIOS = true; mParticle.init(apiKey, window.mParticle.config); @@ -106,12 +100,9 @@ describe('native-sdk methods', function() { window.mParticle.config.minWebviewBridgeVersion ) .should.equal(true); - - done(); }); - it('isWebviewEnabled returns true if there is an Android bridge, minWebviewBridgeVersion is 2', function(done) { - mParticle._resetForTests(MPConfig); + it('isWebviewEnabled returns true if there is an Android bridge, minWebviewBridgeVersion is 2', () => { window.mParticle.config.minWebviewBridgeVersion = 2; mParticle.init(apiKey, window.mParticle.config); @@ -125,12 +116,9 @@ describe('native-sdk methods', function() { window.mParticle.config.minWebviewBridgeVersion ) .should.equal(true); - - done(); }); - it('isWebviewEnabled returns true if there is an iOS bridge, minWebviewBridgeVersion is 2', function(done) { - mParticle._resetForTests(MPConfig); + it('isWebviewEnabled returns true if there is an iOS bridge, minWebviewBridgeVersion is 2', () => { window.mParticle.config.minWebviewBridgeVersion = 2; window.webkit = { messageHandlers: { @@ -146,11 +134,9 @@ describe('native-sdk methods', function() { window.mParticle.config.minWebviewBridgeVersion ) .should.equal(true); - - done(); }); - it('isWebviewEnabled returns true if there is an iOS nonMessageHandler bridge and minWebviewBridgeVersion is 2', function(done) { + it('isWebviewEnabled returns true if there is an iOS nonMessageHandler bridge and minWebviewBridgeVersion is 2', () => { mParticle.minWebviewBridgeVersion = 2; window.mParticle.uiwebviewBridgeName = 'mParticle_bridgeName_v2'; @@ -161,11 +147,9 @@ describe('native-sdk methods', function() { mParticle.minWebviewBridgeVersion ) .should.equal(true); - - done(); }); - it('isWebviewEnabled returns true if there is an iOS nonMessageHandler bridge and minWebviewBridgeVersion is 2', function(done) { + it('isWebviewEnabled returns true if there is an iOS nonMessageHandler bridge and minWebviewBridgeVersion is 2', () => { mParticle.minWebviewBridgeVersion = 2; window.mParticle.uiwebviewBridgeName = 'mParticle_bridgeName_v2'; @@ -176,12 +160,9 @@ describe('native-sdk methods', function() { mParticle.minWebviewBridgeVersion ) .should.equal(true); - - done(); }); - it('isWebviewEnabled returns false if there is a v1 Android bridge, and minWebviewBridgeVersion is 2', function(done) { - mParticle._resetForTests(MPConfig); + it('isWebviewEnabled returns false if there is a v1 Android bridge, and minWebviewBridgeVersion is 2', () => { window.mParticle.config.minWebviewBridgeVersion = 2; mParticle.init(apiKey, window.mParticle.config); window.mParticleAndroid = new mParticleAndroid(); @@ -193,12 +174,9 @@ describe('native-sdk methods', function() { window.mParticle.config.minWebviewBridgeVersion ) .should.equal(false); - - done(); }); - it('isWebviewEnabled returns false if there is a v1 iOS bridge, and minWebviewBridgeVersion is 2', function(done) { - mParticle._resetForTests(MPConfig); + it('isWebviewEnabled returns false if there is a v1 iOS bridge, and minWebviewBridgeVersion is 2', () => { window.mParticle.config.minWebviewBridgeVersion = 2; mParticle.init(apiKey, window.mParticle.config); mParticle.isIOS = true; @@ -212,11 +190,9 @@ describe('native-sdk methods', function() { .should.equal(false); delete mParticle.isIOS; - - done(); }); - it('isWebviewEnabled returns true if there is a v2 Android bridge, and minWebviewBridgeVersion is 1, and no v1 Android bridge exists', function(done) { + it('isWebviewEnabled returns true if there is a v2 Android bridge, and minWebviewBridgeVersion is 1, and no v1 Android bridge exists', () => { mParticle.minWebviewBridgeVersion = 1; window.mParticleAndroid_bridgeName_v2 = new mParticleAndroid(); @@ -227,11 +203,9 @@ describe('native-sdk methods', function() { mParticle.minWebviewBridgeVersion ) .should.equal(true); - - done(); }); - it('isWebviewEnabled returns true if there is a v2 iOS messageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists', function(done) { + it('isWebviewEnabled returns true if there is a v2 iOS messageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists', () => { mParticle.minWebviewBridgeVersion = 1; window.webkit = { messageHandlers: { @@ -246,11 +220,9 @@ describe('native-sdk methods', function() { mParticle.minWebviewBridgeVersion ) .should.equal(true); - - done(); }); - it('isWebviewEnabled returns true if there is a v2 iOS nonMessageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists', function(done) { + it('isWebviewEnabled returns true if there is a v2 iOS nonMessageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists', () => { mParticle.minWebviewBridgeVersion = 1; window.mParticle.uiwebviewBridgeName = 'mParticle_bridgeName_v2'; @@ -263,11 +235,9 @@ describe('native-sdk methods', function() { .should.equal(true); delete mParticle.isIOS; - - done(); }); - it('isWebviewEnabled returns true if there is a v2 Android bridge, and minWebviewBridgeVersion is 1, and no v1 Android bridge exists', function(done) { + it('isWebviewEnabled returns true if there is a v2 Android bridge, and minWebviewBridgeVersion is 1, and no v1 Android bridge exists', () => { mParticle.minWebviewBridgeVersion = 1; window.mParticleAndroid_bridgeName_v2 = new mParticleAndroid(); @@ -278,11 +248,9 @@ describe('native-sdk methods', function() { mParticle.minWebviewBridgeVersion ) .should.equal(true); - - done(); }); - it('isWebviewEnabled returns true if there is a v2 iOS messageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists', function(done) { + it('isWebviewEnabled returns true if there is a v2 iOS messageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists', () => { mParticle.minWebviewBridgeVersion = 1; window.webkit = { messageHandlers: { @@ -297,11 +265,9 @@ describe('native-sdk methods', function() { mParticle.minWebviewBridgeVersion ) .should.equal(true); - - done(); }); - it('isWebviewEnabled returns true if there is a v2 iOS nonMessageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists', function(done) { + it('isWebviewEnabled returns true if there is a v2 iOS nonMessageHandler bridge, and minWebviewBridgeVersion is 1, and no v1 ios bridge exists', () => { mParticle.minWebviewBridgeVersion = 1; window.mParticle.uiwebviewBridgeName = 'mParticle_bridgeName_v2'; @@ -312,11 +278,9 @@ describe('native-sdk methods', function() { mParticle.minWebviewBridgeVersion ) .should.equal(true); - - done(); }); - it('isWebviewEnabled returns false if there is an unmatched requiredWebviewBridgeName, even if bridge 1 exists and min version is 1', function(done) { + it('isWebviewEnabled returns false if there is an unmatched requiredWebviewBridgeName, even if bridge 1 exists and min version is 1', () => { mParticle.minWebviewBridgeVersion = 1; mParticle.requiredWebviewBridgeName = 'nonmatching'; window.mParticle.uiwebviewBridgeName = 'mParticle_bridgeName_v2'; @@ -329,13 +293,11 @@ describe('native-sdk methods', function() { ) .should.equal(false); delete mParticle.isIOS; - done(); }); }); describe('bridge version 1', function() { beforeEach(function() { - mParticle._resetForTests(MPConfig); window.mParticleAndroid = null; window.mParticle.isIOS = null; window.mParticleAndroid = new mParticleAndroid(); @@ -343,18 +305,14 @@ describe('native-sdk methods', function() { mParticle.init(apiKey, window.mParticle.config); }); - it('should set mParitcle._Store.SDKConfig.isIOS to true when mParticle.isIOS is true', function(done) { - mParticle._resetForTests(MPConfig); + it('should set mParitcle._Store.SDKConfig.isIOS to true when mParticle.isIOS is true', () => { mParticle.isIOS = true; mParticle.init(apiKey, window.mParticle.config); mParticle.getInstance()._Store.SDKConfig.isIOS.should.equal(true); - - done(); }); - it('invoke setSessionAttributes of $src_key/$src_env of apikey/\'webview\' to the Android\'s on init if apiKey is available', function(done) { - mParticle._resetForTests(MPConfig); + it('invoke setSessionAttributes of $src_key/$src_env of apikey/\'webview\' to the Android\'s on init if apiKey is available', () => { window.mParticleAndroid = new mParticleAndroid(); window.mParticle.init(apiKey, window.mParticle.config); @@ -371,11 +329,9 @@ describe('native-sdk methods', function() { JSON.parse( window.mParticleAndroid.sessionAttrData[1] ).should.have.property('value', apiKey); - done(); }); - it('invoke only setSessionAttributes of $src_key/$src_env if apikey is missing from webview', function(done) { - mParticle._resetForTests(MPConfig); + it('invoke only setSessionAttributes of $src_key/$src_env if apikey is missing from webview', () => { window.mParticleAndroid = new mParticleAndroid(); window.mParticle.init(null, window.mParticle.config); @@ -386,11 +342,9 @@ describe('native-sdk methods', function() { JSON.parse( window.mParticleAndroid.sessionAttrData[0] ).should.have.property('value', 'webview'); - - done(); }); - it('should invoke setSessionAttributes on Android and pass through proper data', function(done) { + it('should invoke setSessionAttributes on Android and pass through proper data', () => { window.mParticleAndroid.resetSessionAttrData(); mParticle.setSessionAttribute('key', 'value'); @@ -401,10 +355,9 @@ describe('native-sdk methods', function() { window.mParticleAndroid.sessionAttrData[0].should.equal( JSON.stringify({ key: 'key', value: 'value' }) ); - done(); }); - it('should invoke logEvent on Android and pass through proper event', function(done) { + it('should invoke logEvent on Android and pass through proper event', () => { mParticle.logEvent('testEvent'); window.mParticleAndroid.logEventCalled.should.equal(true); @@ -416,11 +369,9 @@ describe('native-sdk methods', function() { 'EventDataType', 'OptOut', ]); - - done(); }); - it('should invoke setAttribute on Android and pass through proper data', function(done) { + it('should invoke setAttribute on Android and pass through proper data', () => { mParticle.Identity.getCurrentUser().setUserAttribute( 'key', 'value' @@ -432,11 +383,9 @@ describe('native-sdk methods', function() { JSON.stringify({ key: 'key', value: 'value' }) ); window.mParticleAndroid.resetUserAttributes(); - - done(); }); - it('should invoke setAttribute on Android and pass through proper data when invoking setUserAttributes', function(done) { + it('should invoke setAttribute on Android and pass through proper data when invoking setUserAttributes', () => { mParticle.Identity.getCurrentUser().setUserAttributes({ gender: 'male', age: 21, @@ -448,11 +397,9 @@ describe('native-sdk methods', function() { window.mParticleAndroid.userAttrData[1].should.equal( JSON.stringify({ key: 'age', value: 21 }) ); - - done(); }); - it('should invoke removeAttributes on native SDK', function(done) { + it('should invoke removeAttributes on native SDK', () => { mParticle.Identity.getCurrentUser().setUserAttribute( 'key', 'value' @@ -463,11 +410,9 @@ describe('native-sdk methods', function() { window.mParticleAndroid.removeUserAttributeCalled.should.equal( true ); - - done(); }); - it('should not sync cookies when in a mobile web view for Android', function(done) { + it('should not sync cookies when in a mobile web view for Android', () => { const pixelSettings = { name: 'AdobeEventForwarder', moduleId: 5, @@ -485,10 +430,9 @@ describe('native-sdk methods', function() { const data = getLocalStorage(); Should(data).not.be.ok(); - done(); }); - it('should send a JSON object to the native SDK\'s Identity methods', function(done) { + it('should send a JSON object to the native SDK\'s Identity methods', () => { let result, identityAPIRequest = { userIdentities: { @@ -531,11 +475,9 @@ describe('native-sdk methods', function() { window.mParticleAndroid.loginData.should.equal(JSONData); window.mParticleAndroid.logoutData.should.equal(JSONData); window.mParticleAndroid.modifyData.should.equal(JSONData); - - done(); }); - it('should send events via the mParticle.ready method ', function(done) { + it('should send events via the mParticle.ready method ', () => { mParticle.ready(function() { mParticle.logEvent('test'); }); @@ -544,8 +486,6 @@ describe('native-sdk methods', function() { JSON.parse(window.mParticleAndroid.event).EventName.should.equal( 'test' ); - - done(); }); }); @@ -555,7 +495,6 @@ describe('native-sdk methods', function() { beforeEach(function() { window.mParticleAndroid = null; window.mParticle.isIOS = null; - mParticle._resetForTests(MPConfig); window.mParticle.config.minWebviewBridgeVersion = 2; window.mParticle.config.requiredWebviewBridgeName = 'bridgeName'; @@ -572,7 +511,7 @@ describe('native-sdk methods', function() { delete window.mParticleAndroid_bridgeName_v2; }); - it('should invoke logEvent on Android and pass through proper event', function(done) { + it('should invoke logEvent on Android and pass through proper event', () => { mParticle.logEvent('testEvent'); mParticleAndroidV2Bridge.logEventCalled.should.equal(true); @@ -586,11 +525,9 @@ describe('native-sdk methods', function() { 'EventDataType', 'OptOut', ]); - - done(); }); - it('should invoke setAttribute on Android and pass through proper data', function(done) { + it('should invoke setAttribute on Android and pass through proper data', () => { mParticle.Identity.getCurrentUser().setUserAttribute( 'key', 'value' @@ -603,10 +540,9 @@ describe('native-sdk methods', function() { JSON.stringify({ key: 'key', value: 'value' }) ); mParticleAndroidV2Bridge.resetUserAttributes(); - done(); }); - it('should invoke setAttribute on Android and pass through proper data when invoking setUserAttributes', function(done) { + it('should invoke setAttribute on Android and pass through proper data when invoking setUserAttributes', () => { mParticle.Identity.getCurrentUser().setUserAttributes({ gender: 'male', age: 21, @@ -621,11 +557,9 @@ describe('native-sdk methods', function() { JSON.stringify({ key: 'age', value: 21 }) ); mParticleAndroidV2Bridge.resetUserAttributes(); - - done(); }); - it('should invoke removeAttributes on Android', function(done) { + it('should invoke removeAttributes on Android', () => { mParticle.Identity.getCurrentUser().setUserAttribute( 'key', 'value' @@ -638,11 +572,9 @@ describe('native-sdk methods', function() { mParticleAndroidV2Bridge.removeUserAttributeCalled.should.equal( true ); - - done(); }); - it('should invoke setSessionAttributes on Android and pass through proper data', function(done) { + it('should invoke setSessionAttributes on Android and pass through proper data', () => { mParticle.setSessionAttribute('key', 'value'); mParticleAndroidV2Bridge.setSessionAttributeCalled.should.equal( @@ -651,11 +583,9 @@ describe('native-sdk methods', function() { mParticleAndroidV2Bridge.sessionAttrData[2].should.equal( JSON.stringify({ key: 'key', value: 'value' }) ); - - done(); }); - it('should not sync cookies when in a mobile web view for Android', function(done) { + it('should not sync cookies when in a mobile web view for Android', () => { const pixelSettings = { name: 'AdobeEventForwarder', moduleId: 5, @@ -672,10 +602,9 @@ describe('native-sdk methods', function() { const data = getLocalStorage(); Should(data).not.be.ok(); - done(); }); - it('should send a JSON object to the Android\'s Identity methods', function(done) { + it('should send a JSON object to the Android\'s Identity methods', () => { let result, identityAPIRequest = { userIdentities: { @@ -718,11 +647,9 @@ describe('native-sdk methods', function() { mParticleAndroidV2Bridge.loginData.should.equal(JSONData); mParticleAndroidV2Bridge.logoutData.should.equal(JSONData); mParticleAndroidV2Bridge.modifyData.should.equal(JSONData); - - done(); }); - it('should send a JSON object to the Android\'s Alias method', function(done) { + it('should send a JSON object to the Android\'s Alias method', () => { let callbackResult; const aliasRequest = { destinationMpid: '101', @@ -744,11 +671,9 @@ describe('native-sdk methods', function() { callbackResult.message.should.equal( 'Alias request sent to native sdk' ); - - done(); }); - it('should send events via the mParticle.ready method ', function(done) { + it('should send events via the mParticle.ready method ', () => { mParticle.ready(function() { mParticle.logEvent('test'); }); @@ -757,11 +682,9 @@ describe('native-sdk methods', function() { JSON.parse( mParticleAndroidV2Bridge.event ).EventName.should.equal('test'); - - done(); }); - it('should send an event with a product list when calling logPurchase', function(done) { + it('should send an event with a product list when calling logPurchase', () => { const product = mParticle.eCommerce.createProduct( 'product1', 'sku', @@ -803,16 +726,12 @@ describe('native-sdk methods', function() { JSON.parse( mParticleAndroidV2Bridge.event ).ProductAction.ProductList[1].Name.should.equal('product2'); - - done(); }); - it('should invoke upload on native SDK', function(done) { + it('should invoke upload on native SDK', () => { mParticle.upload(); mParticleAndroidV2Bridge.uploadCalled.should.equal(true); - - done(); }); }); @@ -821,7 +740,6 @@ describe('native-sdk methods', function() { beforeEach(function() { window.mParticleAndroid = null; window.mParticle.isIOS = null; - mParticle._resetForTests(MPConfig); window.mParticle.config.minWebviewBridgeVersion = 2; window.mParticle.config.requiredWebviewBridgeName = 'bridgeName'; @@ -845,7 +763,7 @@ describe('native-sdk methods', function() { delete mParticle.enableWebviewBridge; }); - it('should invoke logEvent on iOS SDK and pass through proper event', function(done) { + it('should invoke logEvent on iOS SDK and pass through proper event', () => { mParticle.logEvent('testEvent'); JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties( @@ -863,11 +781,9 @@ describe('native-sdk methods', function() { 'EventDataType', 'OptOut', ]); - - done(); }); - it('should invoke setAttribute on iOS SDK and pass through proper data', function(done) { + it('should invoke setAttribute on iOS SDK and pass through proper data', () => { mParticle.Identity.getCurrentUser().setUserAttribute( 'key', 'value' @@ -884,11 +800,9 @@ describe('native-sdk methods', function() { JSON.parse( mParticleIOSV2Bridge.data[0] ).value.should.have.property('value', 'value'); - - done(); }); - it('should invoke setAttribute on iOS SDK and pass through proper data when invoking setUserAttributes', function(done) { + it('should invoke setAttribute on iOS SDK and pass through proper data when invoking setUserAttributes', () => { mParticle.Identity.getCurrentUser().setUserAttributes({ gender: 'male', age: 21, @@ -918,11 +832,9 @@ describe('native-sdk methods', function() { JSON.parse( mParticleIOSV2Bridge.data[1] ).value.should.have.property('value', 21); - - done(); }); - it('should invoke removeAttributes on iOS SDK', function(done) { + it('should invoke removeAttributes on iOS SDK', () => { mParticle.Identity.getCurrentUser().setUserAttribute( 'key', 'value' @@ -953,11 +865,9 @@ describe('native-sdk methods', function() { JSON.parse( mParticleIOSV2Bridge.data[1] ).value.should.have.property('value', null); - - done(); }); - it('should invoke setSessionAttributes on ios SDK and pass through proper data', function(done) { + it('should invoke setSessionAttributes on ios SDK and pass through proper data', () => { mParticle.setSessionAttribute('key', 'value'); JSON.parse(mParticleIOSV2Bridge.data[0]).should.have.properties( @@ -971,12 +881,10 @@ describe('native-sdk methods', function() { ).value.should.have.property('key', 'key'); JSON.parse( mParticleIOSV2Bridge.data[0] - ).value.should.have.property('value', 'value'); - - done(); + ).value.should.have.property('value', 'value'); }); - it('should not sync cookies when in a mobile web view', function(done) { + it('should not sync cookies when in a mobile web view', () => { const pixelSettings = { name: 'AdobeEventForwarder', moduleId: 5, @@ -993,10 +901,9 @@ describe('native-sdk methods', function() { const data = getLocalStorage(); Should(data).not.be.ok(); - done(); }); - it('should send a JSON object to the ios SDK\'s Identity methods', function(done) { + it('should send a JSON object to the ios SDK\'s Identity methods', () => { let result, identityAPIRequest = { userIdentities: { @@ -1051,11 +958,9 @@ describe('native-sdk methods', function() { JSON.parse(mParticleIOSV2Bridge.data[0]).value ).should.equal(JSONData); mParticleIOSV2Bridge.reset(); - - done(); }); - it('should send a JSON object to the iOS SDK\'s Alias method', function(done) { + it('should send a JSON object to the iOS SDK\'s Alias method', () => { let callbackResult; const aliasRequest = { destinationMpid: '101', @@ -1087,11 +992,9 @@ describe('native-sdk methods', function() { callbackResult.message.should.equal( 'Alias request sent to native sdk' ); - - done(); }); - it('should send events via the mParticle.ready method ', function(done) { + it('should send events via the mParticle.ready method ', () => { mParticle.ready(function() { mParticle.logEvent('test'); }); @@ -1102,10 +1005,9 @@ describe('native-sdk methods', function() { mParticleIOSV2Bridge.data[0] ).value.should.have.property('EventName', 'test'); - done(); }); - it('should send an event with a product list when calling logPurchase', function(done) { + it('should send an event with a product list when calling logPurchase', () => { const product = mParticle.eCommerce.createProduct( 'product1', 'sku', @@ -1156,11 +1058,9 @@ describe('native-sdk methods', function() { ).value.ProductAction.ProductList[1].Name.should.equal( 'product2' ); - - done(); }); - it('should invoke upload on iOS SDK', function(done) { + it('should invoke upload on iOS SDK', () => { mParticle.upload(); @@ -1172,8 +1072,6 @@ describe('native-sdk methods', function() { ); (JSON.parse(mParticleIOSV2Bridge.data[0]).value === null).should.equal(true); - - done(); }); }); }); diff --git a/test/src/tests-persistence.ts b/test/src/tests-persistence.ts index ce3c6f93..045ff7f7 100644 --- a/test/src/tests-persistence.ts +++ b/test/src/tests-persistence.ts @@ -32,6 +32,8 @@ const { describe('persistence', () => { beforeEach(() => { + mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; fetchMock.post(urls.events, 200); fetchMockSuccess(urls.identify, { @@ -42,6 +44,7 @@ describe('persistence', () => { afterEach(() => { fetchMock.restore(); + sinon.restore(); }); describe('#setCookie', () => { @@ -164,8 +167,6 @@ describe('persistence', () => { }); it('should move new schema from cookies to localStorage with useCookieStorage = false', done => { - mParticle._resetForTests(MPConfig); - const cookies = JSON.stringify({ gs: { sid: 'sid', @@ -197,9 +198,7 @@ describe('persistence', () => { done(); }); - it('should migrate localStorage to cookies with useCookieStorage = true', done => { - mParticle._resetForTests(MPConfig); - + it('should migrate localStorage to cookies with useCookieStorage = true', () => { setLocalStorage(); mParticle.config.useCookieStorage = true; @@ -219,8 +218,6 @@ describe('persistence', () => { '1', 'testuser@mparticle.com' ); - - done(); }); it('localStorage - should key cookies on mpid on first run', async () => { @@ -490,7 +487,6 @@ describe('persistence', () => { }); it('should revert to cookie storage if localStorage is not available and useCookieStorage is set to false', async () => { - mParticle._resetForTests(MPConfig); mParticle.getInstance()._Persistence.determineLocalStorageAvailability = () => { return false; }; @@ -570,8 +566,6 @@ describe('persistence', () => { }); it('should add new MPID to cookies when returned MPID does not match anything in cookies, and have empty UI and UA', async () => { - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey, mParticle.config); await waitForCondition(hasIdentifyReturned); @@ -1207,7 +1201,6 @@ describe('persistence', () => { }); it('integration test - migrates a large localStorage cookie to cookies and properly remove MPIDs', async () => { - mParticle._resetForTests(MPConfig); mParticle.config.useCookieStorage = false; mParticle.config.maxCookieSize = 700; @@ -1666,8 +1659,6 @@ describe('persistence', () => { }); it('should properly set setLastSeenTime()', async () => { - mParticle._resetForTests(MPConfig); - const cookies = JSON.stringify({ gs: { sid: 'lst Test', @@ -1797,8 +1788,6 @@ describe('persistence', () => { }); it('should save to persistence a device id set with setDeviceId', async () => { - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey, mParticle.config); await waitForCondition(hasIdentityCallInflightReturned); mParticle.setDeviceId('foo-guid'); @@ -1809,8 +1798,7 @@ describe('persistence', () => { .gs.das.should.equal('foo-guid'); }); - it('should save to persistence a device id set via mParticle.config', done => { - mParticle._resetForTests(MPConfig); + it('should save to persistence a device id set via mParticle.config', () => { mParticle.config.deviceId = 'foo-guid'; mParticle.init(apiKey, mParticle.config); @@ -1818,13 +1806,9 @@ describe('persistence', () => { .getInstance() ._Persistence.getLocalStorage() .gs.das.should.equal('foo-guid'); - - done(); }); - it('should prioritize device id set via mParticle.config instead of local storage', done => { - mParticle._resetForTests(MPConfig); - + it('should prioritize device id set via mParticle.config instead of local storage', () => { mParticle.init(apiKey, mParticle.config); const initialDeviceId = mParticle.getInstance().getDeviceId(); @@ -1851,8 +1835,6 @@ describe('persistence', () => { mParticle.getInstance()._Persistence.getLocalStorage().gs.das, 'Device ID stored in Local Storage should be the new Device ID' ).to.equal(expectedDeviceId); - - done(); }); // this test confirms a bug has been fixed where setting a user attribute, then user attribute list @@ -1867,7 +1849,6 @@ describe('persistence', () => { // first test local storage mParticle.config.useCookieStorage = false; - mParticle._resetForTests(MPConfig); mParticle.init(apiKey, mParticle.config); await waitForCondition(() => window.mParticle.getInstance()?._Store?.identityCallInFlight === false); @@ -1880,8 +1861,6 @@ describe('persistence', () => { user.getAllUserAttributes()['ua-list'][1].should.equal(''); user.getAllUserAttributes()['ua-1'].should.equal('a'); - mParticle._resetForTests(MPConfig); - // then test cookie storage mParticle.config.useCookieStorage = true; @@ -1899,10 +1878,6 @@ describe('persistence', () => { }); describe('noFunctional privacy flag', () => { - beforeEach(() => { - mParticle._resetForTests(MPConfig); - }); - describe('set to true', () => { beforeEach(() => { mParticle.config.launcherOptions = { noFunctional: true }; diff --git a/test/src/tests-queue-public-methods.js b/test/src/tests-queue-public-methods.js index c798fc6a..e626c846 100644 --- a/test/src/tests-queue-public-methods.js +++ b/test/src/tests-queue-public-methods.js @@ -1,3 +1,5 @@ +import sinon from 'sinon'; +import fetchMock from 'fetch-mock/esm/client'; import { apiKey, MPConfig, testMPID, urls } from './config/constants'; import { SDKProductActionType } from '../../src/sdkRuntimeModels'; import Utils from './config/utils'; @@ -7,15 +9,18 @@ const { waitForCondition, fetchMockSuccess, hasIdentityCallInflightReturned } = describe('Queue Public Methods', function () { beforeEach(function () { + fetchMock.config.overwriteRoutes = true; fetchMockSuccess(urls.events); fetchMockSuccess(urls.identify, { mpid: testMPID, is_logged_in: false, }); }); - + afterEach(function () { mParticle._resetForTests(MPConfig); + fetchMock.restore(); + sinon.restore(); }); describe('mParticle Core', function () { @@ -30,7 +35,7 @@ describe('Queue Public Methods', function () { mParticle.isInitialized().should.equal(false); mParticle.getInstance().isInitialized().should.equal(false); window.mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.isInitialized().should.equal(true); mParticle.getInstance().isInitialized().should.equal(true); }); @@ -48,7 +53,7 @@ describe('Queue Public Methods', function () { mParticle.setAppVersion('1.2.3'); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); }); }); @@ -65,7 +70,7 @@ describe('Queue Public Methods', function () { mParticle.setAppName('Timmy'); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); }); }); @@ -73,20 +78,16 @@ describe('Queue Public Methods', function () { describe('#ready', function () { it('should queue if not initialized', function () { mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); - mParticle.ready(function () { - console.log('fired ready function'); - }); + mParticle.ready(function () {}); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); }); it('should process queue after initialization', async function () { mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); - mParticle.ready(function () { - console.log('fired ready function'); - }); + mParticle.ready(function () {}); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); }); }); @@ -103,7 +104,7 @@ describe('Queue Public Methods', function () { mParticle.setPosition(10, 4); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); }); }); @@ -128,7 +129,7 @@ describe('Queue Public Methods', function () { mParticle.logBaseEvent(event); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); }); }); @@ -145,7 +146,7 @@ describe('Queue Public Methods', function () { mParticle.logEvent('Test Event'); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); }); }); @@ -162,7 +163,7 @@ describe('Queue Public Methods', function () { mParticle.logError('test error', {}); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); }); }); @@ -179,7 +180,7 @@ describe('Queue Public Methods', function () { mParticle.logPageView('test page view', {}); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); }); }); @@ -196,7 +197,7 @@ describe('Queue Public Methods', function () { mParticle.setOptOut(true); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); }); }); @@ -213,7 +214,7 @@ describe('Queue Public Methods', function () { mParticle.setIntegrationAttribute('12345', {}); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); }); }); @@ -230,7 +231,7 @@ describe('Queue Public Methods', function () { mParticle.setSessionAttribute('foo', 'bar'); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); }); }); @@ -239,7 +240,7 @@ describe('Queue Public Methods', function () { it('returns true when Store is initialized', async function () { mParticle.getInstance().isInitialized().should.be.false(); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance().isInitialized().should.be.true(); }); }); @@ -258,7 +259,7 @@ describe('Queue Public Methods', function () { mParticle.eCommerce.setCurrencyCode('USD'); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); }); }); @@ -277,7 +278,7 @@ describe('Queue Public Methods', function () { mParticle.eCommerce.logProductAction(SDKProductActionType.Purchase, product); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); }); }); @@ -294,7 +295,7 @@ describe('Queue Public Methods', function () { mParticle.eCommerce.logPromotion('Test'); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); }); }); @@ -315,7 +316,7 @@ describe('Queue Public Methods', function () { mParticle.eCommerce.logImpression(impression); mParticle.getInstance()._preInit.readyQueue.length.should.equal(1); mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(hasIdentityCallInflightReturned) + await waitForCondition(hasIdentityCallInflightReturned); mParticle.getInstance()._preInit.readyQueue.length.should.equal(0); }); }); diff --git a/test/src/tests-runtimeToBatchEventsDTO.ts b/test/src/tests-runtimeToBatchEventsDTO.ts index fb452220..d0924648 100644 --- a/test/src/tests-runtimeToBatchEventsDTO.ts +++ b/test/src/tests-runtimeToBatchEventsDTO.ts @@ -1,3 +1,4 @@ +import fetchMock from 'fetch-mock/esm/client'; import * as Converter from '../../src/sdkToEventsApiConverter'; import { expect } from 'chai'; import Types from '../../src/types'; @@ -14,17 +15,18 @@ declare global { describe('Old model to batch model conversion', () => { beforeEach(function() { + window.mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; window.mParticle.init(apiKey, window.mParticle.config); }); afterEach(function() { - window.mParticle._resetForTests(MPConfig); + fetchMock.restore(); }); const batchDataTests = [{ devmode: false }, { devmode: true }]; batchDataTests.forEach(params => { - it('Batch level conversion ' + params, done => { - window.mParticle._resetForTests(MPConfig); + it('Batch level conversion ' + params, () => { window.mParticle.config.appVersion = 'a version'; window.mParticle.config.appName = 'a name'; @@ -79,9 +81,8 @@ describe('Old model to batch model conversion', () => { const sdkEvent = window.mParticle.getInstance()._ServerModel.createEventObject( publicEvent - ) as SDKEvent; - console.log(sdkEvent); - expect(sdkEvent).to.be.ok; + ) as SDKEvent; + expect(sdkEvent).to.be.ok; batch = Converter.convertEvents( '123', [sdkEvent, sdkEvent], @@ -118,12 +119,10 @@ describe('Old model to batch model conversion', () => { 'foo-flag': 'foo-flag-val', }); expect(batchEvent.data.session_uuid).to.equal('foo-session-id'); - - done(); }); }); - it('User attribute conversion ', done => { + it('User attribute conversion ', () => { window.mParticle.getInstance().Identity.getCurrentUser = () => { return { getUserIdentities: () => { @@ -164,11 +163,9 @@ describe('Old model to batch model conversion', () => { 'foo-user-attr': 'foo-attr-value', 'foo-user-attr-list': ['item1', 'item2'], }); - - done(); }); - it('Data Plan Context conversion', done => { + it('Data Plan Context conversion', () => { const publicEvent = { messageType: Types.MessageType.PageEvent, name: 'foo page', @@ -209,10 +206,9 @@ describe('Old model to batch model conversion', () => { expect(batch.context.data_plan).to.be.ok; expect(batch.context.data_plan.plan_id).to.equal("foo"); expect(batch.context.data_plan.plan_version).be.equal(4); - done(); }); - it('User identity conversion ', done => { + it('User identity conversion ', () => { window.mParticle.getInstance().Identity.getCurrentUser = () => { return { getUserIdentities: () => { @@ -263,8 +259,6 @@ describe('Old model to batch model conversion', () => { expect(batch.user_identities.other_id_2).to.equal('foo-other2'); expect(batch.user_identities.other_id_3).to.equal('foo-other3'); expect(batch.user_identities.other_id_4).to.equal('foo-other4'); - - done(); }); const baseEventConversion: { [key: number]: EventsApi.EventType } = { @@ -279,7 +273,7 @@ describe('Old model to batch model conversion', () => { }; Object.keys(baseEventConversion).forEach(key => { - it('Base Event Conversion ' + baseEventConversion[key], done => { + it('Base Event Conversion ' + baseEventConversion[key], () => { let event = Converter.convertEvent(null); expect(event).to.be.null; @@ -312,11 +306,10 @@ describe('Old model to batch model conversion', () => { event = Converter.convertEvent(sdkEvent); expect(event).to.be.ok; expect(event.event_type).to.equal(baseEventConversion[key]); - done(); }); }); - it('Commerce Event Product Action convertion', done => { + it('Commerce Event Product Action convertion', () => { const sdkEvent: SDKEvent = { EventName: 'eCommerce - Purchase', EventCategory: 16, @@ -415,10 +408,9 @@ describe('Old model to batch model conversion', () => { sdkProduct.Attributes ); } - done(); }); - it ('Media Event Conversion', done => { + it ('Media Event Conversion', () => { const sdkEvent: SDKEvent = { EventName: "Pause Event", EventCategory: 9, @@ -465,11 +457,9 @@ describe('Old model to batch model conversion', () => { expect(event).to.be.ok; expect(event.event_type).to.equal('custom_event'); expect(event.data.custom_event_type).to.equal('media') - - done(); }); - it('Set width and height to 0 when window is defined but screen is not defined', done => { + it('Set width and height to 0 when window is defined but screen is not defined', () => { const originalScreen = window.screen; delete window.screen; @@ -519,6 +509,5 @@ describe('Old model to batch model conversion', () => { // set screen back on window.screen = originalScreen; - done(); }); }); \ No newline at end of file diff --git a/test/src/tests-self-hosting-specific.js b/test/src/tests-self-hosting-specific.js index a28b358e..a9c1499d 100644 --- a/test/src/tests-self-hosting-specific.js +++ b/test/src/tests-self-hosting-specific.js @@ -14,6 +14,8 @@ const { // Calls to /config are specific to only the self hosting environment describe('/config self-hosting integration tests', function() { beforeEach(function() { + mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; fetchMock.post(urls.events, 200); }); @@ -25,7 +27,6 @@ describe('/config self-hosting integration tests', function() { // https://go.mparticle.com/work/SQDSDKS-7160 it.skip('queues events in the eventQueue while /config is in flight, then processes them afterwards with correct MPID', async () => { - mParticle._resetForTests(MPConfig); window.mParticle.config.requestConfig = true; window.mParticle.config.flags.eventBatchingIntervalMillis = 0; // trigger event uploads immediately @@ -75,7 +76,6 @@ describe('/config self-hosting integration tests', function() { // https://go.mparticle.com/work/SQDSDKS-6852 it.skip('queued events contain login mpid instead of identify mpid when calling login immediately after mParticle initializes', async () => { const messages = []; - mParticle._resetForTests(MPConfig); window.mParticle.config.requestConfig = true; window.mParticle.config.flags.eventBatchingIntervalMillis = 0; // trigger event uploads immediately @@ -159,11 +159,9 @@ describe('/config self-hosting integration tests', function() { localStorage.removeItem('mprtcl-v4_workspaceTokenTest'); - window.mParticle.config.requestConfig = false; }); it('cookie name has workspace token in it in self hosting mode after config fetch', async () => { - mParticle._resetForTests(MPConfig); window.mParticle.config.requestConfig = true; window.mParticle.config.logLevel = 'verbose'; delete window.mParticle.config.workspaceToken; @@ -181,12 +179,10 @@ describe('/config self-hosting integration tests', function() { const data = window.localStorage.getItem('mprtcl-v4_wtTest'); (typeof data === 'string').should.equal(true); - window.mParticle.config.requestConfig = false; }); describe('/config self-hosting with direct url routing', async () => { it('should return direct urls when no baseUrls are passed and directURLRouting is true', async () => { - mParticle._resetForTests(MPConfig); window.mParticle.config.requestConfig = true; delete window.mParticle.config.workspaceToken; @@ -224,7 +220,6 @@ describe('/config self-hosting integration tests', function() { }); it('should prioritize passed in baseUrls over direct urls', async () => { - mParticle._resetForTests(MPConfig); window.mParticle.config.requestConfig = true; window.mParticle.config.aliasUrl = 'jssdks.foo.mparticle.com/v1/identity/'; @@ -251,7 +246,7 @@ describe('/config self-hosting integration tests', function() { mParticle.init(apiKey, window.mParticle.config); - waitForCondition(hasConfigurationReturned); + await waitForCondition(hasConfigurationReturned); const { aliasUrl, configUrl, diff --git a/test/src/tests-serverModel.ts b/test/src/tests-serverModel.ts index 1da06e99..5077c3b6 100644 --- a/test/src/tests-serverModel.ts +++ b/test/src/tests-serverModel.ts @@ -1,5 +1,6 @@ +import fetchMock from 'fetch-mock/esm/client'; import Types from '../../src/types'; -import { urls, testMPID, apiKey } from './config/constants'; +import { urls, testMPID, apiKey, MPConfig } from './config/constants'; import { expect } from 'chai'; import { IUploadObject } from '../../src/serverModel'; import { IdentityApiData } from '@mparticle/web-sdk'; @@ -22,6 +23,8 @@ const ServerModel = mParticle.getInstance()._ServerModel; describe('ServerModel', () => { beforeEach(() => { + mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; initialEvent = { messageType: Types.MessageType.PageEvent, name: 'foo page', @@ -31,6 +34,10 @@ describe('ServerModel', () => { }; }); + afterEach(() => { + fetchMock.restore(); + }); + describe('#convertToConsentStateDTO', () => { it('should convert Consent State with GDPR to a DTO', () => { const consentState = ({ @@ -159,9 +166,6 @@ describe('ServerModel', () => { mParticle.init(apiKey, mParticle.config); }); - afterEach(function() { - }); - it('should create an event object without a user', () => { const mPStore = mParticle.getInstance()._Store; @@ -1129,9 +1133,6 @@ describe('ServerModel', () => { mParticle.init(apiKey, mParticle.config); }); - afterEach(function() { - }); - it('Should not convert data plan object to server DTO when no id or version is set', () => { let sdkEvent = window.mParticle .getInstance() @@ -1146,7 +1147,6 @@ describe('ServerModel', () => { }); it('Should convert data plan id to server DTO', () => { - mParticle._resetForTests(); mParticle.config.dataPlan = { planId: 'plan_slug', }; @@ -1164,7 +1164,6 @@ describe('ServerModel', () => { }); it('Should not convert data plan object to server DTO when no id is set', () => { - mParticle._resetForTests(); mParticle.config.dataPlan = { planVersion: 5, }; @@ -1182,7 +1181,6 @@ describe('ServerModel', () => { }); it('Should convert entire data plan object to server DTO', () => { - mParticle._resetForTests(); mParticle.config.dataPlan = { planId: 'plan_slug', planVersion: 10, diff --git a/test/src/tests-session-manager.ts b/test/src/tests-session-manager.ts index 0e8e2096..db59a181 100644 --- a/test/src/tests-session-manager.ts +++ b/test/src/tests-session-manager.ts @@ -32,6 +32,8 @@ describe('SessionManager', () => { let sandbox; beforeEach(() => { + mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; sandbox = sinon.createSandbox(); fetchMock.post(urls.events, 200); @@ -42,8 +44,8 @@ describe('SessionManager', () => { afterEach(function() { sandbox.restore(); - mParticle._resetForTests(MPConfig); fetchMock.restore(); + sinon.restore(); }); describe('Unit Tests', () => { @@ -51,12 +53,6 @@ describe('SessionManager', () => { clock = sinon.useFakeTimers(now.getTime()); }); - afterEach(function() { - sandbox.restore(); - clock.restore(); - mParticle._resetForTests(MPConfig); - }); - describe('#initialize', () => { beforeEach(() => { // Change timeout to 10 minutes so we can make sure defaults are not in use @@ -855,10 +851,6 @@ describe('SessionManager', () => { }); describe('Integration Tests', () => { - afterEach(function() { - fetchMock.restore(); - }); - it('should end a session if the session timeout expires', () => { const generateUniqueIdSpy = sinon.stub( mParticle.getInstance()._Helpers, diff --git a/test/src/tests-store.ts b/test/src/tests-store.ts index 60f96206..418b5499 100644 --- a/test/src/tests-store.ts +++ b/test/src/tests-store.ts @@ -1,5 +1,6 @@ import { expect } from 'chai'; import sinon from 'sinon'; +import fetchMock from 'fetch-mock/esm/client'; import { SDKInitConfig } from '../../src/sdkRuntimeModels'; import Store, { IStore, @@ -104,6 +105,8 @@ describe('Store', () => { }; beforeEach(function() { + window.mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; sandbox = sinon.createSandbox(); clock = sinon.useFakeTimers(now.getTime()); // MP Instance is just used because Store requires an mParticle instance @@ -111,9 +114,10 @@ describe('Store', () => { }); afterEach(function() { - window.mParticle._resetForTests(MPConfig); sandbox.restore(); clock.restore(); + fetchMock.restore(); + sinon.restore(); }); describe('initialization', () => { @@ -1811,7 +1815,6 @@ describe('Store', () => { }); it('should set noFunctional and noTargeting from init config', () => { - window.mParticle._resetForTests(MPConfig); window.mParticle.config = window.mParticle.config || {}; window.mParticle.config.launcherOptions = { noFunctional: true, noTargeting: true }; diff --git a/test/src/tests-user.ts b/test/src/tests-user.ts index 12951971..237c1bd1 100644 --- a/test/src/tests-user.ts +++ b/test/src/tests-user.ts @@ -1,3 +1,4 @@ +import sinon from 'sinon'; import { expect } from 'chai'; import Utils from './config/utils'; import { urls, apiKey, MPConfig, testMPID } from './config/constants'; @@ -22,6 +23,8 @@ const hasIdentifyReturned = () => { // https://go.mparticle.com/work/SQDSDKS-6508 describe('mParticle User', () => { beforeEach(() => { + mParticle._resetForTests(MPConfig); + fetchMock.config.overwriteRoutes = true; delete mParticle.config.useCookieStorage; fetchMock.post(urls.events, 200); localStorage.clear(); @@ -36,14 +39,12 @@ describe('mParticle User', () => { afterEach(() => { fetchMock.restore(); - mParticle._resetForTests(MPConfig); + sinon.restore(); }); describe('Consent State', () => { // https://go.mparticle.com/work/SQDSDKS-7393 it('get/set consent state for single user', async () => { - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey, mParticle.config); await waitForCondition(hasIdentifyReturned); let consentState = mParticle @@ -80,8 +81,6 @@ describe('mParticle User', () => { }); it('get/set consent state for multiple users', async () => { - mParticle._resetForTests(MPConfig); - mParticle.init(apiKey, mParticle.config); await waitForCondition(hasIdentifyReturned);