-
Notifications
You must be signed in to change notification settings - Fork 3
feat: Support adding identities to select placement attributes #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
34bee4e
5be4bdc
53fa728
203ffcc
113f9b3
b504950
6e07d7a
511a094
a01b6ce
b6013e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -116,6 +116,32 @@ var constructor = function () { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Adds user identities to the attributes object | ||
| * @param {Object} attributes - The attributes object to add identities to | ||
| * @param {Object} filteredUser - The filtered user object containing identities | ||
| * @returns {Object} The attributes object with added identities | ||
| */ | ||
| function addIdentityAttributes(attributes, filteredUser) { | ||
| if (!filteredUser || !filteredUser.getUserIdentities) { | ||
| return attributes; | ||
| } | ||
|
|
||
| var userIdentities = filteredUser.getUserIdentities().userIdentities; | ||
| if (!userIdentities) { | ||
| return attributes; | ||
| } | ||
|
|
||
| for (var identityKey in userIdentities) { | ||
| if (userIdentities.hasOwnProperty(identityKey)) { | ||
| var identityValue = userIdentities[identityKey]; | ||
| attributes[identityKey] = identityValue; | ||
| } | ||
| } | ||
|
|
||
| return attributes; | ||
| } | ||
|
|
||
| /** | ||
| * Selects placements for Rokt Web SDK with merged attributes, filters, and experimentation options | ||
| * @see https://docs.rokt.com/developers/integration-guides/web/library/select-placements-options/ | ||
|
|
@@ -160,6 +186,12 @@ var constructor = function () { | |
| ? fetchOptimizely() | ||
| : {}; | ||
|
|
||
| // Add user identities to the attributes | ||
| filteredAttributes = addIdentityAttributes( | ||
| filteredAttributes, | ||
| filteredUser | ||
| ); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're merging all the different user attributes below, so I think instead of mutating the existing filtered attributes, we should create a new object that will be merged below. I think this would make logging and debugging easier in the future. Also, it looks like you're just adding the user identities into the select placement attributes so you really don't need to modify the filtered attributes (i think). You can just pull the identities out the of the user and just add them into the select placements attributes. |
||
|
|
||
| var selectPlacementsAttributes = mergeObjects( | ||
| filteredAttributes, | ||
| optimizelyAttributes, | ||
|
|
@@ -177,6 +209,7 @@ var constructor = function () { | |
|
|
||
| function onUserIdentified(filteredUser) { | ||
| self.filteredUser = filteredUser; | ||
| self.filters.filteredUser = filteredUser; | ||
|
alexs-mparticle marked this conversation as resolved.
|
||
| self.userAttributes = filteredUser.getAllUserAttributes(); | ||
| } | ||
|
|
||
|
|
@@ -200,7 +233,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; | ||
|
|
||
|
|
@@ -218,7 +250,6 @@ var constructor = function () { | |
| self.filteredUser = roktFilters.filteredUser; | ||
| } | ||
|
alexs-mparticle marked this conversation as resolved.
|
||
| } | ||
|
|
||
| // Attaches the kit to the Rokt manager | ||
| window.mParticle.Rokt.attachKit(self); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -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: [], | ||||||
|
|
@@ -620,6 +623,309 @@ describe('Rokt Forwarder', () => { | |||||
| }, | ||||||
| }); | ||||||
| }); | ||||||
|
|
||||||
| describe('Identity handling', () => { | ||||||
|
rmi22186 marked this conversation as resolved.
|
||||||
| 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; | ||||||
| }, | ||||||
| }; | ||||||
| }); | ||||||
|
|
||||||
| it('should handle case when userIdentities is null but userAttributes exist', async () => { | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| window.mParticle.Rokt.filters = { | ||||||
| userAttributeFilters: [], | ||||||
| filterUserAttributes: function (attributes) { | ||||||
| return attributes; | ||||||
| }, | ||||||
| filteredUser: { | ||||||
| getMPID: function () { | ||||||
| return 'abc'; | ||||||
| }, | ||||||
| getUserIdentities: function () { | ||||||
| return { userIdentities: {} }; | ||||||
| }, | ||||||
| }, | ||||||
| }; | ||||||
|
|
||||||
| // 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: 'abc', | ||||||
| } | ||||||
| ); | ||||||
| }); | ||||||
|
|
||||||
| it('should handle case when userAttributes is null but userIdentities exist', async () => { | ||||||
|
rmi22186 marked this conversation as resolved.
Outdated
|
||||||
| 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 handle case when both userAttributes and userIdentities exist', async () => { | ||||||
|
rmi22186 marked this conversation as resolved.
Outdated
|
||||||
| 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', | ||||||
| }, | ||||||
| }; | ||||||
| }, | ||||||
| }, | ||||||
| }; | ||||||
|
|
||||||
| // 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', | ||||||
| } | ||||||
| ); | ||||||
| }); | ||||||
|
|
||||||
| it('should handle case when filteredUser is null', async () => { | ||||||
|
rmi22186 marked this conversation as resolved.
Outdated
|
||||||
| 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 handle case when getUserIdentities function does not exist', async () => { | ||||||
|
rmi22186 marked this conversation as resolved.
Outdated
|
||||||
| 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', | ||||||
| } | ||||||
| ); | ||||||
| }); | ||||||
| }); | ||||||
| }); | ||||||
|
|
||||||
| describe('#setUserAttribute', () => { | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the purpose of this code change is to extract the user identities into the selectPlacement attributes, this function should a wrapper around
filteredUser.getUserIdentities().userIdentitiesthat simply returns the identities to be merged later.It shouldn't be mutating the attributes at all, which can lead to side effects.