Skip to content

Commit 8418e83

Browse files
feat: Add hashAttributes method (#24)
1 parent fe62270 commit 8418e83

3 files changed

Lines changed: 180 additions & 9 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"lint": "eslint src/ test/src/",
1515
"lint:fix": "eslint src/ test/src/ --fix",
1616
"watch": "rollup --config rollup.config.js -w",
17-
"watch:test": "rollup --config rollup.test.config.js -w",
17+
"watch:tests": "rollup --config rollup.test.config.js -w",
1818
"test": "npm run build && npm run build:test && karma start test/karma.config.js",
1919
"test:debug": "npm run build && npm run build:test && DEBUG=true karma start test/karma.config.js"
2020
},

src/Rokt-Kit.js

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,21 @@ var constructor = function () {
3030
self.filteredUser = {};
3131
self.userAttributes = {};
3232

33+
/**
34+
* Passes attributes to the Rokt Web SDK for client-side hashing
35+
* @see https://docs.rokt.com/developers/integration-guides/web/library/integration-launcher#hash-attributes
36+
* @param {Object} attributes - The attributes to be hashed
37+
* @returns {Promise<Object|null>} A Promise resolving to the
38+
* hashed attributes from the launcher, or `null` if the kit is not initialized
39+
*/
40+
function hashAttributes(attributes) {
41+
if (!isInitialized()) {
42+
console.error('Rokt Kit: Not initialized');
43+
return null;
44+
}
45+
return self.launcher.hashAttributes(attributes);
46+
}
47+
3348
function initForwarder(
3449
settings,
3550
_service,
@@ -81,12 +96,15 @@ var constructor = function () {
8196
}
8297
}
8398

99+
/**
100+
* Selects placements for Rokt Web SDK with merged attributes, filters, and experimentation options
101+
* @see https://docs.rokt.com/developers/integration-guides/web/library/select-placements-options/
102+
* @param {Object} options - The options object for selecting placements containing:
103+
* - identifier {string}: The placement identifier
104+
* - attributes {Object}: Optional attributes to merge with existing attributes
105+
* @returns {Promise<void>} A Promise resolving to the Rokt launcher's selectPlacements method with processed attributes
106+
*/
84107
function selectPlacements(options) {
85-
// https://docs.rokt.com/developers/integration-guides/web/library/select-placements-options/
86-
// options should contain:
87-
// - identifier
88-
// - attributes
89-
90108
var attributes = (options && options.attributes) || {};
91109
var placementAttributes = mergeObjects(self.userAttributes, attributes);
92110

@@ -192,9 +210,6 @@ var constructor = function () {
192210
});
193211
}
194212

195-
// Called by the mParticle Rokt Manager
196-
this.selectPlacements = selectPlacements;
197-
198213
// mParticle Kit Callback Methods
199214
function fetchOptimizely() {
200215
var forwarders = window.mParticle
@@ -236,10 +251,27 @@ var constructor = function () {
236251
}
237252
return {};
238253
}
254+
255+
// Called by the mParticle Rokt Manager
256+
this.selectPlacements = selectPlacements;
257+
this.hashAttributes = hashAttributes;
258+
259+
// Kit Callback Methods
239260
this.init = initForwarder;
240261
this.setUserAttribute = setUserAttribute;
241262
this.onUserIdentified = onUserIdentified;
242263
this.removeUserAttribute = removeUserAttribute;
264+
265+
/**
266+
* Checks if the kit is properly initialized and ready for use.
267+
* Both conditions must be true:
268+
* 1. self.isInitialized - Set after successful initialization of the kit
269+
* 2. self.launcher - The Rokt launcher instance must be available
270+
* @returns {boolean} Whether the kit is fully initialized
271+
*/
272+
function isInitialized() {
273+
return !!(self.isInitialized && self.launcher);
274+
}
243275
};
244276

245277
function getId() {

test/src/tests.js

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,145 @@ describe('Rokt Forwarder', () => {
189189
});
190190
});
191191

