From 0540240a311b953c2ffa5ab427aeae7532a0d515 Mon Sep 17 00:00:00 2001 From: Ian Flournoy Date: Mon, 27 Apr 2020 21:04:09 -0400 Subject: [PATCH 1/6] Add unit coverage for parrableIdSystem getId callback --- test/spec/modules/parrableIdSystem_spec.js | 66 +++++++++++++++++++--- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/test/spec/modules/parrableIdSystem_spec.js b/test/spec/modules/parrableIdSystem_spec.js index 93415126a0a..9321c342678 100644 --- a/test/spec/modules/parrableIdSystem_spec.js +++ b/test/spec/modules/parrableIdSystem_spec.js @@ -1,15 +1,19 @@ import { expect } from 'chai'; -import {config} from 'src/config.js'; +import { config } from 'src/config.js'; import * as utils from 'src/utils.js'; import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js'; import { parrableIdSubmodule } from 'modules/parrableIdSystem.js'; import { newStorageManager } from 'src/storageManager.js'; +import { getRefererInfo } from 'src/refererDetection.js'; + +import { server } from 'test/mocks/xhr'; const storage = newStorageManager(); const EXPIRED_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:01 GMT'; const P_COOKIE_NAME = '_parrable_eid'; -const P_COOKIE_VALUE = '01.1563917337.test-eid'; +const P_COOKIE_EID = '01.1563917337.test-eid'; +const P_XHR_EID = '01.1588030911.test-new-eid' const P_CONFIG_MOCK = { name: 'parrableId', params: { @@ -31,6 +35,7 @@ describe('Parrable ID System', function() { } } } + function getAdUnitMock(code = 'adUnit-code') { return { code, @@ -46,33 +51,76 @@ describe('Parrable ID System', function() { }; } + describe('parrableIdSystem.getId()', function() { + let submoduleCallback; + let callbackSpy = sinon.spy(); + + beforeEach(function() { + submoduleCallback = parrableIdSubmodule.getId( + P_CONFIG_MOCK.params, + null, + P_COOKIE_EID + ).callback; + callbackSpy.reset(); + }); + + it('returns a callback used to refresh the ID', function() { + expect(submoduleCallback).to.be.a('function'); + }); + + it('invoked callback creates an xhr request to Parrable with id and telemetry', function() { + submoduleCallback(callbackSpy); + + let request = server.requests[0]; + let queryParams = utils.parseQS(request.url.split('?')[1]); + let data = JSON.parse(atob(queryParams.data)); + + expect(request.url).to.contain('h.parrable.com/prebid'); + expect(data).to.deep.equal({ + eid: P_COOKIE_EID, + trackers: P_CONFIG_MOCK.params.partner.split(','), + url: getRefererInfo().referer + }); + }); + + it('callback responds with updated eid from Parrable backend', function() { + submoduleCallback(callbackSpy); + server.requests[0].respond(200, + { 'Content-Type': 'text/plain' }, + JSON.stringify({ eid: P_XHR_EID }) + ); + expect(callbackSpy.calledWith(P_XHR_EID)).to.be.true; + }); + }); + describe('Parrable ID in Bid Request', function() { let adUnits; beforeEach(function() { adUnits = [getAdUnitMock()]; - }); - - it('should append parrableid to bid request', function(done) { // simulate existing browser local storage values storage.setCookie( P_COOKIE_NAME, - P_COOKIE_VALUE, + P_COOKIE_EID, (new Date(Date.now() + 5000).toUTCString()) ); - setSubmoduleRegistry([parrableIdSubmodule]); init(config); config.setConfig(getConfigMock()); + }); + + afterEach(function() { + storage.setCookie(P_COOKIE_NAME, '', EXPIRED_COOKIE_DATE); + }); + it('provides the parrableid in the bid request', function(done) { requestBidsHook(function() { adUnits.forEach(unit => { unit.bids.forEach(bid => { expect(bid).to.have.deep.nested.property('userId.parrableid'); - expect(bid.userId.parrableid).to.equal(P_COOKIE_VALUE); + expect(bid.userId.parrableid).to.equal(P_COOKIE_EID); }); }); - storage.setCookie(P_COOKIE_NAME, '', EXPIRED_COOKIE_DATE); done(); }, { adUnits }); }); From 4af9a6f3e85751f9ea04ee93c32077c054e38b30 Mon Sep 17 00:00:00 2001 From: Ian Flournoy Date: Wed, 29 Apr 2020 14:06:51 -0400 Subject: [PATCH 2/6] PBID-14: Pass uspString to Parrable as us_privacy query parameter --- modules/parrableIdSystem.js | 9 ++- test/spec/modules/parrableIdSystem_spec.js | 64 +++++++++++++++++----- 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/modules/parrableIdSystem.js b/modules/parrableIdSystem.js index cc569a79062..e4e8fb5c5f4 100644 --- a/modules/parrableIdSystem.js +++ b/modules/parrableIdSystem.js @@ -9,6 +9,7 @@ import * as utils from '../src/utils.js' import { ajax } from '../src/ajax.js'; import { submodule } from '../src/hook.js'; import { getRefererInfo } from '../src/refererDetection.js'; +import { uspDataHandler } from '../src/adapterManager.js'; const PARRABLE_URL = 'https://h.parrable.com/prebid'; @@ -24,10 +25,11 @@ function isValidConfig(configParams) { return true; } -function fetchId(configParams, consentData, currentStoredId) { +function fetchId(configParams, currentStoredId) { if (!isValidConfig(configParams)) return; const refererInfo = getRefererInfo(); + const uspString = uspDataHandler.getConsentData(); const data = { eid: currentStoredId || null, @@ -37,6 +39,7 @@ function fetchId(configParams, consentData, currentStoredId) { const searchParams = { data: btoa(JSON.stringify(data)), + us_privacy: uspString, _rand: Math.random() }; @@ -88,8 +91,8 @@ export const parrableIdSubmodule = { * @param {ConsentData} [consentData] * @returns {function(callback:function)} */ - getId(configParams, consentData, currentStoredId) { - return fetchId(configParams, consentData, currentStoredId); + getId(configParams, gdprConsentData, currentStoredId) { + return fetchId(configParams, currentStoredId); } }; diff --git a/test/spec/modules/parrableIdSystem_spec.js b/test/spec/modules/parrableIdSystem_spec.js index 9321c342678..9595cba1700 100644 --- a/test/spec/modules/parrableIdSystem_spec.js +++ b/test/spec/modules/parrableIdSystem_spec.js @@ -1,11 +1,11 @@ import { expect } from 'chai'; import { config } from 'src/config.js'; import * as utils from 'src/utils.js'; -import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js'; -import { parrableIdSubmodule } from 'modules/parrableIdSystem.js'; import { newStorageManager } from 'src/storageManager.js'; import { getRefererInfo } from 'src/refererDetection.js'; - +import * as consentUsp from 'modules/consentManagementUsp.js'; +import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js'; +import { parrableIdSubmodule } from 'modules/parrableIdSystem.js'; import { server } from 'test/mocks/xhr'; const storage = newStorageManager(); @@ -52,45 +52,79 @@ describe('Parrable ID System', function() { } describe('parrableIdSystem.getId()', function() { - let submoduleCallback; let callbackSpy = sinon.spy(); beforeEach(function() { - submoduleCallback = parrableIdSubmodule.getId( - P_CONFIG_MOCK.params, - null, - P_COOKIE_EID - ).callback; callbackSpy.reset(); }); it('returns a callback used to refresh the ID', function() { - expect(submoduleCallback).to.be.a('function'); + let getIdResponse = parrableIdSubmodule.getId( + P_CONFIG_MOCK.params, + null, + P_COOKIE_EID + ); + expect(getIdResponse.callback).to.be.a('function'); }); - it('invoked callback creates an xhr request to Parrable with id and telemetry', function() { - submoduleCallback(callbackSpy); + it('callback creates xhr to Parrable that synchronizes the ID', function() { + let getIdCallback = parrableIdSubmodule.getId( + P_CONFIG_MOCK.params, + null, + P_COOKIE_EID + ).callback; + + getIdCallback(callbackSpy); let request = server.requests[0]; let queryParams = utils.parseQS(request.url.split('?')[1]); let data = JSON.parse(atob(queryParams.data)); expect(request.url).to.contain('h.parrable.com/prebid'); + expect(queryParams.us_privacy).to.equal('null'); expect(data).to.deep.equal({ eid: P_COOKIE_EID, trackers: P_CONFIG_MOCK.params.partner.split(','), url: getRefererInfo().referer }); - }); - it('callback responds with updated eid from Parrable backend', function() { - submoduleCallback(callbackSpy); server.requests[0].respond(200, { 'Content-Type': 'text/plain' }, JSON.stringify({ eid: P_XHR_EID }) ); + expect(callbackSpy.calledWith(P_XHR_EID)).to.be.true; }); + + it('passes the uspString to Parrable', function(done) { + let adUnits = [getAdUnitMock()]; + let uspString = '1YNN'; + let consentManagementConfig = { + usp: { + cmpApi: 'static', + consentData: { + getUSPData: { + uspString + } + } + } + }; + + // Outside of tests the consentManagementUsp module is run at priority 50 + // in the requestBids hook, where userId runs at 40 (later than 50) + // So when userId module collects userIdSystem callbacks the Usp data + // should be present. + consentUsp.setConsentConfig(consentManagementConfig); + consentUsp.requestBidsHook(function() { + parrableIdSubmodule.getId( + P_CONFIG_MOCK.params, + null, + P_COOKIE_EID + ).callback(callbackSpy); + expect(server.requests[0].url).to.contain('us_privacy=' + uspString); + done(); + }, { adUnits }); + }); }); describe('Parrable ID in Bid Request', function() { From 11b457b27d473a8220f01cd7dcb44190b77446bb Mon Sep 17 00:00:00 2001 From: Ian Flournoy Date: Thu, 30 Apr 2020 13:02:23 -0400 Subject: [PATCH 3/6] PBID-14: Simplify parrableIdSystem us_privacy test --- test/spec/modules/parrableIdSystem_spec.js | 39 ++++++---------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/test/spec/modules/parrableIdSystem_spec.js b/test/spec/modules/parrableIdSystem_spec.js index 9595cba1700..317f8be7b2f 100644 --- a/test/spec/modules/parrableIdSystem_spec.js +++ b/test/spec/modules/parrableIdSystem_spec.js @@ -3,7 +3,7 @@ import { config } from 'src/config.js'; import * as utils from 'src/utils.js'; import { newStorageManager } from 'src/storageManager.js'; import { getRefererInfo } from 'src/refererDetection.js'; -import * as consentUsp from 'modules/consentManagementUsp.js'; +import { uspDataHandler } from 'src/adapterManager.js'; import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js'; import { parrableIdSubmodule } from 'modules/parrableIdSystem.js'; import { server } from 'test/mocks/xhr'; @@ -55,7 +55,7 @@ describe('Parrable ID System', function() { let callbackSpy = sinon.spy(); beforeEach(function() { - callbackSpy.reset(); + callbackSpy.resetHistory(); }); it('returns a callback used to refresh the ID', function() { @@ -96,34 +96,15 @@ describe('Parrable ID System', function() { expect(callbackSpy.calledWith(P_XHR_EID)).to.be.true; }); - it('passes the uspString to Parrable', function(done) { - let adUnits = [getAdUnitMock()]; + it('passes the uspString to Parrable', function() { let uspString = '1YNN'; - let consentManagementConfig = { - usp: { - cmpApi: 'static', - consentData: { - getUSPData: { - uspString - } - } - } - }; - - // Outside of tests the consentManagementUsp module is run at priority 50 - // in the requestBids hook, where userId runs at 40 (later than 50) - // So when userId module collects userIdSystem callbacks the Usp data - // should be present. - consentUsp.setConsentConfig(consentManagementConfig); - consentUsp.requestBidsHook(function() { - parrableIdSubmodule.getId( - P_CONFIG_MOCK.params, - null, - P_COOKIE_EID - ).callback(callbackSpy); - expect(server.requests[0].url).to.contain('us_privacy=' + uspString); - done(); - }, { adUnits }); + uspDataHandler.setConsentData(uspString); + parrableIdSubmodule.getId( + P_CONFIG_MOCK.params, + null, + P_COOKIE_EID + ).callback(callbackSpy); + expect(server.requests[0].url).to.contain('us_privacy=' + uspString); }); }); From 914503eef30718bf671622d87236e93184492b84 Mon Sep 17 00:00:00 2001 From: Ian Flournoy Date: Thu, 30 Apr 2020 13:40:37 -0400 Subject: [PATCH 4/6] PBID-14: Only send us_privacy to Parrable when a value exists --- modules/parrableIdSystem.js | 5 ++++- test/spec/modules/parrableIdSystem_spec.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/parrableIdSystem.js b/modules/parrableIdSystem.js index e4e8fb5c5f4..ba5fae81952 100644 --- a/modules/parrableIdSystem.js +++ b/modules/parrableIdSystem.js @@ -39,10 +39,13 @@ function fetchId(configParams, currentStoredId) { const searchParams = { data: btoa(JSON.stringify(data)), - us_privacy: uspString, _rand: Math.random() }; + if (uspString) { + searchParams.us_privacy = uspString; + } + const options = { method: 'GET', withCredentials: true diff --git a/test/spec/modules/parrableIdSystem_spec.js b/test/spec/modules/parrableIdSystem_spec.js index 317f8be7b2f..d0bd75a9b2d 100644 --- a/test/spec/modules/parrableIdSystem_spec.js +++ b/test/spec/modules/parrableIdSystem_spec.js @@ -81,7 +81,7 @@ describe('Parrable ID System', function() { let data = JSON.parse(atob(queryParams.data)); expect(request.url).to.contain('h.parrable.com/prebid'); - expect(queryParams.us_privacy).to.equal('null'); + expect(queryParams).to.not.have.property('us_privacy'); expect(data).to.deep.equal({ eid: P_COOKIE_EID, trackers: P_CONFIG_MOCK.params.partner.split(','), From 43724a336f742e8ad21dfbf0c7ffc84c8fd61ef6 Mon Sep 17 00:00:00 2001 From: Ian Flournoy Date: Tue, 5 May 2020 16:19:41 -0400 Subject: [PATCH 5/6] Remove path check from parrableIdSystem url test --- test/spec/modules/parrableIdSystem_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/parrableIdSystem_spec.js b/test/spec/modules/parrableIdSystem_spec.js index d0bd75a9b2d..4a02e16362c 100644 --- a/test/spec/modules/parrableIdSystem_spec.js +++ b/test/spec/modules/parrableIdSystem_spec.js @@ -80,7 +80,7 @@ describe('Parrable ID System', function() { let queryParams = utils.parseQS(request.url.split('?')[1]); let data = JSON.parse(atob(queryParams.data)); - expect(request.url).to.contain('h.parrable.com/prebid'); + expect(request.url).to.contain('h.parrable.com'); expect(queryParams).to.not.have.property('us_privacy'); expect(data).to.deep.equal({ eid: P_COOKIE_EID, From 8f717daeae8762b3fd59b2773b985df29f7dee96 Mon Sep 17 00:00:00 2001 From: Ian Flournoy Date: Mon, 11 May 2020 09:52:35 -0400 Subject: [PATCH 6/6] Add missing extension to mock xhr import --- test/spec/modules/parrableIdSystem_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/parrableIdSystem_spec.js b/test/spec/modules/parrableIdSystem_spec.js index 4a02e16362c..662f63f6638 100644 --- a/test/spec/modules/parrableIdSystem_spec.js +++ b/test/spec/modules/parrableIdSystem_spec.js @@ -6,7 +6,7 @@ import { getRefererInfo } from 'src/refererDetection.js'; import { uspDataHandler } from 'src/adapterManager.js'; import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js'; import { parrableIdSubmodule } from 'modules/parrableIdSystem.js'; -import { server } from 'test/mocks/xhr'; +import { server } from 'test/mocks/xhr.js'; const storage = newStorageManager();