From fc95a5257e500832e2d6b1ac7bf9cd5c3dd5210c Mon Sep 17 00:00:00 2001 From: Anand Venkatraman Date: Wed, 23 May 2018 23:24:56 +0530 Subject: [PATCH] Consent Management module bug fix. (#2588) * ET-1691: Pulsepoint Analytics adapter for Prebid. (#1) * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: Adding pulsepoint analytics and tests for pulsepoint adapter * ET-1691: cleanup * ET-1691: minor * ET-1691: revert package.json change * Adding bidRequest to bidFactory.createBid method as per https://github.com/prebid/Prebid.js/issues/509 * ET-1765: Adding support for additional params in PulsePoint adapter (#2) * ET-1850: Fixing https://github.com/prebid/Prebid.js/issues/866 * Minor fix * Adding mandatory parameters to Bid * GDPR Bug Fix with String response * minor --- modules/consentManagement.js | 3 +- test/spec/modules/consentManagement_spec.js | 97 ++++++++++++++------- 2 files changed, 68 insertions(+), 32 deletions(-) diff --git a/modules/consentManagement.js b/modules/consentManagement.js index 2a47bb25899..f4eedd57cfd 100644 --- a/modules/consentManagement.js +++ b/modules/consentManagement.js @@ -8,6 +8,7 @@ import * as utils from 'src/utils'; import { config } from 'src/config'; import { gdprDataHandler } from 'src/adaptermanager'; import includes from 'core-js/library/fn/array/includes'; +import strIncludes from 'core-js/library/fn/string/includes'; const DEFAULT_CMP = 'iab'; const DEFAULT_CONSENT_TIMEOUT = 10000; @@ -132,7 +133,7 @@ function lookupIabConsent(cmpSuccess, cmpError, adUnits) { function readPostMessageResponse(event) { // small customization to prevent reading strings from other sources that aren't JSON.stringified - let json = (typeof event.data === 'string' && includes(event.data, 'cmpReturn')) ? JSON.parse(event.data) : event.data; + let json = (typeof event.data === 'string' && strIncludes(event.data, 'cmpReturn')) ? JSON.parse(event.data) : event.data; if (json.__cmpReturn) { let i = json.__cmpReturn; cmpCallbacks[i.callId](i.returnValue, i.success); diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index eb1614e4965..18df72f044d 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -201,60 +201,95 @@ describe('consentManagement', function () { describe('CMP workflow for iframed page', () => { let eventStub = sinon.stub(); - let cmpStub = sinon.stub(); + let postMessageStub = sinon.stub(); + let ifr = null; beforeEach(() => { didHookReturn = false; - window.__cmp = function() {}; sinon.stub(utils, 'logError'); sinon.stub(utils, 'logWarn'); + ifr = createIFrameMarker(); }); afterEach(() => { config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); eventStub.restore(); - cmpStub.restore(); + postMessageStub.restore(); delete window.__cmp; utils.logError.restore(); utils.logWarn.restore(); resetConsentData(); + document.body.removeChild(ifr); }); - it('should return the consent string from a postmessage + addEventListener response', () => { - let testConsentData = { - data: { - __cmpReturn: { - returnValue: { - gdprApplies: true, - metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' - } + function createIFrameMarker() { + var ifr = document.createElement('iframe'); + ifr.width = 0; + ifr.height = 0; + ifr.name = '__cmpLocator'; + document.body.appendChild(ifr); + return ifr; + } + + testIFramedPage('with/JSON response', { + data: { + __cmpReturn: { + returnValue: { + gdprApplies: true, + metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' } } - }; - eventStub = sinon.stub(window, 'addEventListener').callsFake((...args) => { - args[1](testConsentData); - }); - cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { - args[2]({ - gdprApplies: true, - metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' + } + }, false); + + testIFramedPage('with/String response', { + data: { + __cmpReturn: { + returnValue: { + gdprApplies: true, + metadata: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' + } + } + } + }, true); + + function testIFramedPage(testName, testConsentData, messageFormatString) { + it(`should return the consent string from a postmessage + addEventListener response - ${testName}`, () => { + let messageListener; + eventStub = sinon.stub(window, 'addEventListener').callsFake((...args) => { + // save reference to event listener for message + // so we can return the data when the message arrives via 'postMessage' + messageListener = args[1]; + }); + // when the iframed window sends a message to the window + // containing the CMP, intercept it and respond back with data + // on the message listener. + postMessageStub = sinon.stub(window, 'postMessage').callsFake((...args) => { + if (messageListener && args[0] && args[0].__cmpCall) { + // take the callId from request and stamp it on the response. + testConsentData.data.__cmpReturn.callId = args[0].__cmpCall.callId; + // serialize the data part to String if requested + messageListener(messageFormatString ? { + data: JSON.stringify(testConsentData.data) + } : testConsentData); + } }); - }); - setConfig(goodConfigWithAllowAuction); + setConfig(goodConfigWithAllowAuction); - requestBidsHook({}, () => { - didHookReturn = true; - }); - let consent = gdprDataHandler.getConsentData(); + requestBidsHook({}, () => { + didHookReturn = true; + }); + let consent = gdprDataHandler.getConsentData(); - sinon.assert.notCalled(utils.logWarn); - sinon.assert.notCalled(utils.logError); - expect(didHookReturn).to.be.true; - expect(consent.consentString).to.equal('BOJy+UqOJy+UqABAB+AAAAAZ+A=='); - expect(consent.gdprApplies).to.be.true; - }); + sinon.assert.notCalled(utils.logWarn); + sinon.assert.notCalled(utils.logError); + expect(didHookReturn).to.be.true; + expect(consent.consentString).to.equal('BOJy+UqOJy+UqABAB+AAAAAZ+A=='); + expect(consent.gdprApplies).to.be.true; + }); + } }); describe('CMP workflow for normal pages:', () => {