192+
describe('#hashAttributes', () => {
193+
beforeEach(() => {
194+
window.Rokt = new MockRoktForwarder();
195+
window.mParticle.Rokt = window.Rokt;
196+
window.mParticle.Rokt.attachKitCalled = false;
197+
window.mParticle.Rokt.attachKit = async (kit) => {
198+
window.mParticle.Rokt.attachKitCalled = true;
199+
window.mParticle.Rokt.kit = kit;
200+
Promise.resolve();
201+
};
202+
window.mParticle.forwarder.launcher = {
203+
hashAttributes: function (attributes) {
204+
// Mocking the hashAttributes method to show that
205+
// the attributes will be transformed by the launcher's
206+
// hashAttributes method.
207+
const hashedAttributes = {};
208+
for (const key in attributes) {
209+
if (attributes.hasOwnProperty(key)) {
210+
hashedAttributes[key + '-hash'] =
211+
'hashed-' + attributes[key];
212+
}
213+
}
214+
window.mParticle.Rokt.hashedAttributes = hashedAttributes;
215+
window.mParticle.Rokt.hashAttributesCalled = true;
216+
217+
return Promise.resolve(hashedAttributes);
218+
},
219+
};
220+
});
221+
222+
it('should call launcher.hashAttributes with passed through attributes when fully initialized', function () {
223+
// Ensure both initialization conditions are met
224+
window.mParticle.forwarder.isInitialized = true;
225+
window.mParticle.forwarder.launcher = {
226+
hashAttributes: function (attributes) {
227+
window.mParticle.Rokt.hashAttributesOptions = attributes;
228+
window.mParticle.Rokt.hashAttributesCalled = true;
229+
return {
230+
'test-attribute': 'hashed-value',
231+
};
232+
},
233+
};
234+
235+
var attributes = {
236+
'test-attribute': 'test-value',
237+
};
238+
239+
window.mParticle.forwarder.hashAttributes(attributes);
240+
241+
window.Rokt.hashAttributesCalled.should.equal(true);
242+
window.Rokt.hashAttributesOptions.should.deepEqual(attributes);
243+
});
244+
245+
it('should return null when launcher exists but kit is not initialized', function () {
246+
// Set launcher but ensure isInitialized is false
247+
window.mParticle.forwarder.isInitialized = false;
248+
window.mParticle.forwarder.launcher = {
249+
hashAttributes: function () {},
250+
};
251+
252+
var result = window.mParticle.forwarder.hashAttributes({
253+
'test-attribute': 'test-value',
254+
});
255+
256+
(result === null).should.equal(true);
257+
});
258+
259+
it('should log an error when called before initialization', function () {
260+
var errorLogged = false;
261+
var errorMessage = null;
262+
window.console.error = function (message) {
263+
errorLogged = true;
264+
errorMessage = message;
265+
};
266+
267+
// Ensure kit is not initialized
268+
window.mParticle.forwarder.isInitialized = false;
269+
window.mParticle.forwarder.launcher = null;
270+
271+
window.mParticle.forwarder.hashAttributes({
272+
'test-attribute': 'test-value',
273+
});
274+
275+
errorLogged.should.equal(true);
276+
errorMessage.should.equal('Rokt Kit: Not initialized');
277+
});
278+
279+
it('should return null when kit is initialized but launcher is missing', function () {
280+
// Mock isInitialized but remove launcher
281+
window.mParticle.forwarder.isInitialized = true;
282+
window.mParticle.forwarder.launcher = null;
283+
284+
var result = window.mParticle.forwarder.hashAttributes({
285+
'test-attribute': 'test-value',
286+
});
287+
288+
(result === null).should.equal(true);
289+
});
290+
291+
it('should log an error when kit is initialized but launcher is missing', function () {
292+
var errorLogged = false;
293+
var errorMessage = null;
294+
window.console.error = function (message) {
295+
errorLogged = true;
296+
errorMessage = message;
297+
};
298+
299+
window.mParticle.forwarder.isInitialized = true;
300+
window.mParticle.forwarder.launcher = null;
301+
302+
window.mParticle.forwarder.hashAttributes({
303+
'test-attribute': 'test-value',
304+
});
305+
306+
errorLogged.should.equal(true);
307+
errorMessage.should.equal('Rokt Kit: Not initialized');
308+
});
309+
310+
it('should return hashed attributes from launcher', async () => {
311+
await window.mParticle.forwarder.init(
312+
{
313+
accountId: '123456',
314+
},
315+
reportService.cb,
316+
true,
317+
null,
318+
{}
319+
);
320+
321+
const result = await window.mParticle.forwarder.hashAttributes({
322+
'test-attribute': 'test-value',
323+
});
324+
325+
result.should.deepEqual({
326+
'test-attribute-hash': 'hashed-test-value',
327+
});
328+
});
329+
});
330+
192331
describe('#selectPlacements', () => {
193332
beforeEach(() => {
194333
window.Rokt = new MockRoktForwarder();

0 commit comments

Comments
 (0)