diff --git a/src/Rokt-Kit.js b/src/Rokt-Kit.js index 8d43392..dd86efc 100644 --- a/src/Rokt-Kit.js +++ b/src/Rokt-Kit.js @@ -25,7 +25,6 @@ var constructor = function () { self.launcher = null; self.filters = {}; - self.filteredUser = {}; self.userAttributes = {}; /** @@ -115,6 +114,18 @@ var constructor = function () { console.warn('Unable to find Rokt on the page'); } } + /** + * Returns the user identities from the filtered user, if any + * @param {Object} filteredUser - The filtered user object containing identities + * @returns {Object} The user identities from the filtered user + */ + function returnUserIdentities(filteredUser) { + if (!filteredUser || !filteredUser.getUserIdentities) { + return {}; + } + + return filteredUser.getUserIdentities().userIdentities; + } /** * Selects placements for Rokt Web SDK with merged attributes, filters, and experimentation options @@ -160,8 +171,11 @@ var constructor = function () { ? fetchOptimizely() : {}; + var filteredUserIdentities = returnUserIdentities(filteredUser); + var selectPlacementsAttributes = mergeObjects( filteredAttributes, + filteredUserIdentities, optimizelyAttributes, { mpid: mpid, @@ -176,7 +190,7 @@ var constructor = function () { } function onUserIdentified(filteredUser) { - self.filteredUser = filteredUser; + self.filters.filteredUser = filteredUser; self.userAttributes = filteredUser.getAllUserAttributes(); } @@ -200,7 +214,6 @@ var constructor = function () { .then(function (launcher) { // Assign the launcher to a global variable for later access window.Rokt.currentLauncher = launcher; - // Locally cache the launcher and filters self.launcher = launcher; @@ -214,11 +227,8 @@ var constructor = function () { console.warn( 'Rokt Kit: No filtered user has been set.' ); - } else { - self.filteredUser = roktFilters.filteredUser; } } - // Attaches the kit to the Rokt manager window.mParticle.Rokt.attachKit(self); diff --git a/test/src/tests.js b/test/src/tests.js index 8978734..b859ce7 100644 --- a/test/src/tests.js +++ b/test/src/tests.js @@ -218,7 +218,10 @@ describe('Rokt Forwarder', () => { {} ); - await waitForCondition(() => window.mParticle.Rokt.attachKitCalled); + // Wait for initialization to complete (after launcher is created) + await waitForCondition(() => { + return window.mParticle.forwarder.isInitialized; + }); window.mParticle.Rokt.kit.filters.should.deepEqual({ userAttributesFilters: [], @@ -232,7 +235,7 @@ describe('Rokt Forwarder', () => { }, }); - window.mParticle.Rokt.kit.filteredUser + window.mParticle.Rokt.kit.filters.filteredUser .getMPID() .should.equal('123'); }); @@ -470,154 +473,462 @@ describe('Rokt Forwarder', () => { }; }); - it('should call launcher.selectPlacements with all passed through options', async () => { - await window.mParticle.forwarder.init( - { - accountId: '123456', - }, - reportService.cb, - true, - null, - {} - ); + describe('Default initialization', () => { + it('should call launcher.selectPlacements with all passed through options', async () => { + await window.mParticle.forwarder.init( + { + accountId: '123456', + }, + reportService.cb, + true, + null, + {} + ); - await window.mParticle.forwarder.selectPlacements({ - identifier: 'test-placement', - attributes: { - test: 'test', - }, + await window.mParticle.forwarder.selectPlacements({ + identifier: 'test-placement', + attributes: { + test: 'test', + }, + }); + + window.Rokt.selectPlacementsCalled.should.equal(true); + window.Rokt.selectPlacementsOptions.should.deepEqual({ + identifier: 'test-placement', + attributes: { + test: 'test', + mpid: '123', + }, + }); }); - window.Rokt.selectPlacementsCalled.should.equal(true); - window.Rokt.selectPlacementsOptions.should.deepEqual({ - identifier: 'test-placement', - attributes: { - test: 'test', - mpid: '123', - }, + it('should collect mpid and send to launcher.selectPlacements', async () => { + await window.mParticle.forwarder.init( + { + accountId: '123456', + }, + reportService.cb, + true, + null, + { + 'user-attribute': 'user-attribute-value', + } + ); + + await window.mParticle.forwarder.selectPlacements({ + identifier: 'test-placement', + attributes: { + 'user-attribute': 'user-attribute-value', + }, + }); + + window.Rokt.selectPlacementsCalled.should.equal(true); + window.Rokt.selectPlacementsOptions.should.deepEqual({ + identifier: 'test-placement', + attributes: { + 'user-attribute': 'user-attribute-value', + mpid: '123', + }, + }); }); }); - it('should call launcher.selectPlacements with filtered user attributes', async () => { - window.mParticle.forwarder.filters.filterUserAttributes = - function () { - return { + describe('User Attributes', () => { + it('should call launcher.selectPlacements with filtered user attributes', async () => { + window.mParticle.forwarder.filters.filterUserAttributes = + function () { + return { + 'user-attribute': 'user-attribute-value', + 'unfiltered-attribute': 'unfiltered-value', + }; + }; + + await window.mParticle.forwarder.init( + { + accountId: '123456', + }, + reportService.cb, + true, + null, + {} + ); + + await window.mParticle.forwarder.selectPlacements({ + identifier: 'test-placement', + attributes: { + 'unfiltered-attribute': 'unfiltered-value', + 'filtered-attribute': 'filtered-value', + }, + }); + + window.Rokt.selectPlacementsCalled.should.equal(true); + window.Rokt.selectPlacementsOptions.should.deepEqual({ + identifier: 'test-placement', + attributes: { 'user-attribute': 'user-attribute-value', 'unfiltered-attribute': 'unfiltered-value', + mpid: '123', + }, + }); + }); + + it('should filter user attributes through filterUserAttributes function before sending to selectPlacements', async () => { + // Mocked filterUserAttributes function will return filtered attributes + // based on the config passed in the init method and will ultimately + // remove any attributes from the init method that are filtered. + // Also, any initial attributes from the init call that have updated + // durring runtime should be returned by the filterUserAttribute method. + window.mParticle.forwarder.filters.filterUserAttributes = + function () { + return { + 'user-attribute': 'user-attribute-value', + 'unfiltered-attribute': 'unfiltered-value', + 'changed-attribute': 'new-value', + }; }; - }; - await window.mParticle.forwarder.init( - { - accountId: '123456', - }, - reportService.cb, - true, - null, - {} - ); + await window.mParticle.forwarder.init( + { + accountId: '123456', + }, + reportService.cb, + true, + null, + { + // These should be filtered out + 'blocked-attribute': 'blocked-value', + 'initial-user-attribute': + 'initial-user-attribute-value', + + // This should be updated + 'changed-attribute': 'old-value', + } + ); - await window.mParticle.forwarder.selectPlacements({ - identifier: 'test-placement', - attributes: { - 'unfiltered-attribute': 'unfiltered-value', - 'filtered-attribute': 'filtered-value', - }, - }); + await window.mParticle.forwarder.selectPlacements({ + identifier: 'test-placement', + attributes: { + // This should pass through + 'unfiltered-attribute': 'unfiltered-value', - window.Rokt.selectPlacementsCalled.should.equal(true); - window.Rokt.selectPlacementsOptions.should.deepEqual({ - identifier: 'test-placement', - attributes: { - 'user-attribute': 'user-attribute-value', - 'unfiltered-attribute': 'unfiltered-value', - mpid: '123', - }, - }); - }); + // This should be filtered out + 'filtered-attribute': 'filtered-value', + }, + }); - it('should filter user attributes through filterUserAttributes function before sending to selectPlacements', async () => { - // Mocked filterUserAttributes function will return filtered attributes - // based on the config passed in the init method and will ultimately - // remove any attributes from the init method that are filtered. - // Also, any initial attributes from the init call that have updated - // durring runtime should be returned by the filterUserAttribute method. - window.mParticle.forwarder.filters.filterUserAttributes = - function () { - return { + window.Rokt.selectPlacementsCalled.should.equal(true); + window.Rokt.selectPlacementsOptions.should.deepEqual({ + identifier: 'test-placement', + attributes: { 'user-attribute': 'user-attribute-value', 'unfiltered-attribute': 'unfiltered-value', 'changed-attribute': 'new-value', - }; + mpid: '123', + }, + }); + }); + }); + + describe('Identity handling', () => { + beforeEach(() => { + window.Rokt = new MockRoktForwarder(); + window.mParticle.Rokt = window.Rokt; + window.mParticle.Rokt.attachKitCalled = false; + window.mParticle.Rokt.attachKit = async (kit) => { + window.mParticle.Rokt.attachKitCalled = true; + window.mParticle.Rokt.kit = kit; + Promise.resolve(); + }; + window.mParticle.forwarder.launcher = { + selectPlacements: function (options) { + window.mParticle.Rokt.selectPlacementsOptions = options; + window.mParticle.Rokt.selectPlacementsCalled = true; + }, }; + }); - await window.mParticle.forwarder.init( - { - accountId: '123456', - }, - reportService.cb, - true, - null, - { - // These should be filtered out - 'blocked-attribute': 'blocked-value', - 'initial-user-attribute': 'initial-user-attribute-value', + it('should send userAttributes if userIdentities is null but userAttributes exists', async () => { + window.mParticle.Rokt.filters = { + userAttributeFilters: [], + filterUserAttributes: function (attributes) { + return attributes; + }, + filteredUser: { + getMPID: function () { + return 'abc'; + }, + getUserIdentities: function () { + return { userIdentities: {} }; + }, + }, + }; - // This should be updated - 'changed-attribute': 'old-value', - } - ); + // Set up the createLauncher to properly resolve asynchronously + window.Rokt.createLauncher = async function () { + return Promise.resolve({ + selectPlacements: function (options) { + window.mParticle.Rokt.selectPlacementsOptions = + options; + window.mParticle.Rokt.selectPlacementsCalled = true; + }, + }); + }; - await window.mParticle.forwarder.selectPlacements({ - identifier: 'test-placement', - attributes: { - // This should pass through - 'unfiltered-attribute': 'unfiltered-value', + await window.mParticle.forwarder.init( + { + accountId: '123456', + }, + reportService.cb, + true, + null, + { + 'test-attribute': 'test-value', + } + ); - // This should be filtered out - 'filtered-attribute': 'filtered-value', - }, + // Wait for initialization to complete (after launcher is created) + await waitForCondition(() => { + return window.mParticle.forwarder.isInitialized; + }); + + await window.mParticle.forwarder.selectPlacements({ + identifier: 'test-placement', + attributes: {}, + }); + + window.Rokt.selectPlacementsOptions.attributes.should.deepEqual( + { + 'test-attribute': 'test-value', + mpid: 'abc', + } + ); }); - window.Rokt.selectPlacementsCalled.should.equal(true); - window.Rokt.selectPlacementsOptions.should.deepEqual({ - identifier: 'test-placement', - attributes: { - 'user-attribute': 'user-attribute-value', - 'unfiltered-attribute': 'unfiltered-value', - 'changed-attribute': 'new-value', - mpid: '123', - }, + it('should send userIdentities when userAttributes is null but userIdentities exists', async () => { + window.mParticle.Rokt.filters = { + userAttributeFilters: [], + filterUserAttributes: function () { + return {}; + }, + filteredUser: { + getMPID: function () { + return '234'; + }, + getUserIdentities: function () { + return { + userIdentities: { + customerid: 'customer123', + email: 'test@example.com', + }, + }; + }, + }, + }; + + // Set up the createLauncher to properly resolve asynchronously + window.Rokt.createLauncher = async function () { + return Promise.resolve({ + selectPlacements: function (options) { + window.mParticle.Rokt.selectPlacementsOptions = + options; + window.mParticle.Rokt.selectPlacementsCalled = true; + }, + }); + }; + await window.mParticle.forwarder.init( + { + accountId: '123456', + }, + reportService.cb, + true, + null, + {} + ); + // Wait for initialization to complete (after launcher is created) + await waitForCondition(() => { + return window.mParticle.forwarder.isInitialized; + }); + + await window.mParticle.forwarder.selectPlacements({ + identifier: 'test-placement', + attributes: {}, + }); + + window.Rokt.selectPlacementsOptions.attributes.should.deepEqual( + { + customerid: 'customer123', + email: 'test@example.com', + mpid: '234', + } + ); }); - }); - it('should collect mpid and send to launcher.selectPlacements', async () => { - await window.mParticle.forwarder.init( - { - accountId: '123456', - }, - reportService.cb, - true, - null, - { - 'user-attribute': 'user-attribute-value', - } - ); + it('should send userAttributes and userIdentities if both exist', async () => { + window.mParticle.Rokt.filters = { + userAttributeFilters: [], + filterUserAttributes: function (attributes) { + return attributes; + }, + filteredUser: { + getMPID: function () { + return '123'; + }, + getUserIdentities: function () { + return { + userIdentities: { + customerid: 'customer123', + email: 'test@example.com', + }, + }; + }, + }, + }; - await window.mParticle.forwarder.selectPlacements({ - identifier: 'test-placement', - attributes: { - 'user-attribute': 'user-attribute-value', - }, + // Set up the createLauncher to properly resolve asynchronously + window.Rokt.createLauncher = async function () { + return Promise.resolve({ + selectPlacements: function (options) { + window.mParticle.Rokt.selectPlacementsOptions = + options; + window.mParticle.Rokt.selectPlacementsCalled = true; + }, + }); + }; + + await window.mParticle.forwarder.init( + { + accountId: '123456', + }, + reportService.cb, + true, + null, + { + 'test-attribute': 'test-value', + } + ); + + // Wait for initialization to complete (after launcher is created) + await waitForCondition(() => { + return window.mParticle.forwarder.isInitialized; + }); + + await window.mParticle.forwarder.selectPlacements({ + identifier: 'test-placement', + attributes: {}, + }); + + window.Rokt.selectPlacementsOptions.attributes.should.deepEqual( + { + 'test-attribute': 'test-value', + customerid: 'customer123', + email: 'test@example.com', + mpid: '123', + } + ); }); - window.Rokt.selectPlacementsCalled.should.equal(true); - window.Rokt.selectPlacementsOptions.should.deepEqual({ - identifier: 'test-placement', - attributes: { - 'user-attribute': 'user-attribute-value', - mpid: '123', - }, + it('should not send userIdentities if filteredUser is null', async () => { + window.mParticle.Rokt.filters = { + userAttributeFilters: [], + filterUserAttributes: function (attributes) { + return attributes; + }, + filteredUser: null, + }; + + // Set up the createLauncher to properly resolve asynchronously + window.Rokt.createLauncher = async function () { + return Promise.resolve({ + selectPlacements: function (options) { + window.mParticle.Rokt.selectPlacementsOptions = + options; + window.mParticle.Rokt.selectPlacementsCalled = true; + }, + }); + }; + + await window.mParticle.forwarder.init( + { + accountId: '123456', + }, + reportService.cb, + true, + null, + { + 'test-attribute': 'test-value', + } + ); + + // Wait for initialization to complete (after launcher is created) + await waitForCondition(() => { + return window.mParticle.forwarder.isInitialized; + }); + + await window.mParticle.forwarder.selectPlacements({ + identifier: 'test-placement', + attributes: {}, + }); + + window.Rokt.selectPlacementsOptions.attributes.should.deepEqual( + { + 'test-attribute': 'test-value', + mpid: null, + } + ); + }); + + it('should not send userIdentities if getUserIdentities function does not exist', async () => { + window.mParticle.Rokt.filters = { + userAttributeFilters: [], + filterUserAttributes: function (attributes) { + return attributes; + }, + filteredUser: { + getMPID: function () { + return '123'; + }, + // getUserIdentities is intentionally missing + }, + }; + + window.Rokt.createLauncher = async function () { + return Promise.resolve({ + selectPlacements: function (options) { + window.mParticle.Rokt.selectPlacementsOptions = + options; + window.mParticle.Rokt.selectPlacementsCalled = true; + }, + }); + }; + + await window.mParticle.forwarder.init( + { + accountId: '123456', + }, + reportService.cb, + true, + null, + { + 'test-attribute': 'test-value', + } + ); + + // Wait for initialization to complete (after launcher is created) + await waitForCondition(() => { + return window.mParticle.forwarder.isInitialized; + }); + + await window.mParticle.forwarder.selectPlacements({ + identifier: 'test-placement', + attributes: {}, + }); + + window.Rokt.selectPlacementsOptions.attributes.should.deepEqual( + { + 'test-attribute': 'test-value', + mpid: '123', + } + ); }); }); }); @@ -665,7 +976,7 @@ describe('Rokt Forwarder', () => { 'test-attribute': 'test-value', }); - window.mParticle.forwarder.filteredUser + window.mParticle.forwarder.filters.filteredUser .getMPID() .should.equal('123'); });