From bc2ca568a127f3f32093ba56f3091fe0fad6010f Mon Sep 17 00:00:00 2001 From: Marcio Pereira Date: Mon, 10 Apr 2017 18:58:36 +0100 Subject: [PATCH 1/3] ONE Mobile implemented. --- src/adapters/aol.js | 225 ++++++++++++-- src/ajax.js | 3 + test/spec/adapters/aol_spec.js | 539 ++++++++++++++++++++++++--------- 3 files changed, 585 insertions(+), 182 deletions(-) diff --git a/src/adapters/aol.js b/src/adapters/aol.js index 08b27ad562a..9a3d81c2424 100644 --- a/src/adapters/aol.js +++ b/src/adapters/aol.js @@ -2,17 +2,130 @@ const utils = require('../utils.js'); const ajax = require('../ajax.js').ajax; const bidfactory = require('../bidfactory.js'); const bidmanager = require('../bidmanager.js'); +const constants = require('../constants.json'); const AolAdapter = function AolAdapter() { let showCpmAdjustmentWarning = true; const pubapiTemplate = template`${'protocol'}://${'host'}/pubapi/3.0/${'network'}/${'placement'}/${'pageid'}/${'sizeid'}/ADTECH;v=2;cmd=bid;cors=yes;alias=${'alias'}${'bidfloor'};misc=${'misc'}`; + const nexageBaseApiTemplate = template`${'protocol'}://${'host'}/bidRequest?`; + const nexageGetApiTemplate = template`dcn=${'dcn'}&pos=${'pos'}&cmd=bid${'ext'}`; const BIDDER_CODE = 'aol'; - const SERVER_MAP = { + const MP_SERVER_MAP = { us: 'adserver-us.adtech.advertising.com', eu: 'adserver-eu.adtech.advertising.com', as: 'adserver-as.adtech.advertising.com' }; + const NEXAGE_SERVER = 'hb.nexage.com'; + const SYNC_TYPES = { + iframe: 'IFRAME', + img: 'IMG' + }; + + let DOMReady = (() => { + let readyEventFired = false; + return fn => { + let idempotentFn = () => { + if (readyEventFired) { + return; + } + readyEventFired = true; + return fn(); + }; + let doScrollCheck = () => { + if (readyEventFired) { + return; + } + try { + document.documentElement.doScroll('left'); + } catch (e) { + setTimeout(doScrollCheck, 1); + return; + } + return idempotentFn(); + }; + if (document.readyState === "complete") { + return idempotentFn(); + } + if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", idempotentFn, false); + window.addEventListener("load", idempotentFn, false); + } else if (document.attachEvent) { + document.attachEvent("onreadystatechange", idempotentFn); + window.attachEvent("onload", idempotentFn); + let topLevel = false; + try { + topLevel = window.frameElement === null; + } catch (e) { + } + if (document.documentElement.doScroll && topLevel) { + return doScrollCheck(); + } + } + }; + })(); + + function dropSyncCookies(pixels) { + let pixelElements = parsePixelItems(pixels); + renderPixelElements(pixelElements); + } + + function parsePixelItems(pixels) { + let itemsRegExp = /(img|iframe)[\s\S]*?src\s*=\s*("|')(.*?)\2/gi; + let tagNameRegExp = /\w*(?=\s)/; + let srcRegExp = /src=("|')(.*?)\1/; + let pixelsItems = []; + + if (pixels) { + let matchedItems = pixels.match(itemsRegExp); + if (matchedItems) { + matchedItems.forEach(item => { + let tagNameMatches = item.match(tagNameRegExp); + let sourcesPathMatches = item.match(srcRegExp); + if (tagNameMatches && sourcesPathMatches) { + pixelsItems.push({ + tagName: tagNameMatches[0].toUpperCase(), + src: sourcesPathMatches[2] + }); + } + }); + } + } + + return pixelsItems; + } + + function renderPixelElements(pixelsElements) { + pixelsElements.forEach((element) => { + switch (element.tagName) { + case SYNC_TYPES.img: + return renderPixelImage(element); + case SYNC_TYPES.iframe: + return renderPixelIframe(element); + } + }); + } + + function renderPixelImage(pixelsItem) { + let image = new Image(); + image.src = pixelsItem.src; + } + + function renderPixelIframe(pixelsItem) { + let iframe = document.createElement('iframe'); + iframe.width = 1; + iframe.height = 1; + iframe.style.display = 'none'; + iframe.src = pixelsItem.src; + if (document.readyState === 'interactive' || + document.readyState === 'complete') { + document.body.appendChild(iframe); + } else { + DOMReady(() => { + document.body.appendChild(iframe); + }); + } + } function template(strings, ...keys) { return function(...values) { @@ -26,13 +139,13 @@ const AolAdapter = function AolAdapter() { }; } - function _buildPubapiUrl(bid) { + function _buildMarketplaceUrl(bid) { const params = bid.params; const serverParam = params.server; let regionParam = params.region || 'us'; let server; - if (!SERVER_MAP.hasOwnProperty(regionParam)) { + if (!MP_SERVER_MAP.hasOwnProperty(regionParam)) { utils.logWarn(`Unknown region '${regionParam}' for AOL bidder.`); regionParam = 'us'; // Default region. } @@ -40,7 +153,7 @@ const AolAdapter = function AolAdapter() { if (serverParam) { server = serverParam; } else { - server = SERVER_MAP[regionParam]; + server = MP_SERVER_MAP[regionParam]; } // Set region param, used by AOL analytics. @@ -60,6 +173,22 @@ const AolAdapter = function AolAdapter() { }); } + function _buildNexageApiUrl(bid) { + let {dcn, pos} = bid.params; + let nexageApi = nexageBaseApiTemplate({ + protocol: (document.location.protocol === 'https:') ? 'https' : 'http', + host: bid.params.host || NEXAGE_SERVER + }); + if (dcn && pos) { + let ext = ''; + utils._each(bid.params.ext, (value, key) => { + ext += `&${key}=${encodeURIComponent(value)}`; + }); + nexageApi += nexageGetApiTemplate({dcn, pos, ext}); + } + return nexageApi; + } + function _addErrorBidResponse(bid, response = {}) { const bidResponse = bidfactory.createBid(2, bid); bidResponse.bidderCode = BIDDER_CODE; @@ -94,7 +223,11 @@ const AolAdapter = function AolAdapter() { let ad = bidData.adm; if (response.ext && response.ext.pixels) { - ad += response.ext.pixels; + if (bid.params.userSyncOn === constants.EVENTS.BID_RESPONSE) { + dropSyncCookies(response.ext.pixels); + } else { + ad += response.ext.pixels; + } } const bidResponse = bidfactory.createBid(1, bid); @@ -113,40 +246,68 @@ const AolAdapter = function AolAdapter() { bidmanager.addBidResponse(bid.placementCode, bidResponse); } + function _isNexageRequestPost(bid) { + if (bid.params.id && bid.params.imp && bid.params.imp[0]) { + let imp = bid.params.imp[0]; + return imp.id && imp.tagid + && ((imp.banner && imp.banner.w && imp.banner.h) + || (imp.video && imp.video.mimes && imp.video.minduration && imp.video.maxduration)); + } + } + function _callBids(params) { utils._each(params.bids, bid => { - const pubapiUrl = _buildPubapiUrl(bid); - - ajax(pubapiUrl, response => { - // needs to be here in case bidderSettings are defined after requestBids() is called - if (showCpmAdjustmentWarning && - $$PREBID_GLOBAL$$.bidderSettings && $$PREBID_GLOBAL$$.bidderSettings.aol && - typeof $$PREBID_GLOBAL$$.bidderSettings.aol.bidCpmAdjustment === 'function' - ) { - utils.logWarn( - 'bidCpmAdjustment is active for the AOL adapter. ' + - 'As of Prebid 0.14, AOL can bid in net – please contact your accounts team to enable.' - ); + let apiUrl; + let data = null; + let options = { + withCredentials: true + }; + let isNexageRequestPost = _isNexageRequestPost(bid); + if (bid.params.placement && bid.params.network) { + apiUrl = _buildMarketplaceUrl(bid); + } else if(bid.params.dcn && bid.params.pos || isNexageRequestPost) { + apiUrl = _buildNexageApiUrl(bid); + if (isNexageRequestPost) { + data = bid.params; + options.customHeaders = { + 'x-openrtb-version': '2.2' + }; + options.method = 'POST'; + options.contentType = 'application/json'; } - showCpmAdjustmentWarning = false; // warning is shown at most once + } + if (apiUrl) { + ajax(apiUrl, response => { + // Needs to be here in case bidderSettings are defined after requestBids() is called + if (showCpmAdjustmentWarning && + $$PREBID_GLOBAL$$.bidderSettings && $$PREBID_GLOBAL$$.bidderSettings.aol && + typeof $$PREBID_GLOBAL$$.bidderSettings.aol.bidCpmAdjustment === 'function' + ) { + utils.logWarn( + 'bidCpmAdjustment is active for the AOL adapter. ' + + 'As of Prebid 0.14, AOL can bid in net – please contact your accounts team to enable.' + ); + } + showCpmAdjustmentWarning = false; // warning is shown at most once - if (!response && response.length <= 0) { - utils.logError('Empty bid response', BIDDER_CODE, bid); - _addErrorBidResponse(bid, response); - return; - } + if (!response && response.length <= 0) { + utils.logError('Empty bid response', BIDDER_CODE, bid); + _addErrorBidResponse(bid, response); + return; + } - try { - response = JSON.parse(response); - } catch (e) { - utils.logError('Invalid JSON in bid response', BIDDER_CODE, bid); - _addErrorBidResponse(bid, response); - return; - } + try { + response = JSON.parse(response); + } catch (e) { + utils.logError('Invalid JSON in bid response', BIDDER_CODE, bid); + _addErrorBidResponse(bid, response); + return; + } - _addBidResponse(bid, response); + _addBidResponse(bid, response); - }, null, { withCredentials: true }); + }, data, options); + } }); } diff --git a/src/ajax.js b/src/ajax.js index 019efd34106..59ebf977b86 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -83,6 +83,9 @@ export function ajax(url, callback, data, options = {}) { if (options.withCredentials) { x.withCredentials = true; } + utils._each(options.customHeaders, (value, header) => { + x.setRequestHeader(header, value); + }); if (options.preflight) { x.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); } diff --git a/test/spec/adapters/aol_spec.js b/test/spec/adapters/aol_spec.js index 38346743d4c..df2d3d6b550 100644 --- a/test/spec/adapters/aol_spec.js +++ b/test/spec/adapters/aol_spec.js @@ -1,7 +1,10 @@ import {expect} from 'chai'; +import { cloneDeep } from 'lodash'; import * as utils from 'src/utils'; import AolAdapter from 'src/adapters/aol'; import bidmanager from 'src/bidmanager'; +import events from 'src/events'; +import constants from 'src/constants'; const DEFAULT_BIDDER_REQUEST = { bidderCode: 'aol', @@ -44,7 +47,7 @@ describe('AolAdapter', () => { beforeEach(() => adapter = new AolAdapter()); function createBidderRequest({bids, params} = {}) { - var bidderRequest = utils.cloneJson(DEFAULT_BIDDER_REQUEST); + var bidderRequest = cloneDeep(DEFAULT_BIDDER_REQUEST); if (bids && Array.isArray(bids)) { bidderRequest.bids = bids; } @@ -60,180 +63,334 @@ describe('AolAdapter', () => { }); describe('bid request', () => { - let xhr; - let requests; - beforeEach(() => { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = request => requests.push(request); - }); - - afterEach(() => xhr.restore()); - - it('requires parameters to be made', () => { - adapter.callBids({}); - expect(requests).to.be.empty; - }); - - it('should hit the default pubapi endpoint', () => { - adapter.callBids(DEFAULT_BIDDER_REQUEST); - expect(requests[0].url).to.contain('adserver-us.adtech.advertising.com/pubapi/3.0/'); + describe('Marketplace api', () => { + + let xhr; + let requests; + + beforeEach(() => { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); + }); + + afterEach(() => xhr.restore()); + + it('requires parameters to be made', () => { + adapter.callBids({}); + expect(requests).to.be.empty; + }); + + it('should hit the Marketplace api endpoint with the Marketplace config', () => { + adapter.callBids(DEFAULT_BIDDER_REQUEST); + expect(requests[0].url).to.contain('adserver-us.adtech.advertising.com/pubapi/3.0/'); + }); + + it('should hit endpoint based on the region config option', () => { + adapter.callBids(createBidderRequest({ + params: { + placement: 1234567, + network: '9599.1', + region: 'eu' + } + })); + expect(requests[0].url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/'); + }); + + it('should hit the default endpoint in case of unknown region config option', () => { + adapter.callBids(createBidderRequest({ + params: { + placement: 1234567, + network: '9599.1', + region: 'an' + } + })); + expect(requests[0].url).to.contain('adserver-us.adtech.advertising.com/pubapi/3.0/'); + }); + + it('should hit endpoint based on the server config option', () => { + adapter.callBids(createBidderRequest({ + params: { + placement: 1234567, + network: '9599.1', + server: 'adserver-eu.adtech.advertising.com' + } + })); + expect(requests[0].url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/'); + }); + + it('should be the pubapi bid request', () => { + adapter.callBids(DEFAULT_BIDDER_REQUEST); + expect(requests[0].url).to.contain('cmd=bid;'); + }); + + it('should be the version 2 of pubapi', () => { + adapter.callBids(DEFAULT_BIDDER_REQUEST); + expect(requests[0].url).to.contain('v=2;'); + }); + + it('should contain cache busting', () => { + adapter.callBids(DEFAULT_BIDDER_REQUEST); + expect(requests[0].url).to.match(/misc=\d+/); + }); + + it('should contain required params - placement & network', () => { + adapter.callBids(createBidderRequest({ + params: { + placement: 1234567, + network: '9599.1' + } + })); + expect(requests[0].url).to.contain('/pubapi/3.0/9599.1/1234567/'); + }); + + it('should contain pageId and sizeId of 0 if params are missing', () => { + adapter.callBids(createBidderRequest({ + params: { + placement: 1234567, + network: '9599.1' + } + })); + expect(requests[0].url).to.contain('/pubapi/3.0/9599.1/1234567/0/0/ADTECH;'); + }); + + it('should contain pageId optional param', () => { + adapter.callBids(createBidderRequest({ + params: { + placement: 1234567, + network: '9599.1', + pageId: 12345 + } + })); + expect(requests[0].url).to.contain('/pubapi/3.0/9599.1/1234567/12345/'); + }); + + it('should contain sizeId optional param', () => { + adapter.callBids(createBidderRequest({ + params: { + placement: 1234567, + network: '9599.1', + sizeId: 12345 + } + })); + expect(requests[0].url).to.contain('/12345/ADTECH;'); + }); + + it('should contain generated alias if alias param is missing', () => { + adapter.callBids(createBidderRequest({ + params: { + placement: 1234567, + network: '9599.1' + } + })); + expect(requests[0].url).to.match(/alias=\w+?;/); + }); + + it('should contain alias optional param', () => { + adapter.callBids(createBidderRequest({ + params: { + placement: 1234567, + network: '9599.1', + alias: 'desktop_articlepage_something_box_300_250' + } + })); + expect(requests[0].url).to.contain('alias=desktop_articlepage_something_box_300_250'); + }); + + it('should not contain bidfloor if bidFloor param is missing', () => { + adapter.callBids(createBidderRequest({ + params: { + placement: 1234567, + network: '9599.1' + } + })); + expect(requests[0].url).not.to.contain('bidfloor='); + }); + + it('should contain bidFloor optional param', () => { + adapter.callBids(createBidderRequest({ + params: { + placement: 1234567, + network: '9599.1', + bidFloor: 0.80 + } + })); + expect(requests[0].url).to.contain('bidfloor=0.8'); + }); + + }); + + describe('Nexage api', () => { + + let xhr; + let requests; + + beforeEach(() => { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); + }); + + afterEach(() => xhr.restore()); + + it('requires parameters to be made', () => { + adapter.callBids({}); + expect(requests).to.be.empty; + }); + + it('should hit the nexage api endpoint with the nexage config', () => { + adapter.callBids(createBidderRequest({ + params: { + dcn: '11223344', + pos: 'header-2324' + } + })); + expect(requests[0].url).to.contain('hb.nexage.com/bidRequest?'); + }); + + it('should hit the nexage api custom endpoint if specified in the nexage config', () => { + adapter.callBids(createBidderRequest({ + params: { + host: 'qa-hb.nexage.com', + dcn: '11223344', + pos: 'header-2324' + } + })); + expect(requests[0].url).to.contain('qa-hb.nexage.com/bidRequest?'); + }); + + it('should contain required params - dcn & pos', () => { + adapter.callBids(createBidderRequest({ + params: { + dcn: '54321123', + pos: 'footer-2324' + } + })); + expect(requests[0].url).to.contain('hb.nexage.com/bidRequest?dcn=54321123&pos=footer-2324'); + }); + + it('should contain cmd=bid by default', () => { + adapter.callBids(createBidderRequest({ + params: { + dcn: '54321123', + pos: 'footer-2324' + } + })); + expect(requests[0].url).to.contain('hb.nexage.com/bidRequest?dcn=54321123&pos=footer-2324&cmd=bid'); + }); + + it('should contain optional parameters if they are set', () => { + adapter.callBids(createBidderRequest({ + params: { + dcn: '54321123', + pos: 'footer-2324', + ext: { + param1: 'val1', + param2: 'val2', + param3: 'val3', + param4: 'val4' + } + } + })); + expect(requests[0].url).to.contain('hb.nexage.com/bidRequest?dcn=54321123&pos=footer-2324&cmd=bid' + + '¶m1=val1¶m2=val2¶m3=val3¶m4=val4'); + }); + + it('should hit the nexage api endpoint with post data with the openrtb config', () => { + let bidConfig = { + id: 'id-1', + imp: [{ + id: 'id-2', + banner: { + w: '100', + h: '100' + }, + tagid: 'header1' + }] + }; + adapter.callBids(createBidderRequest({ + params: bidConfig + })); + expect(requests[0].url).to.contain('hb.nexage.com/bidRequest?'); + expect(requests[0].requestBody).to.deep.equal(bidConfig); + expect(requests[0].requestHeaders).to.have.property('x-openrtb-version'); + }); + + it('should not hit the nexage api endpoint with post data with the openrtb config' + + ' if a required parameter is missing', () => { + let bidConfig = { + id: 'id-1', + imp: [{ + // id: 'id-2', + banner: { + w: '100', + h: '100' + }, + tagid: 'header1' + }] + }; + adapter.callBids(createBidderRequest({ + params: bidConfig + })); + expect(requests).to.be.empty; + }) + ; }); - it('should hit endpoint based on the region config option', () => { - adapter.callBids(createBidderRequest({ - params: { - placement: 1234567, - network: '9599.1', - region: 'eu' - } - })); - expect(requests[0].url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/'); - }); + }); - it('should hit the default endpoint in case of unknown region config option', () => { - adapter.callBids(createBidderRequest({ - params: { - placement: 1234567, - network: '9599.1', - region: 'an' - } - })); - expect(requests[0].url).to.contain('adserver-us.adtech.advertising.com/pubapi/3.0/'); - }); + describe('bid response', () => { - it('should hit endpoint based on the server config option', () => { - adapter.callBids(createBidderRequest({ - params: { - placement: 1234567, - network: '9599.1', - server: 'adserver-eu.adtech.advertising.com' - } - })); - expect(requests[0].url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/'); - }); + let server; - it('should be the pubapi bid request', () => { - adapter.callBids(DEFAULT_BIDDER_REQUEST); - expect(requests[0].url).to.contain('cmd=bid;'); + beforeEach(() => { + server = sinon.fakeServer.create(); + sinon.stub(bidmanager, 'addBidResponse'); }); - it('should be the version 2 of pubapi', () => { - adapter.callBids(DEFAULT_BIDDER_REQUEST); - expect(requests[0].url).to.contain('v=2;'); + afterEach(() => { + server.restore(); + bidmanager.addBidResponse.restore(); }); - it('should contain cache busting', () => { + it('should be added to bidmanager if returned from pubapi', () => { + server.respondWith(JSON.stringify(DEFAULT_PUBAPI_RESPONSE)); adapter.callBids(DEFAULT_BIDDER_REQUEST); - expect(requests[0].url).to.match(/misc=\d+/); - }); - - it('should contain required params - placement & network', () => { - adapter.callBids(createBidderRequest({ - params: { - placement: 1234567, - network: '9599.1' - } - })); - expect(requests[0].url).to.contain('/pubapi/3.0/9599.1/1234567/'); - }); - - it('should contain pageId and sizeId of 0 if params are missing', () => { - adapter.callBids(createBidderRequest({ - params: { - placement: 1234567, - network: '9599.1' - } - })); - expect(requests[0].url).to.contain('/pubapi/3.0/9599.1/1234567/0/0/ADTECH;'); - }); - - it('should contain pageId optional param', () => { - adapter.callBids(createBidderRequest({ - params: { - placement: 1234567, - network: '9599.1', - pageId: 12345 - } - })); - expect(requests[0].url).to.contain('/pubapi/3.0/9599.1/1234567/12345/'); - }); - - it('should contain sizeId optional param', () => { - adapter.callBids(createBidderRequest({ - params: { - placement: 1234567, - network: '9599.1', - sizeId: 12345 - } - })); - expect(requests[0].url).to.contain('/12345/ADTECH;'); - }); - - it('should contain generated alias if alias param is missing', () => { - adapter.callBids(createBidderRequest({ - params: { - placement: 1234567, - network: '9599.1' - } - })); - expect(requests[0].url).to.match(/alias=\w+?;/); - }); - - it('should contain alias optional param', () => { - adapter.callBids(createBidderRequest({ - params: { - placement: 1234567, - network: '9599.1', - alias: 'desktop_articlepage_something_box_300_250' - } - })); - expect(requests[0].url).to.contain('alias=desktop_articlepage_something_box_300_250'); + server.respond(); + expect(bidmanager.addBidResponse.calledOnce).to.be.true; }); - it('should not contain bidfloor if bidFloor param is missing', () => { + it('should be added to bidmanager if returned from nexage GET bid request', () => { + server.respondWith(JSON.stringify(DEFAULT_PUBAPI_RESPONSE)); adapter.callBids(createBidderRequest({ params: { - placement: 1234567, - network: '9599.1' + dcn: '54321123', + pos: 'footer-2324' } })); - expect(requests[0].url).not.to.contain('bidfloor='); + server.respond(); + expect(bidmanager.addBidResponse.calledOnce).to.be.true; }); - it('should contain bidFloor optional param', () => { + it('should be added to bidmanager if returned from nexage POST bid request', () => { + server.respondWith(JSON.stringify(DEFAULT_PUBAPI_RESPONSE)); adapter.callBids(createBidderRequest({ params: { - placement: 1234567, - network: '9599.1', - bidFloor: 0.80 + id: 'id-1', + imp: [{ + id: 'id-2', + banner: { + w: '100', + h: '100' + }, + tagid: 'header1' + }] } })); - expect(requests[0].url).to.contain('bidfloor=0.8'); - }); - - }); - - describe('bid response', () => { - - let server; - - beforeEach(() => { - server = sinon.fakeServer.create(); - sinon.stub(bidmanager, 'addBidResponse'); - }); - - afterEach(() => { - server.restore(); - bidmanager.addBidResponse.restore(); - }); - - it('should be added to bidmanager if returned from pubapi', () => { - server.respondWith(JSON.stringify(DEFAULT_PUBAPI_RESPONSE)); - adapter.callBids(DEFAULT_BIDDER_REQUEST); server.respond(); expect(bidmanager.addBidResponse.calledOnce).to.be.true; + var bidResponse = bidmanager.addBidResponse.firstCall.args[1]; }); it('should be added to bidmanager with correct bidderCode', () => { @@ -429,6 +586,88 @@ describe('AolAdapter', () => { var bidResponse = bidmanager.addBidResponse.firstCall.args[1]; expect(bidResponse.cpm).to.equal('a9334987'); }); + + it('should not render pixels on pubapi response when no parameter is set', () => { + server.respondWith(JSON.stringify({ + "id": "245730051428950632", + "cur": "USD", + "seatbid": [{ + "bid": [{ + "id": 1, + "impid": "245730051428950632", + "price": 0.09, + "adm": "", + "crid": "12345", + "h": 90, + "w": 728, + "ext": {"sizeid": 225} + }] + }], + "ext": { + "pixels": "" + } + })); + adapter.callBids(DEFAULT_BIDDER_REQUEST); + server.respond(); + expect(bidmanager.addBidResponse.calledOnce).to.be.true; + expect(document.body.querySelectorAll('iframe[src="pixels.org"]').length).to.equal(0); + }); + + it('should render pixels from pubapi response when param userSyncOn is set with \'bidResponse\'', () => { + server.respondWith(JSON.stringify({ + "id": "245730051428950632", + "cur": "USD", + "seatbid": [{ + "bid": [{ + "id": 1, + "impid": "245730051428950632", + "price": 0.09, + "adm": "", + "crid": "12345", + "h": 90, + "w": 728, + "ext": {"sizeid": 225} + }] + }], + "ext": { + "pixels": "" + } + })); + adapter.callBids({ + bidderCode: 'aol', + requestId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', + bidderRequestId: '7101db09af0db2', + start: new Date().getTime(), + bids: [{ + bidder: 'aol', + bidId: '84ab500420319d', + bidderRequestId: '7101db09af0db2', + requestId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', + placementCode: 'foo', + params: { + placement: 1234567, + network: '9599.1', + userSyncOn: 'bidResponse' + } + }] + }); + server.respond(); + + expect(bidmanager.addBidResponse.calledOnce).to.be.true; + + let assertPixelsItem = (pixelsItemSelector) => { + let pixelsItem = document.body.querySelectorAll(pixelsItemSelector)[0]; + + expect(pixelsItem.width).to.equal('1'); + expect(pixelsItem.height).to.equal('1'); + expect(pixelsItem.style.display).to.equal('none'); + }; + + assertPixelsItem('iframe[src="pixels.org"]'); + assertPixelsItem('iframe[src="pixels1.org"]'); + }); + }); describe('when bidCpmAdjustment is set', () => { From aca040f23c2ea5679a1a384f25710c16b3a91a1a Mon Sep 17 00:00:00 2001 From: Marcio Pereira Date: Tue, 11 Apr 2017 14:27:38 +0100 Subject: [PATCH 2/3] Fixed JSHint issues. --- src/adapters/aol.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/adapters/aol.js b/src/adapters/aol.js index 9a3d81c2424..aaacc2c1f93 100644 --- a/src/adapters/aol.js +++ b/src/adapters/aol.js @@ -22,7 +22,7 @@ const AolAdapter = function AolAdapter() { img: 'IMG' }; - let DOMReady = (() => { + let domReady = (() => { let readyEventFired = false; return fn => { let idempotentFn = () => { @@ -121,7 +121,7 @@ const AolAdapter = function AolAdapter() { document.readyState === 'complete') { document.body.appendChild(iframe); } else { - DOMReady(() => { + domReady(() => { document.body.appendChild(iframe); }); } @@ -249,9 +249,9 @@ const AolAdapter = function AolAdapter() { function _isNexageRequestPost(bid) { if (bid.params.id && bid.params.imp && bid.params.imp[0]) { let imp = bid.params.imp[0]; - return imp.id && imp.tagid - && ((imp.banner && imp.banner.w && imp.banner.h) - || (imp.video && imp.video.mimes && imp.video.minduration && imp.video.maxduration)); + return imp.id && imp.tagid && + ((imp.banner && imp.banner.w && imp.banner.h) || + (imp.video && imp.video.mimes && imp.video.minduration && imp.video.maxduration)); } } From 267f2da17c8f784e23bfd0dbae2a48d654cb6ede Mon Sep 17 00:00:00 2001 From: Zhukovsky Date: Fri, 28 Apr 2017 19:09:11 +0300 Subject: [PATCH 3/3] Remove logic for supporting old browsers. --- src/adapters/aol.js | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/src/adapters/aol.js b/src/adapters/aol.js index aaacc2c1f93..d0b6c702bbf 100644 --- a/src/adapters/aol.js +++ b/src/adapters/aol.js @@ -32,36 +32,13 @@ const AolAdapter = function AolAdapter() { readyEventFired = true; return fn(); }; - let doScrollCheck = () => { - if (readyEventFired) { - return; - } - try { - document.documentElement.doScroll('left'); - } catch (e) { - setTimeout(doScrollCheck, 1); - return; - } - return idempotentFn(); - }; + if (document.readyState === "complete") { return idempotentFn(); } - if (document.addEventListener) { - document.addEventListener("DOMContentLoaded", idempotentFn, false); - window.addEventListener("load", idempotentFn, false); - } else if (document.attachEvent) { - document.attachEvent("onreadystatechange", idempotentFn); - window.attachEvent("onload", idempotentFn); - let topLevel = false; - try { - topLevel = window.frameElement === null; - } catch (e) { - } - if (document.documentElement.doScroll && topLevel) { - return doScrollCheck(); - } - } + + document.addEventListener("DOMContentLoaded", idempotentFn, false); + window.addEventListener("load", idempotentFn, false); }; })();