From 4b279553d290bb7d5bcaa144216f836e5fd51364 Mon Sep 17 00:00:00 2001 From: Yevhenii Melnyk Date: Tue, 29 Sep 2020 20:50:44 +0200 Subject: [PATCH 1/5] Use pbjs implementation of the cookies, localstorage, ajax and pixel in the liveintent id module. Send gpdr data in the liveintent id module requests. Pass email hashes into the liveintent id. --- modules/liveIntentIdSystem.js | 56 ++++++--- modules/userId/index.js | 2 +- package-lock.json | 41 ++----- package.json | 2 +- test/spec/modules/liveIntentIdSystem_spec.js | 121 ++++++++++++------- 5 files changed, 130 insertions(+), 92 deletions(-) diff --git a/modules/liveIntentIdSystem.js b/modules/liveIntentIdSystem.js index bd2638e5936..1eb6de7c1c8 100644 --- a/modules/liveIntentIdSystem.js +++ b/modules/liveIntentIdSystem.js @@ -5,14 +5,32 @@ * @requires module:modules/userId */ import * as utils from '../src/utils.js'; -import { ajax } from '../src/ajax.js'; +import { triggerPixel } from '../src/utils.js'; +import { ajaxBuilder } from '../src/ajax.js'; import { submodule } from '../src/hook.js'; import { LiveConnect } from 'live-connect-js/cjs/live-connect.js'; -import { uspDataHandler } from '../src/adapterManager.js'; +import { gdprDataHandler, uspDataHandler } from '../src/adapterManager.js'; import { getStorageManager } from '../src/storageManager.js'; const MODULE_NAME = 'liveIntentId'; export const storage = getStorageManager(null, MODULE_NAME); +const calls = { + ajaxGet: (url, onSuccess, onError, timeout) => { + ajaxBuilder(timeout)( + url, + { + success: onSuccess, + error: onError + }, + undefined, + { + method: 'GET', + withCredentials: true + } + ) + }, + pixelGet: triggerPixel +} let eventFired = false; let liveConnect = null; @@ -64,18 +82,30 @@ function initializeLiveConnect(configParams) { if (configParams.partner) { identityResolutionConfig.source = configParams.partner } + if (configParams.ajaxTimeout) { + identityResolutionConfig.ajaxTimeout = configParams.ajaxTimeout; + } const liveConnectConfig = parseLiveIntentCollectorConfig(configParams.liCollectConfig); liveConnectConfig.wrapperName = 'prebid'; liveConnectConfig.identityResolutionConfig = identityResolutionConfig; liveConnectConfig.identifiersToResolve = configParams.identifiersToResolve || []; + if (configParams.emailHash) { + liveConnectConfig.eventSource = { hash: configParams.emailHash } + } const usPrivacyString = uspDataHandler.getConsentData(); if (usPrivacyString) { liveConnectConfig.usPrivacyString = usPrivacyString; } + const gdprConsent = gdprDataHandler.getConsentData() + if (gdprConsent) { + liveConnectConfig.gdprApplies = gdprConsent.gdprApplies ? 1 : 0; + liveConnectConfig.gdprConsent = gdprConsent.consentString; + } - // The second param is the storage object, which means that all LS & Cookie manipulation will go through PBJS utils. - liveConnect = LiveConnect(liveConnectConfig, storage); + // The second param is the storage object, LS & Cookie manipulation uses PBJS utils. + // The third param is the ajax and pixel object, the ajax and pixel use PBJS utils. + liveConnect = LiveConnect(liveConnectConfig, storage, calls); return liveConnect; } @@ -130,11 +160,9 @@ export const liveIntentIdSubmodule = { return; } tryFireEvent(); - // Don't do the internal ajax call, but use the composed url and fire it via PBJS ajax module - const url = liveConnect.resolutionCallUrl(); - const result = function (callback) { - const callbacks = { - success: response => { + const result = function(callback) { + liveConnect.resolve( + response => { let responseObj = {}; if (response) { try { @@ -145,14 +173,14 @@ export const liveIntentIdSubmodule = { } callback(responseObj); }, - error: error => { + error => { utils.logError(`${MODULE_NAME}: ID fetch encountered an error: `, error); callback(); } - }; - ajax(url, callbacks, undefined, { method: 'GET', withCredentials: true }); - }; - return {callback: result}; + ) + } + + return { callback: result }; } }; diff --git a/modules/userId/index.js b/modules/userId/index.js index 14f7ad3599b..97d18ae0c98 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -83,8 +83,8 @@ * @property {(string|undefined)} publisherId - the unique identifier of the publisher in question * @property {(string|undefined)} ajaxTimeout - the number of milliseconds a resolution request can take before automatically being terminated * @property {(array|undefined)} identifiersToResolve - the identifiers from either ls|cookie to be attached to the getId query - * @property {(string|undefined)} providedIdentifierName - defines the name of an identifier that can be found in local storage or in the cookie jar that can be sent along with the getId request. This parameter should be used whenever a customer is able to provide the most stable identifier possible * @property {(LiveIntentCollectConfig|undefined)} liCollectConfig - the config for LiveIntent's collect requests + * @property {(string|undefined)} emailHash - the email hash of the user */ /** diff --git a/package-lock.json b/package-lock.json index 1784b885be9..4c436cff9f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "4.8.0-pre", + "version": "4.10.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -7796,13 +7796,11 @@ "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", "object-inspect": "^1.7.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.0" } }, "es-array-method-boxes-properly": { @@ -7838,6 +7836,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -12076,7 +12075,7 @@ "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", "dev": true, "requires": { - "has-symbols": "^1.0.1" + "has": "^1.0.3" } }, "is-relative": { @@ -15709,9 +15708,8 @@ "dev": true }, "live-connect-js": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/live-connect-js/-/live-connect-js-1.1.10.tgz", - "integrity": "sha512-G/LJKN3b21DZILCQRyataC/znLvJRyogtu7mAkKlkhP9B9UJ8bcOL7ihW/clD2PsT4hVUkeabHhUGsPCmhsjFw==", + "version": "github:LiveIntent/live-connect#6da4ab18239b1df864a1e031652a1274b092175f", + "from": "github:LiveIntent/live-connect#RTA-386", "requires": { "@kiosked/ulid": "^3.0.0", "abab": "^2.0.3", @@ -17484,7 +17482,8 @@ "object-inspect": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true }, "object-is": { "version": "1.1.2", @@ -20696,26 +20695,6 @@ "es-abstract": "^1.17.0-next.1" } }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", diff --git a/package.json b/package.json index fc5a0441ad1..49e832d0dbb 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,6 @@ "fun-hooks": "^0.9.9", "jsencrypt": "^3.0.0-rc.1", "just-clone": "^1.0.2", - "live-connect-js": "1.1.10" + "live-connect-js": "LiveIntent/live-connect#RTA-386" } } diff --git a/test/spec/modules/liveIntentIdSystem_spec.js b/test/spec/modules/liveIntentIdSystem_spec.js index b19d38d5859..d20f133c0d1 100644 --- a/test/spec/modules/liveIntentIdSystem_spec.js +++ b/test/spec/modules/liveIntentIdSystem_spec.js @@ -1,46 +1,52 @@ -import {liveIntentIdSubmodule, reset as resetLiveIntentIdSubmodule, storage} from 'modules/liveIntentIdSystem.js'; +import { liveIntentIdSubmodule, reset as resetLiveIntentIdSubmodule, storage } from 'modules/liveIntentIdSystem.js'; import * as utils from 'src/utils.js'; -import {uspDataHandler} from '../../../src/adapterManager.js'; -import {server} from 'test/mocks/xhr.js'; +import { gdprDataHandler, uspDataHandler } from '../../../src/adapterManager.js'; +import { server } from 'test/mocks/xhr.js'; const PUBLISHER_ID = '89899'; -const defaultConfigParams = {publisherId: PUBLISHER_ID}; -const responseHeader = {'Content-Type': 'application/json'} +const defaultConfigParams = { publisherId: PUBLISHER_ID }; +const responseHeader = { 'Content-Type': 'application/json' } -describe('LiveIntentId', function () { +describe('LiveIntentId', function() { let pixel = {}; let logErrorStub; - let consentDataStub; + let uspConsentDataStub; + let gdprConsentDataStub; let getCookieStub; let getDataFromLocalStorageStub; let imgStub; - beforeEach(function () { + beforeEach(function() { imgStub = sinon.stub(window, 'Image').returns(pixel); getCookieStub = sinon.stub(storage, 'getCookie'); getDataFromLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage'); logErrorStub = sinon.stub(utils, 'logError'); - consentDataStub = sinon.stub(uspDataHandler, 'getConsentData'); + uspConsentDataStub = sinon.stub(uspDataHandler, 'getConsentData'); + gdprConsentDataStub = sinon.stub(gdprDataHandler, 'getConsentData'); }); - afterEach(function () { + afterEach(function() { pixel = {}; imgStub.restore(); getCookieStub.restore(); getDataFromLocalStorageStub.restore(); logErrorStub.restore(); - consentDataStub.restore(); + uspConsentDataStub.restore(); + gdprConsentDataStub.restore(); resetLiveIntentIdSubmodule(); }); - it('should initialize LiveConnect with a us privacy string when getId, and include it in all requests', function () { - consentDataStub.returns('1YNY'); + it('should initialize LiveConnect with a privacy string when getId, and include it in the resolution request', function() { + uspConsentDataStub.returns('1YNY'); + gdprConsentDataStub.returns({ + gdprApplies: true, + consentString: 'consentDataString' + }) let callBackSpy = sinon.spy(); let submoduleCallback = liveIntentIdSubmodule.getId(defaultConfigParams).callback; - expect(pixel.src).to.match(/.*us_privacy=1YNY/); submoduleCallback(callBackSpy); - let request = server.requests[0]; - expect(request.url).to.match(/.*us_privacy=1YNY/); + let request = server.requests[1]; + expect(request.url).to.match(/.*us_privacy=1YNY.*&gdpr=1&gdpr_consent=consentDataString.*/); request.respond( 200, responseHeader, @@ -49,12 +55,25 @@ describe('LiveIntentId', function () { expect(callBackSpy.calledOnce).to.be.true; }); - it('should fire an event when getId', function () { + it('should fire an event when getId', function() { + uspConsentDataStub.returns('1YNY'); + gdprConsentDataStub.returns({ + gdprApplies: true, + consentString: 'consentDataString' + }) liveIntentIdSubmodule.getId(defaultConfigParams); - expect(pixel.src).to.match(/https:\/\/rp.liadm.com\/p\?wpn=prebid.*/) + expect(server.requests[0].url).to.match(/https:\/\/rp.liadm.com\/j\?wpn=prebid.*us_privacy=1YNY.*&gdpr=1&gdpr_consent=consentDataString.*/) }); - it('should initialize LiveConnect with the config params when decode and emit an event', function () { + it('should fire an event when getId and a hash is provided', function() { + liveIntentIdSubmodule.getId({ + ...defaultConfigParams, + emailHash: '58131bc547fb87af94cebdaf3102321f' + }); + expect(server.requests[0].url).to.match(/https:\/\/rp.liadm.com\/j\?.*e=58131bc547fb87af94cebdaf3102321f.+/) + }); + + it('should initialize LiveConnect with the config params when decode and emit an event', function() { liveIntentIdSubmodule.decode({}, { ...defaultConfigParams, ...{ @@ -65,39 +84,51 @@ describe('LiveIntentId', function () { } } }); - expect(pixel.src).to.match(/https:\/\/collector.liveintent.com\/p\?aid=a-0001&wpn=prebid.*/) + expect(server.requests[0].url).to.match(/https:\/\/collector.liveintent.com\/j\?aid=a-0001&wpn=prebid.*/) }); - it('should initialize LiveConnect and emit an event with a us privacy string when decode', function () { - consentDataStub.returns('1YNY'); + it('should initialize LiveConnect and emit an event with a privacy string when decode', function() { + uspConsentDataStub.returns('1YNY'); + gdprConsentDataStub.returns({ + gdprApplies: false, + consentString: 'consentDataString' + }) liveIntentIdSubmodule.decode({}, defaultConfigParams); - expect(pixel.src).to.match(/.*us_privacy=1YNY/); + expect(server.requests[0].url).to.match(/.*us_privacy=1YNY.*&gdpr=0&gdpr_consent=consentDataString.*/); + }); + + it('should fire an event when decode and a hash is provided', function() { + liveIntentIdSubmodule.decode({}, { + ...defaultConfigParams, + emailHash: '58131bc547fb87af94cebdaf3102321f' + }); + expect(server.requests[0].url).to.match(/https:\/\/rp.liadm.com\/j\?.*e=58131bc547fb87af94cebdaf3102321f.+/) }); - it('should not return a decoded identifier when the unifiedId is not present in the value', function () { - const result = liveIntentIdSubmodule.decode({additionalData: 'data'}); + it('should not return a decoded identifier when the unifiedId is not present in the value', function() { + const result = liveIntentIdSubmodule.decode({ additionalData: 'data' }); expect(result).to.be.undefined; }); - it('should fire an event when decode', function () { + it('should fire an event when decode', function() { liveIntentIdSubmodule.decode({}, defaultConfigParams); - expect(pixel.src).to.be.not.null + expect(server.requests[0].url).to.be.not.null }); - it('should initialize LiveConnect and send data only once', function () { + it('should initialize LiveConnect and send data only once', function() { liveIntentIdSubmodule.getId(defaultConfigParams); liveIntentIdSubmodule.decode({}, defaultConfigParams); liveIntentIdSubmodule.getId(defaultConfigParams); liveIntentIdSubmodule.decode({}, defaultConfigParams); - expect(imgStub.calledOnce).to.be.true; + expect(server.requests.length).to.be.eq(1); }); - it('should call the Custom URL of the LiveIntent Identity Exchange endpoint', function () { + it('should call the Custom URL of the LiveIntent Identity Exchange endpoint', function() { getCookieStub.returns(null); let callBackSpy = sinon.spy(); - let submoduleCallback = liveIntentIdSubmodule.getId({...defaultConfigParams, ...{'url': 'https://dummy.liveintent.com/idex'}}).callback; + let submoduleCallback = liveIntentIdSubmodule.getId({ ...defaultConfigParams, ...{ 'url': 'https://dummy.liveintent.com/idex' } }).callback; submoduleCallback(callBackSpy); - let request = server.requests[0]; + let request = server.requests[1]; expect(request.url).to.be.eq('https://dummy.liveintent.com/idex/prebid/89899'); request.respond( 200, @@ -107,7 +138,7 @@ describe('LiveIntentId', function () { expect(callBackSpy.calledOnce).to.be.true; }); - it('should call the default url of the LiveIntent Identity Exchange endpoint, with a partner', function () { + it('should call the default url of the LiveIntent Identity Exchange endpoint, with a partner', function() { getCookieStub.returns(null); let callBackSpy = sinon.spy(); let submoduleCallback = liveIntentIdSubmodule.getId({ @@ -118,7 +149,7 @@ describe('LiveIntentId', function () { } }).callback; submoduleCallback(callBackSpy); - let request = server.requests[0]; + let request = server.requests[1]; expect(request.url).to.be.eq('https://dummy.liveintent.com/idex/rubicon/89899'); request.respond( 200, @@ -128,12 +159,12 @@ describe('LiveIntentId', function () { expect(callBackSpy.calledOnce).to.be.true; }); - it('should call the LiveIntent Identity Exchange endpoint, with no additional query params', function () { + it('should call the LiveIntent Identity Exchange endpoint, with no additional query params', function() { getCookieStub.returns(null); let callBackSpy = sinon.spy(); let submoduleCallback = liveIntentIdSubmodule.getId(defaultConfigParams).callback; submoduleCallback(callBackSpy); - let request = server.requests[0]; + let request = server.requests[1]; expect(request.url).to.be.eq('https://idx.liadm.com/idex/prebid/89899'); request.respond( 200, @@ -143,12 +174,12 @@ describe('LiveIntentId', function () { expect(callBackSpy.calledOnce).to.be.true; }); - it('should log an error and continue to callback if ajax request errors', function () { + it('should log an error and continue to callback if ajax request errors', function() { getCookieStub.returns(null); let callBackSpy = sinon.spy(); let submoduleCallback = liveIntentIdSubmodule.getId(defaultConfigParams).callback; submoduleCallback(callBackSpy); - let request = server.requests[0]; + let request = server.requests[1]; expect(request.url).to.be.eq('https://idx.liadm.com/idex/prebid/89899'); request.respond( 503, @@ -159,13 +190,13 @@ describe('LiveIntentId', function () { expect(callBackSpy.calledOnce).to.be.true; }); - it('should include the LiveConnect identifier when calling the LiveIntent Identity Exchange endpoint', function () { + it('should include the LiveConnect identifier when calling the LiveIntent Identity Exchange endpoint', function() { const oldCookie = 'a-xxxx--123e4567-e89b-12d3-a456-426655440000' getDataFromLocalStorageStub.withArgs('_li_duid').returns(oldCookie); let callBackSpy = sinon.spy(); let submoduleCallback = liveIntentIdSubmodule.getId(defaultConfigParams).callback; submoduleCallback(callBackSpy); - let request = server.requests[0]; + let request = server.requests[1]; expect(request.url).to.be.eq(`https://idx.liadm.com/idex/prebid/89899?duid=${oldCookie}`); request.respond( 200, @@ -175,7 +206,7 @@ describe('LiveIntentId', function () { expect(callBackSpy.calledOnce).to.be.true; }); - it('should include the LiveConnect identifier and additional Identifiers to resolve', function () { + it('should include the LiveConnect identifier and additional Identifiers to resolve', function() { const oldCookie = 'a-xxxx--123e4567-e89b-12d3-a456-426655440000' getDataFromLocalStorageStub.withArgs('_li_duid').returns(oldCookie); getDataFromLocalStorageStub.withArgs('_thirdPC').returns('third-pc'); @@ -188,7 +219,7 @@ describe('LiveIntentId', function () { let callBackSpy = sinon.spy(); let submoduleCallback = liveIntentIdSubmodule.getId(configParams).callback; submoduleCallback(callBackSpy); - let request = server.requests[0]; + let request = server.requests[1]; expect(request.url).to.be.eq(`https://idx.liadm.com/idex/prebid/89899?duid=${oldCookie}&_thirdPC=third-pc`); request.respond( 200, @@ -198,9 +229,9 @@ describe('LiveIntentId', function () { expect(callBackSpy.calledOnce).to.be.true; }); - it('should include an additional identifier value to resolve even if it is an object', function () { + it('should include an additional identifier value to resolve even if it is an object', function() { getCookieStub.returns(null); - getDataFromLocalStorageStub.withArgs('_thirdPC').returns({'key': 'value'}); + getDataFromLocalStorageStub.withArgs('_thirdPC').returns({ 'key': 'value' }); const configParams = { ...defaultConfigParams, ...{ @@ -210,7 +241,7 @@ describe('LiveIntentId', function () { let callBackSpy = sinon.spy(); let submoduleCallback = liveIntentIdSubmodule.getId(configParams).callback; submoduleCallback(callBackSpy); - let request = server.requests[0]; + let request = server.requests[1]; expect(request.url).to.be.eq('https://idx.liadm.com/idex/prebid/89899?_thirdPC=%7B%22key%22%3A%22value%22%7D'); request.respond( 200, From c7b60e999279bc7d537379c68466826b85ca293e Mon Sep 17 00:00:00 2001 From: Yevhenii Melnyk Date: Thu, 1 Oct 2020 11:21:07 +0200 Subject: [PATCH 2/5] Pass gdprApplies as a boolean --- modules/liveIntentIdSystem.js | 2 +- modules/userId/index.js | 2 +- package-lock.json | 46 ++++++++++++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/modules/liveIntentIdSystem.js b/modules/liveIntentIdSystem.js index 1eb6de7c1c8..f16a043024f 100644 --- a/modules/liveIntentIdSystem.js +++ b/modules/liveIntentIdSystem.js @@ -99,7 +99,7 @@ function initializeLiveConnect(configParams) { } const gdprConsent = gdprDataHandler.getConsentData() if (gdprConsent) { - liveConnectConfig.gdprApplies = gdprConsent.gdprApplies ? 1 : 0; + liveConnectConfig.gdprApplies = gdprConsent.gdprApplies; liveConnectConfig.gdprConsent = gdprConsent.consentString; } diff --git a/modules/userId/index.js b/modules/userId/index.js index 97d18ae0c98..b395d3c80b0 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -84,7 +84,7 @@ * @property {(string|undefined)} ajaxTimeout - the number of milliseconds a resolution request can take before automatically being terminated * @property {(array|undefined)} identifiersToResolve - the identifiers from either ls|cookie to be attached to the getId query * @property {(LiveIntentCollectConfig|undefined)} liCollectConfig - the config for LiveIntent's collect requests - * @property {(string|undefined)} emailHash - the email hash of the user + * @property {(string|undefined)} emailHash - if provided, the hashed email address of a user */ /** diff --git a/package-lock.json b/package-lock.json index 4c436cff9f4..da3604f3f51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7800,7 +7800,9 @@ "is-regex": "^1.0.5", "object-inspect": "^1.7.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0" + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" } }, "es-array-method-boxes-properly": { @@ -20695,6 +20697,48 @@ "es-abstract": "^1.17.0-next.1" } }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimleft": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", + "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimstart": "^1.0.0" + } + }, + "string.prototype.trimright": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", + "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimend": "^1.0.0" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", From 9d55da7d211111d68592d9f01985a506f989ee04 Mon Sep 17 00:00:00 2001 From: Yevhenii Melnyk Date: Thu, 1 Oct 2020 11:41:23 +0200 Subject: [PATCH 3/5] Add a test for the triggerPixel --- modules/liveIntentIdSystem.js | 2 +- test/spec/modules/liveIntentIdSystem_spec.js | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/liveIntentIdSystem.js b/modules/liveIntentIdSystem.js index f16a043024f..20990c84b9f 100644 --- a/modules/liveIntentIdSystem.js +++ b/modules/liveIntentIdSystem.js @@ -29,7 +29,7 @@ const calls = { } ) }, - pixelGet: triggerPixel + pixelGet: (url, onload) => triggerPixel(url, onload) } let eventFired = false; diff --git a/test/spec/modules/liveIntentIdSystem_spec.js b/test/spec/modules/liveIntentIdSystem_spec.js index d20f133c0d1..443a5f9c544 100644 --- a/test/spec/modules/liveIntentIdSystem_spec.js +++ b/test/spec/modules/liveIntentIdSystem_spec.js @@ -8,7 +8,6 @@ const defaultConfigParams = { publisherId: PUBLISHER_ID }; const responseHeader = { 'Content-Type': 'application/json' } describe('LiveIntentId', function() { - let pixel = {}; let logErrorStub; let uspConsentDataStub; let gdprConsentDataStub; @@ -17,7 +16,7 @@ describe('LiveIntentId', function() { let imgStub; beforeEach(function() { - imgStub = sinon.stub(window, 'Image').returns(pixel); + imgStub = sinon.stub(utils, 'triggerPixel'); getCookieStub = sinon.stub(storage, 'getCookie'); getDataFromLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage'); logErrorStub = sinon.stub(utils, 'logError'); @@ -26,7 +25,6 @@ describe('LiveIntentId', function() { }); afterEach(function() { - pixel = {}; imgStub.restore(); getCookieStub.restore(); getDataFromLocalStorageStub.restore(); @@ -250,4 +248,10 @@ describe('LiveIntentId', function() { ); expect(callBackSpy.calledOnce).to.be.true; }); + + it('should send an error when the cookie jar throws an unexpected error', function() { + getCookieStub.throws('CookieError', 'A message'); + liveIntentIdSubmodule.getId(defaultConfigParams); + expect(imgStub.getCall(0).args[0]).to.match(/.*ae=.+/); + }); }); From 6eb19b57292c74001eccd6e2c56a769230ae8ab4 Mon Sep 17 00:00:00 2001 From: Yevhenii Melnyk Date: Wed, 14 Oct 2020 12:41:23 +0200 Subject: [PATCH 4/5] Use released live-connect --- package-lock.json | 5 +++-- package.json | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index da3604f3f51..7007b42ac53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15710,8 +15710,9 @@ "dev": true }, "live-connect-js": { - "version": "github:LiveIntent/live-connect#6da4ab18239b1df864a1e031652a1274b092175f", - "from": "github:LiveIntent/live-connect#RTA-386", + "version": "1.1.23", + "resolved": "https://registry.npmjs.org/live-connect-js/-/live-connect-js-1.1.23.tgz", + "integrity": "sha512-alOXlYyDdMXt8zzCIs3+iCrdi6r/69c7YRN3sMETa3b2cCOxep3i9j2O0iepk2hxT5JxiR1MvqlqdWAL9d2Hcg==", "requires": { "@kiosked/ulid": "^3.0.0", "abab": "^2.0.3", diff --git a/package.json b/package.json index 49e832d0dbb..685fbb2aa9d 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,6 @@ "fun-hooks": "^0.9.9", "jsencrypt": "^3.0.0-rc.1", "just-clone": "^1.0.2", - "live-connect-js": "LiveIntent/live-connect#RTA-386" + "live-connect-js": "^1.1.23" } } From 385461a6e6fe2446f7eaf46bd67a6bc91e3a4951 Mon Sep 17 00:00:00 2001 From: Yevhenii Melnyk Date: Wed, 14 Oct 2020 14:08:36 +0200 Subject: [PATCH 5/5] Update tests after the master merge --- package-lock.json | 2 +- test/spec/modules/liveIntentIdSystem_spec.js | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7007b42ac53..e0bceb843e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "4.10.0-pre", + "version": "4.12.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/test/spec/modules/liveIntentIdSystem_spec.js b/test/spec/modules/liveIntentIdSystem_spec.js index 1aed536b2d5..aae60cbcd19 100644 --- a/test/spec/modules/liveIntentIdSystem_spec.js +++ b/test/spec/modules/liveIntentIdSystem_spec.js @@ -60,14 +60,14 @@ describe('LiveIntentId', function() { consentString: 'consentDataString' }) liveIntentIdSubmodule.getId(defaultConfigParams); - expect(server.requests[0].url).to.match(/https:\/\/rp.liadm.com\/j\?wpn=prebid.*us_privacy=1YNY.*&gdpr=1&gdpr_consent=consentDataString.*/) + expect(server.requests[0].url).to.match(/https:\/\/rp.liadm.com\/j\?wpn=prebid.*us_privacy=1YNY.*&gdpr=1&gdpr_consent=consentDataString.*/); }); it('should fire an event when getId and a hash is provided', function() { - liveIntentIdSubmodule.getId({ + liveIntentIdSubmodule.getId({ params: { ...defaultConfigParams, emailHash: '58131bc547fb87af94cebdaf3102321f' - }); + }}); expect(server.requests[0].url).to.match(/https:\/\/rp.liadm.com\/j\?.*e=58131bc547fb87af94cebdaf3102321f.+/) }); @@ -81,8 +81,8 @@ describe('LiveIntentId', function() { collectorUrl: 'https://collector.liveintent.com' } } - }); - expect(server.requests[0].url).to.match(/https:\/\/collector.liveintent.com\/j\?aid=a-0001&wpn=prebid.*/) + }}); + expect(server.requests[0].url).to.match(/https:\/\/collector.liveintent.com\/j\?aid=a-0001&wpn=prebid.*/); }); it('should initialize LiveConnect and emit an event with a privacy string when decode', function() { @@ -96,11 +96,11 @@ describe('LiveIntentId', function() { }); it('should fire an event when decode and a hash is provided', function() { - liveIntentIdSubmodule.decode({}, { - ...defaultConfigParams, + liveIntentIdSubmodule.decode({}, { params: { + ...defaultConfigParams.params, emailHash: '58131bc547fb87af94cebdaf3102321f' - }); - expect(server.requests[0].url).to.match(/https:\/\/rp.liadm.com\/j\?.*e=58131bc547fb87af94cebdaf3102321f.+/) + }}); + expect(server.requests[0].url).to.match(/https:\/\/rp.liadm.com\/j\?.*e=58131bc547fb87af94cebdaf3102321f.+/); }); it('should not return a decoded identifier when the unifiedId is not present in the value', function() {