diff --git a/modules.json b/modules.json new file mode 100644 index 00000000000..8857b8f7e25 --- /dev/null +++ b/modules.json @@ -0,0 +1,10 @@ +[ + "appnexusBidAdapter", + "sekindoUMBidAdapter", + "pulsepointBidAdapter", + "audienceNetworkBidAdapter", + "openxBidAdapter", + "rubiconBidAdapter", + "sovrnBidAdapter", + "pubmaticBidAdapter" +] \ No newline at end of file diff --git a/modules/aardvarkBidAdapter.js b/modules/aardvarkBidAdapter.js index f52265e4d1d..077ddef4c63 100644 --- a/modules/aardvarkBidAdapter.js +++ b/modules/aardvarkBidAdapter.js @@ -50,7 +50,7 @@ function requestBids(bidderCode, callbackName, bidReqs) { adloader.loadScript([ '//' + endpoint + '/', ai, '/', scs.join('_'), - '/aardvark/?jsonp=$$PREBID_GLOBAL$$.', callbackName, + '/aardvark/?jsonp=' + preBidNameSpace + '.', callbackName, '&rtkreferer=', ref, '&', bidIds.join('&') ].join('')); } diff --git a/modules/adbladeBidAdapter.js b/modules/adbladeBidAdapter.js index 50f50f515d9..d6a1f40351c 100644 --- a/modules/adbladeBidAdapter.js +++ b/modules/adbladeBidAdapter.js @@ -76,7 +76,7 @@ var AdbladeAdapter = function AdbladeAdapter() { utils.tryAppendQueryString( BASE_URI, 'callback', - '$$PREBID_GLOBAL$$.adbladeResponse' + preBidNameSpace + '.adbladeResponse' ), 'json', JSON.stringify( diff --git a/modules/adbundBidAdapter.js b/modules/adbundBidAdapter.js index a40fc2b8057..1a3adfb22a3 100644 --- a/modules/adbundBidAdapter.js +++ b/modules/adbundBidAdapter.js @@ -48,7 +48,7 @@ function AdBundAdapter() { }; var param = Object.assign({}, bid.params, info); param.sizes = JSON.stringify(param.sizes || bid.sizes); - param.callback = '$$PREBID_GLOBAL$$.adbundResponse'; + param.callback = preBidNameSpace + '.adbundResponse'; $$PREBID_GLOBAL$$.adbundResponse = _createCallback(bid); adloader.loadScript(bidAPI + '?' + _stringify(param)); } diff --git a/modules/adformBidAdapter.js b/modules/adformBidAdapter.js index 69908e70888..d2643428112 100644 --- a/modules/adformBidAdapter.js +++ b/modules/adformBidAdapter.js @@ -16,7 +16,7 @@ function AdformAdapter() { var bids = params.bids; var request = []; var callbackName = '_adf_' + utils.getUniqueIdentifierStr(); - var globalParams = [ [ 'adxDomain', 'adx.adform.net' ], ['fd', 1], [ 'url', null ], [ 'tid', null ], [ 'callback', '$$PREBID_GLOBAL$$.' + callbackName ] ]; + var globalParams = [ [ 'adxDomain', 'adx.adform.net' ], ['fd', 1], [ 'url', null ], [ 'tid', null ], [ 'callback', preBidNameSpace + '.' + callbackName ] ]; for (i = 0, l = bids.length; i < l; i++) { bid = bids[i]; diff --git a/modules/admediaBidAdapter.js b/modules/admediaBidAdapter.js index 4382870eef3..351b8a14d55 100644 --- a/modules/admediaBidAdapter.js +++ b/modules/admediaBidAdapter.js @@ -58,7 +58,7 @@ var AdmediaAdapter = function AdmediaAdapter() { request_obj.siteRef = document.referrer; request_obj.topUrl = utils.getTopWindowUrl(); - request_obj.callback = '$$PREBID_GLOBAL$$'; + request_obj.callback = preBidNameSpace; request_obj.callbackId = bid.bidId; var endpoint = bidderUrl + utils.parseQueryStringParameters(request_obj); diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js index 5adba83e9df..02e0a2db74c 100644 --- a/modules/aolBidAdapter.js +++ b/modules/aolBidAdapter.js @@ -1,341 +1,349 @@ -const utils = require('src/utils.js'); -const ajax = require('src/ajax.js').ajax; -const bidfactory = require('src/bidfactory.js'); -const bidmanager = require('src/bidmanager.js'); -const constants = require('src/constants.json'); -const adaptermanager = require('src/adaptermanager'); -const BaseAdapter = require('src/adapter').default; +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { config } from 'src/config'; +import constants from 'src/constants.json'; const AOL_BIDDERS_CODES = { - aol: 'aol', - onemobile: 'onemobile', - onedisplay: 'onedisplay' + AOL: 'aol', + ONEMOBILE: 'onemobile', + ONEDISPLAY: 'onedisplay' }; +const AOL_ENDPOINTS = { + DISPLAY: { + GET: 'display-get' + }, + MOBILE: { + GET: 'mobile-get', + POST: 'mobile-post' + } +}; + +const SYNC_TYPES = { + IFRAME: { + TAG: 'iframe', + TYPE: 'iframe' + }, + IMAGE: { + TAG: 'img', + TYPE: 'image' + } +}; + +const pubapiTemplate = template`//${'host'}/pubapi/3.0/${'network'}/${'placement'}/${'pageid'}/${'sizeid'}/ADTECH;v=2;cmd=bid;cors=yes;alias=${'alias'}${'bidfloor'}${'keyValues'};misc=${'misc'}`; +const nexageBaseApiTemplate = template`//${'host'}/bidRequest?`; +const nexageGetApiTemplate = template`dcn=${'dcn'}&pos=${'pos'}&cmd=bid${'ext'}`; +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 BID_RESPONSE_TTL = 300; + $$PREBID_GLOBAL$$.aolGlobals = { pixelsDropped: false }; -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 MP_SERVER_MAP = { - us: 'adserver-us.adtech.advertising.com', - eu: 'adserver-eu.adtech.advertising.com', - as: 'adserver-as.adtech.advertising.com' +let showCpmAdjustmentWarning = (function () { + let showCpmWarning = true; + + return function () { + let bidderSettings = $$PREBID_GLOBAL$$.bidderSettings; + if (showCpmWarning && bidderSettings && bidderSettings.aol && + typeof 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.' + ); + showCpmWarning = false; // warning is shown at most once + } }; - const NEXAGE_SERVER = 'hb.nexage.com'; - const SYNC_TYPES = { - iframe: 'IFRAME', - img: 'IMG' +})(); + +function template(strings, ...keys) { + return function(...values) { + let dict = values[values.length - 1] || {}; + let result = [strings[0]]; + keys.forEach(function(key, i) { + let value = Number.isInteger(key) ? values[key] : dict[key]; + result.push(value, strings[i + 1]); + }); + return result.join(''); }; - - let domReady = (() => { - let readyEventFired = false; - return fn => { - let idempotentFn = () => { - if (readyEventFired) { - return; +} + +function isSecureProtocol() { + return document.location.protocol === 'https:'; +} + +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 tagName = item.match(tagNameRegExp)[0]; + let url = item.match(srcRegExp)[2]; + + if (tagName && tagName) { + pixelsItems.push({ + type: tagName === SYNC_TYPES.IMAGE.TAG ? SYNC_TYPES.IMAGE.TYPE : SYNC_TYPES.IFRAME.TYPE, + url: url + }); } - readyEventFired = true; - return fn(); - }; - - if (document.readyState === 'complete') { - return idempotentFn(); - } - - document.addEventListener('DOMContentLoaded', idempotentFn, false); - window.addEventListener('load', idempotentFn, false); - }; - })(); - - function dropSyncCookies(pixels) { - if (!$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped) { - let pixelElements = parsePixelItems(pixels); - renderPixelElements(pixelElements); - $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = true; + }); } } - 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; +} - return pixelsItems; - } +function _buildMarketplaceUrl(bid) { + const params = bid.params; + const serverParam = params.server; + let regionParam = params.region || 'us'; + let server; - function renderPixelElements(pixelsElements) { - pixelsElements.forEach((element) => { - switch (element.tagName) { - case SYNC_TYPES.img: - return renderPixelImage(element); - case SYNC_TYPES.iframe: - return renderPixelIframe(element); - } - }); + if (!MP_SERVER_MAP.hasOwnProperty(regionParam)) { + utils.logWarn(`Unknown region '${regionParam}' for AOL bidder.`); + regionParam = 'us'; // Default region. } - function renderPixelImage(pixelsItem) { - let image = new Image(); - image.src = pixelsItem.src; + if (serverParam) { + server = serverParam; + } else { + server = MP_SERVER_MAP[regionParam]; } - 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); - }); - } - } + // Set region param, used by AOL analytics. + params.region = regionParam; + + return pubapiTemplate({ + host: server, + network: params.network, + placement: parseInt(params.placement), + pageid: params.pageId || 0, + sizeid: params.sizeId || 0, + alias: params.alias || utils.getUniqueIdentifierStr(), + bidfloor: formatMarketplaceBidFloor(params.bidFloor), + keyValues: formatMarketplaceKeyValues(params.keyValues), + misc: new Date().getTime() // cache busting + }); +} - function template(strings, ...keys) { - return function(...values) { - let dict = values[values.length - 1] || {}; - let result = [strings[0]]; - keys.forEach(function(key, i) { - let value = Number.isInteger(key) ? values[key] : dict[key]; - result.push(value, strings[i + 1]); - }); - return result.join(''); - }; - } +function formatMarketplaceBidFloor(bidFloor) { + return (typeof bidFloor !== 'undefined') ? `;bidfloor=${bidFloor.toString()}` : ''; +} - function _buildMarketplaceUrl(bid) { - const params = bid.params; - const serverParam = params.server; - let regionParam = params.region || 'us'; - let server; +function formatMarketplaceKeyValues(keyValues) { + let formattedKeyValues = ''; - if (!MP_SERVER_MAP.hasOwnProperty(regionParam)) { - utils.logWarn(`Unknown region '${regionParam}' for AOL bidder.`); - regionParam = 'us'; // Default region. - } + utils._each(keyValues, (value, key) => { + formattedKeyValues += `;kv${key}=${encodeURIComponent(value)}`; + }); - if (serverParam) { - server = serverParam; - } else { - server = MP_SERVER_MAP[regionParam]; - } + return formattedKeyValues; +} - // Set region param, used by AOL analytics. - params.region = regionParam; - - return pubapiTemplate({ - protocol: (document.location.protocol === 'https:') ? 'https' : 'http', - host: server, - network: params.network, - placement: parseInt(params.placement), - pageid: params.pageId || 0, - sizeid: params.sizeId || 0, - alias: params.alias || utils.getUniqueIdentifierStr(), - bidfloor: (typeof params.bidFloor !== 'undefined') - ? `;bidfloor=${params.bidFloor.toString()}` : '', - misc: new Date().getTime() // cache busting +function _buildOneMobileBaseUrl(bid) { + return nexageBaseApiTemplate({ + host: bid.params.host || NEXAGE_SERVER + }); +} + +function _buildOneMobileGetUrl(bid) { + let {dcn, pos} = bid.params; + let nexageApi = _buildOneMobileBaseUrl(bid); + if (dcn && pos) { + let ext = ''; + if (isSecureProtocol()) { + bid.params.ext = bid.params.ext || {}; + bid.params.ext.secure = 1; + } + utils._each(bid.params.ext, (value, key) => { + ext += `&${key}=${encodeURIComponent(value)}`; }); + nexageApi += nexageGetApiTemplate({dcn, pos, ext}); } + return nexageApi; +} - function _buildNexageApiUrl(bid) { - let {dcn, pos} = bid.params; - let isSecure = (document.location.protocol === 'https:'); - let nexageApi = nexageBaseApiTemplate({ - protocol: isSecure ? 'https' : 'http', - host: bid.params.host || NEXAGE_SERVER - }); - if (dcn && pos) { - let ext = ''; - if (isSecure) { - bid.params.ext = bid.params.ext || {}; - bid.params.ext.secure = 1; - } - utils._each(bid.params.ext, (value, key) => { - ext += `&${key}=${encodeURIComponent(value)}`; - }); - nexageApi += nexageGetApiTemplate({dcn, pos, ext}); - } - return nexageApi; - } +function _parseBidResponse(response, bidRequest) { + let bidData; - function _addErrorBidResponse(bid, response = {}) { - const bidResponse = bidfactory.createBid(2, bid); - bidResponse.bidderCode = bid.bidder; - bidResponse.reason = response.nbr; - bidResponse.raw = response; - bidmanager.addBidResponse(bid.placementCode, bidResponse); + try { + bidData = response.seatbid[0].bid[0]; + } catch (e) { + return; } - function _addBidResponse(bid, response) { - let bidData; + let cpm; - try { - bidData = response.seatbid[0].bid[0]; - } catch (e) { - _addErrorBidResponse(bid, response); - return; - } - - let cpm; + if (bidData.ext && bidData.ext.encp) { + cpm = bidData.ext.encp; + } else { + cpm = bidData.price; - if (bidData.ext && bidData.ext.encp) { - cpm = bidData.ext.encp; - } else { - cpm = bidData.price; - - if (cpm === null || isNaN(cpm)) { - utils.logError('Invalid price in bid response', AOL_BIDDERS_CODES.aol, bid); - _addErrorBidResponse(bid, response); - return; - } + if (cpm === null || isNaN(cpm)) { + utils.logError('Invalid price in bid response', AOL_BIDDERS_CODES.AOL, bid); + return; } + } - let ad = bidData.adm; - if (response.ext && response.ext.pixels) { - if (bid.params.userSyncOn === constants.EVENTS.BID_RESPONSE) { - dropSyncCookies(response.ext.pixels); - } else { - let formattedPixels = response.ext.pixels.replace(/<\/?script( type=('|")text\/javascript('|")|)?>/g, ''); - - ad += ''; - } - } + let ad = bidData.adm; + if (response.ext && response.ext.pixels) { + if (config.getConfig('aol.userSyncOn') !== constants.EVENTS.BID_RESPONSE) { + let formattedPixels = response.ext.pixels.replace(/<\/?script( type=('|")text\/javascript('|")|)?>/g, ''); - const bidResponse = bidfactory.createBid(1, bid); - bidResponse.bidderCode = bid.bidder; - bidResponse.ad = ad; - bidResponse.cpm = cpm; - bidResponse.width = bidData.w; - bidResponse.height = bidData.h; - bidResponse.creativeId = bidData.crid; - bidResponse.pubapiId = response.id; - bidResponse.currencyCode = response.cur; - if (bidData.dealid) { - bidResponse.dealId = bidData.dealid; + ad += ''; } - - bidmanager.addBidResponse(bid.placementCode, bidResponse); } - function _isMarketplaceBidder(bidder) { - return bidder === AOL_BIDDERS_CODES.aol || bidder === AOL_BIDDERS_CODES.onedisplay; - } + return { + bidderCode: bidRequest.bidderCode, + requestId: bidRequest.bidId, + ad: ad, + cpm: cpm, + width: bidData.w, + height: bidData.h, + creativeId: bidData.crid, + pubapiId: response.id, + currency: response.cur, + dealId: bidData.dealid, + netRevenue: true, + ttl: BID_RESPONSE_TTL + }; +} - function _isNexageBidder(bidder) { - return bidder === AOL_BIDDERS_CODES.aol || bidder === AOL_BIDDERS_CODES.onemobile; - } +function _isMarketplaceBidder(bidder) { + return bidder === AOL_BIDDERS_CODES.AOL || bidder === AOL_BIDDERS_CODES.ONEDISPLAY; +} + +function _isNexageBidder(bidder) { + return bidder === AOL_BIDDERS_CODES.AOL || bidder === AOL_BIDDERS_CODES.ONEMOBILE; +} - function _isNexageRequestPost(bid) { - if (_isNexageBidder(bid.bidder) && 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) || +function _isNexageRequestPost(bid) { + if (_isNexageBidder(bid.bidder) && 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 _isNexageRequestGet(bid) { - return _isNexageBidder(bid.bidder) && bid.params.dcn && bid.params.pos; +} + +function _isNexageRequestGet(bid) { + return _isNexageBidder(bid.bidder) && bid.params.dcn && bid.params.pos; +} + +function isMarketplaceBid(bid) { + return _isMarketplaceBidder(bid.bidder) && bid.params.placement && bid.params.network; +} + +function isMobileBid(bid) { + return _isNexageRequestGet(bid) || _isNexageRequestPost(bid); +} + +function resolveEndpointCode(bid) { + if (_isNexageRequestGet(bid)) { + return AOL_ENDPOINTS.MOBILE.GET; + } else if (_isNexageRequestPost(bid)) { + return AOL_ENDPOINTS.MOBILE.POST; + } else if (isMarketplaceBid(bid)) { + return AOL_ENDPOINTS.DISPLAY.GET; } +} - function _isMarketplaceRequest(bid) { - return _isMarketplaceBidder(bid.bidder) && bid.params.placement && bid.params.network; - } +function formatBidRequest(endpointCode, bid) { + let bidRequest; + + switch (endpointCode) { + case AOL_ENDPOINTS.DISPLAY.GET: + bidRequest = { + url: _buildMarketplaceUrl(bid), + method: 'GET' + }; + break; - function _callBids(params) { - utils._each(params.bids, bid => { - let apiUrl; - let data = null; - let options = { - withCredentials: true + case AOL_ENDPOINTS.MOBILE.GET: + bidRequest = { + url: _buildOneMobileGetUrl(bid), + method: 'GET' }; - let isNexageRequestPost = _isNexageRequestPost(bid); - let isNexageRequestGet = _isNexageRequestGet(bid); - let isMarketplaceRequest = _isMarketplaceRequest(bid); - - if (isNexageRequestGet || isNexageRequestPost) { - apiUrl = _buildNexageApiUrl(bid); - if (isNexageRequestPost) { - data = bid.params; - options.customHeaders = { + break; + + case AOL_ENDPOINTS.MOBILE.POST: + bidRequest = { + url: _buildOneMobileBaseUrl(bid), + method: 'POST', + data: bid.params, + options: { + contentType: 'application/json', + customHeaders: { 'x-openrtb-version': '2.2' - }; - options.method = 'POST'; - options.contentType = 'application/json'; + } } - } else if (isMarketplaceRequest) { - apiUrl = _buildMarketplaceUrl(bid); - } + }; + break; + } - 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 + bidRequest.bidderCode = bid.bidder; + bidRequest.bidId = bid.bidId; + bidRequest.userSyncOn = bid.params.userSyncOn; - if (!response && response.length <= 0) { - utils.logError('Empty bid response', AOL_BIDDERS_CODES.aol, bid); - _addErrorBidResponse(bid, response); - return; - } + return bidRequest; +} - try { - response = JSON.parse(response); - } catch (e) { - utils.logError('Invalid JSON in bid response', AOL_BIDDERS_CODES.aol, bid); - _addErrorBidResponse(bid, response); - return; - } +function interpretResponse({body}, bidRequest) { + showCpmAdjustmentWarning(); - _addBidResponse(bid, response); - }, data, options); + if (!body) { + utils.logError('Empty bid response', bidRequest.bidderCode, body); + } else { + let bid = _parseBidResponse(body, bidRequest); + + if (bid) { + return bid; + } + } +} + +export const spec = { + code: AOL_BIDDERS_CODES.AOL, + aliases: [AOL_BIDDERS_CODES.ONEMOBILE, AOL_BIDDERS_CODES.ONEDISPLAY], + isBidRequestValid: function(bid) { + return isMarketplaceBid(bid) || isMobileBid(bid); + }, + buildRequests: function (bids) { + return bids.map(bid => { + const endpointCode = resolveEndpointCode(bid); + + if (endpointCode) { + return formatBidRequest(endpointCode, bid); } }); - } + }, + interpretResponse: interpretResponse, + getUserSyncs: function(options, bidResponses) { + let bidResponse = bidResponses[0]; - return Object.assign(this, new BaseAdapter(AOL_BIDDERS_CODES.aol), { - callBids: _callBids - }); -}; + if (config.getConfig('aol.userSyncOn') === constants.EVENTS.BID_RESPONSE) { + if (!$$PREBID_GLOBAL$$.aolGlobals.pixelsDropped && bidResponse.ext && bidResponse.ext.pixels) { + $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = true; -adaptermanager.registerBidAdapter(new AolAdapter(), AOL_BIDDERS_CODES.aol); -adaptermanager.aliasBidAdapter(AOL_BIDDERS_CODES.aol, AOL_BIDDERS_CODES.onedisplay); -adaptermanager.aliasBidAdapter(AOL_BIDDERS_CODES.aol, AOL_BIDDERS_CODES.onemobile); + return parsePixelItems(bidResponse.ext.pixels); + } + } + + return []; + } +}; -module.exports = AolAdapter; +registerBidder(spec); diff --git a/modules/aolBidAdapter.md b/modules/aolBidAdapter.md new file mode 100644 index 00000000000..a92e933bd36 --- /dev/null +++ b/modules/aolBidAdapter.md @@ -0,0 +1,47 @@ +# Overview + +Module Name: AOL Bid Adapter + +Module Type: AOL Adapter + +Maintainer: hb-fe-tech@oath.com + +# Description + +Module that connects to AOL's demand sources + +# Test Parameters +```javascript + var adUnits = [ + { + code: 'test-ad', + sizes: [[300, 250]], + bids: [ + { + bidder: 'onedisplay', + params: { + placement: '3611253', + network: '9599.1', + bidFloor: '0.80', + keyValues: { + test: 'key' + } + } + } + ] + }, + { + code: 'test-mobile-ad', + sizes: [[300, 250]], + bids: [ + { + bidder: 'onemobile', + params: { + dcn: '2c9d2b50015a5aa95b70a9b0b5b10012', + pos: 'header' + } + } + ] + } + ]; +``` diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 1fb48b68fc4..229e7df44ed 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -47,7 +47,7 @@ AppNexusAdapter = function AppNexusAdapter() { let usePaymentRule = utils.getBidIdParameter('usePaymentRule', bid.params); var jptCall = '//ib.adnxs.com/jpt?'; - jptCall = utils.tryAppendQueryString(jptCall, 'callback', '$$PREBID_GLOBAL$$.handleAnCB'); + jptCall = utils.tryAppendQueryString(jptCall, 'callback', preBidNameSpace+'.handleAnCB'); jptCall = utils.tryAppendQueryString(jptCall, 'callback_uid', callbackId); jptCall = utils.tryAppendQueryString(jptCall, 'psa', '0'); jptCall = utils.tryAppendQueryString(jptCall, 'id', placementId); diff --git a/modules/brightcomBidAdapter.js b/modules/brightcomBidAdapter.js index f1256edeab8..79413ca4a5a 100644 --- a/modules/brightcomBidAdapter.js +++ b/modules/brightcomBidAdapter.js @@ -16,7 +16,7 @@ var BrightcomAdapter = function BrightcomAdapter() { var brightcomBidderCode = 'brightcom'; // Define the callback function - var brightcomCallbackFunction = 'window.$$PREBID_GLOBAL$$=window.$$PREBID_GLOBAL$$||window.parent.$$PREBID_GLOBAL$$||window.top.$$PREBID_GLOBAL$$;window.$$PREBID_GLOBAL$$.brightcomResponse'; + var brightcomCallbackFunction = 'window.' + preBidNameSpace + '=window.' + preBidNameSpace + '||window.parent.' + preBidNameSpace + '||window.top.' + preBidNameSpace + ';window.' + preBidNameSpace + '.brightcomResponse'; // Manage the requested and received ad units' codes, to know which are invalid (didn't return) const reqAdUnitsCode = []; diff --git a/modules/eplanningBidAdapter.js b/modules/eplanningBidAdapter.js index 9c09fd3b782..5c284a122b6 100644 --- a/modules/eplanningBidAdapter.js +++ b/modules/eplanningBidAdapter.js @@ -6,7 +6,7 @@ function EPlanningAdapter() { (function() { const win = window; const doc = win.document; - const pbjsVar = win.$$PREBID_GLOBAL$$; + const pbjsVar = $$PREBID_GLOBAL$$; const _global = {}; const _default = { 'sv': 'ads.us.e-planning.net', 't': 0 }; var rnd; @@ -264,8 +264,8 @@ function EPlanningAdapter() { win.hbpb = win.hbpb || new Hbpb(); })(); - window.$$PREBID_GLOBAL$$ = window.$$PREBID_GLOBAL$$ || {}; - window.$$PREBID_GLOBAL$$.processEPlanningResponse = function(response) { + $$PREBID_GLOBAL$$ = $$PREBID_GLOBAL$$ || {}; + $$PREBID_GLOBAL$$.processEPlanningResponse = function(response) { var bids, bidObject, i; if (response) { bids = response.bids; diff --git a/modules/essensBidAdapter.js b/modules/essensBidAdapter.js index 1b4df4d1685..f572a678e39 100644 --- a/modules/essensBidAdapter.js +++ b/modules/essensBidAdapter.js @@ -50,7 +50,7 @@ function EssensAdapter () { if (!utils.isEmpty(essensBids)) { const payloadJson = {bidderRequestId: bidderRequestId, cur: cur, url: urlParam, ua: uaParam, imp: essensBids} - const scriptUrl = '//' + ENDPOINT + '?callback=$$PREBID_GLOBAL$$.essensResponseHandler' + + const scriptUrl = '//' + ENDPOINT + '?callback=' + preBidNameSpace + '.essensResponseHandler' + '&bid=' + encodeURIComponent(JSON.stringify(payloadJson)) adloader.loadScript(scriptUrl) } else { diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index 521dfabfb2d..9cd2b554638 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -108,7 +108,7 @@ const GumgumAdapter = function GumgumAdapter() { id: bidId }, bid); - const callback = { jsonp: `$$PREBID_GLOBAL$$.handleGumGumCB['${bidId}']` }; + const callback = { jsonp: `${preBidNameSpace}.handleGumGumCB['${bidId}']` }; CALLBACKS[bidId] = _handleGumGumResponse(cachedBid); const query = Object.assign(callback, browserParams, bid, _getDigiTrustQueryParams()); const bidCall = `${bidEndpoint}?${utils.parseQueryStringParameters(query)}`; @@ -144,7 +144,7 @@ const GumgumAdapter = function GumgumAdapter() { if (G) { loadAd(); } else { - topWindow.$$PREBID_GLOBAL$$.loadScript("https://js.gumgum.com/services.js", loadAd); + topWindow.${preBidNameSpace}.loadScript("https://js.gumgum.com/services.js", loadAd); } }(window, top)); `; @@ -164,7 +164,7 @@ const GumgumAdapter = function GumgumAdapter() { delete CALLBACKS[cachedBidRequest.id]; }; - window.$$PREBID_GLOBAL$$.handleGumGumCB = CALLBACKS; + $$PREBID_GLOBAL$$.handleGumGumCB = CALLBACKS; return { callBids: _callBids diff --git a/modules/imonomyBidAdapter.js b/modules/imonomyBidAdapter.js index 7026c28ba6d..c48a2466f78 100644 --- a/modules/imonomyBidAdapter.js +++ b/modules/imonomyBidAdapter.js @@ -64,7 +64,7 @@ function ImonomyAdapter() { connectiontype: connectiontype, requestId: params['requestId'], bidderRequestId: params['bidderRequestId'], - callback: '$$PREBID_GLOBAL$$.' + callbackName, + callback: preBidNameSpace + '.' + callbackName, publisher_id: params['bids'][0]['params']['publisher_id'], bids: encodeURIComponent(JSON.stringify(params['bids'])) }; diff --git a/modules/indexExchangeBidAdapter.js b/modules/indexExchangeBidAdapter.js index 352613b4887..8d8014caf99 100644 --- a/modules/indexExchangeBidAdapter.js +++ b/modules/indexExchangeBidAdapter.js @@ -77,8 +77,8 @@ const DEFAULT_VPAID_MIMES_MAP = { HTML5: ['application/javascript'] }; -const BASE_CYGNUS_VIDEO_URL_INSECURE = `http://as.casalemedia.com/cygnus?v=8&fn=$$PREBID_GLOBAL$$.handleCygnusResponse`; -const BASE_CYGNUS_VIDEO_URL_SECURE = `https://as-sec.casalemedia.com/cygnus?v=8&fn=$$PREBID_GLOBAL$$.handleCygnusResponse`; +const BASE_CYGNUS_VIDEO_URL_INSECURE = `http://as.casalemedia.com/cygnus?v=8&fn=` + preBidNameSpace + `.handleCygnusResponse`; +const BASE_CYGNUS_VIDEO_URL_SECURE = `https://as-sec.casalemedia.com/cygnus?v=8&fn=` + preBidNameSpace + `.handleCygnusResponse`; window.cygnus_index_parse_res = function(response) { try { diff --git a/modules/innityBidAdapter.js b/modules/innityBidAdapter.js index 79afe7ffe17..0e3af18b7d2 100644 --- a/modules/innityBidAdapter.js +++ b/modules/innityBidAdapter.js @@ -23,7 +23,7 @@ var InnityAdapter = function InnityAdapter() { requestParams.width = arrSize[0]; requestParams.height = arrSize[1]; // Callback function - requestParams.callback = '$$PREBID_GLOBAL$$._doInnityCallback'; + requestParams.callback = preBidNameSpace + '._doInnityCallback'; // Callback ID requestParams.callback_uid = bid.bidId; // Load Bidder URL diff --git a/modules/kruxlinkBidAdapter.js b/modules/kruxlinkBidAdapter.js index e3e6569ec1c..08eb07e791a 100644 --- a/modules/kruxlinkBidAdapter.js +++ b/modules/kruxlinkBidAdapter.js @@ -49,7 +49,7 @@ function _makeCallback(id, placements) { } }; - return '$$PREBID_GLOBAL$$.' + callback; + return preBidNameSpace + '.' + callback; } function _callBids(params) { diff --git a/modules/kummaBidAdapter.js b/modules/kummaBidAdapter.js index b65b80c5a1a..3609749a40b 100644 --- a/modules/kummaBidAdapter.js +++ b/modules/kummaBidAdapter.js @@ -24,7 +24,7 @@ var KummaAdapter = function KummaAdapter() { requestParams.width = arrSize[0]; requestParams.height = arrSize[1]; - requestParams.callback = '$$PREBID_GLOBAL$$._doKummaCallback'; + requestParams.callback = preBidNameSpace + '._doKummaCallback'; requestParams.callback_uid = bid.bidId; bidURL = requestURL + utils.parseQueryStringParameters(requestParams); diff --git a/modules/lifestreetBidAdapter.js b/modules/lifestreetBidAdapter.js index aa65ed1fd71..00b7b7f6ab7 100644 --- a/modules/lifestreetBidAdapter.js +++ b/modules/lifestreetBidAdapter.js @@ -93,13 +93,13 @@ const LifestreetAdapter = function LifestreetAdapter() { return; } if (object.message && object.message === PREBID_REQUEST_MESSAGE && object.slotName && - window.$$PREBID_GLOBAL$$[object.slotName]) { + $$PREBID_GLOBAL$$[object.slotName]) { ev.source.postMessage(JSON.stringify({ message: PREBID_RESPONSE_MESSAGE, - slotObject: window.$$PREBID_GLOBAL$$[object.slotName] + slotObject: $$PREBID_GLOBAL$$[object.slotName] }), '*'); - window.$$PREBID_GLOBAL$$[object.slotName].destroy(); - window.$$PREBID_GLOBAL$$[object.slotName] = null; + $$PREBID_GLOBAL$$[object.slotName].destroy(); + $$PREBID_GLOBAL$$[object.slotName] = null; } }, false); } else { diff --git a/modules/memeglobalBidAdapter.js b/modules/memeglobalBidAdapter.js index c47c8ed7381..dbda673bbe8 100644 --- a/modules/memeglobalBidAdapter.js +++ b/modules/memeglobalBidAdapter.js @@ -64,7 +64,7 @@ var MemeGlobalAdapter = function MemeGlobalAdapter() { } }; - var scriptUrl = '//' + bidder + '?callback=window.$$PREBID_GLOBAL$$.mgres' + + var scriptUrl = '//' + bidder + '?callback=window.' + preBidNameSpace + '.mgres' + '&src=' + CONSTANTS.REPO_AND_VERSION + '&br=' + encodeURIComponent(JSON.stringify(bidRequest)); adloader.loadScript(scriptUrl); diff --git a/modules/nginadBidAdapter.js b/modules/nginadBidAdapter.js index 32560120d64..454f6b5d0a9 100644 --- a/modules/nginadBidAdapter.js +++ b/modules/nginadBidAdapter.js @@ -98,7 +98,7 @@ var NginAdAdapter = function NginAdAdapter() { } }; - var scriptUrl = window.location.protocol + '//' + rtbServerDomain + '/bid/rtb?callback=window.$$PREBID_GLOBAL$$.nginadResponse' + + var scriptUrl = window.location.protocol + '//' + rtbServerDomain + '/bid/rtb?callback=window.' + preBidNameSpace + '.nginadResponse' + '&br=' + encodeURIComponent(JSON.stringify(nginadBidReq)); adloader.loadScript(scriptUrl); diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index a0bcd2a945f..ee73b3395c3 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -2,9 +2,9 @@ import { config } from 'src/config'; import {registerBidder} from 'src/adapters/bidderFactory'; import * as utils from 'src/utils'; import {userSync} from 'src/userSync'; -import { BANNER } from 'src/mediaTypes'; +import { BANNER, VIDEO } from 'src/mediaTypes'; -const SUPPORTED_AD_TYPES = [BANNER]; +const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; const BIDDER_VERSION = '2.0.0'; @@ -13,6 +13,11 @@ export const spec = { code: BIDDER_CODE, supportedMediaTypes: SUPPORTED_AD_TYPES, isBidRequestValid: function(bid) { + if (bid.mediaType === VIDEO) { + if (typeof bid.params.video !== 'object' || !bid.params.video.url) { + return false; + } + } return !!(bid.params.unit && bid.params.delDomain); }, buildRequests: function(bids) { @@ -22,27 +27,67 @@ export const spec = { return; } - let delDomain = bids[0].params.delDomain; - let configuredBc = bids[0].params.bc; - let bc = configuredBc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`; - - return buildOXRequest(bids, { - ju: currentURL, - jr: currentURL, - ch: document.charSet || document.characterSet, - res: `${screen.width}x${screen.height}x${screen.colorDepth}`, - ifr: isIfr, - tz: new Date().getTimezoneOffset(), - tws: getViewportDimensions(isIfr), - ef: 'bt%2Cdb', - be: 1, - bc: bc, - nocache: new Date().getTime() - }, - delDomain); + let requests = []; + let bannerRequests = []; + let videoRequests = []; + let bannerBids = []; + let videoBids = []; + + bids.forEach(function (bid) { + if (bid.mediaType === VIDEO) { + videoBids.push(bid); + } else { + bannerBids.push(bid); + } + }); + + // build banner requests + if (bannerBids.length !== 0) { + let delDomain = bannerBids[0].params.delDomain; + let configuredBc = bannerBids[0].params.bc; + let bc = configuredBc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`; + bannerRequests = [ buildOXRequest(bannerBids, { + ju: currentURL, + jr: currentURL, + ch: document.charSet || document.characterSet, + res: `${screen.width}x${screen.height}x${screen.colorDepth}`, + ifr: isIfr, + tz: new Date().getTimezoneOffset(), + tws: getViewportDimensions(isIfr), + ef: 'bt%2Cdb', + be: 1, + bc: bc, + nocache: new Date().getTime() + }, + delDomain)]; + } + // build video requests + if (videoBids.length !== 0) { + videoRequests = buildOXVideoRequest(videoBids); + } + + requests = bannerRequests.concat(videoRequests); + return requests; }, interpretResponse: function({body: oxResponseObj}, bidRequest) { let bidResponses = []; + let mediaType = BANNER; + if (bidRequest && bidRequest.payload) { + if (bidRequest.payload.bids) { + mediaType = bidRequest.payload.bids[0].mediaType; + } else if (bidRequest.payload.bid) { + mediaType = bidRequest.payload.bid.mediaType; + } + } + + if (mediaType === VIDEO) { + if (oxResponseObj && oxResponseObj.pixels) { + userSync.registerSync('iframe', 'openx', oxResponseObj.pixels); + } + bidResponses = createVideoBidResponses(oxResponseObj, bidRequest.payload); + return bidResponses; + } + let adUnits = oxResponseObj.ads.ad; if (oxResponseObj.ads && oxResponseObj.ads.pixels) { userSync.registerSync('iframe', BIDDER_CODE, oxResponseObj.ads.pixels); @@ -96,13 +141,13 @@ function createBidResponses(adUnits, {bids, startTime}) { if (adUnit.deal_id) { bidResponse.dealId = adUnit.deal_id; } - // default 5 mins + // default 5 mins bidResponse.ttl = 300; - // true is net, false is gross + // true is net, false is gross bidResponse.netRevenue = true; bidResponse.currency = adUnit.currency; - // additional fields to add + // additional fields to add if (adUnit.tbd) { bidResponse.tbd = adUnit.tbd; } @@ -211,7 +256,7 @@ function formatCustomParms(customKey, customParams) { // if value is an array, join them with commas first value = value.join(','); } - // return customKey=customValue format, escaping + to . and / to _ + // return customKey=customValue format, escaping + to . and / to _ return (customKey.toLowerCase() + '=' + value.toLowerCase()).replace('+', '.').replace('/', '_') } @@ -265,4 +310,57 @@ function buildOXRequest(bids, oxParams, delDomain) { }; } +function buildOXVideoRequest(bids) { + return bids.map(function(bid) { + let url = 'http://' + bid.params.delDomain + '/v/1.0/avjp'; + let oxVideoParams = generateVideoParameters(bid); + return { + method: 'GET', + url: url, + data: oxVideoParams, + payload: {'bid': bid, 'startTime': new Date()} + }; + }); +} + +function generateVideoParameters(bid) { + let oxVideo = bid.params.video; + let oxVideoParams = { auid: bid.params.unit }; + + Object.keys(oxVideo).forEach(function(key) { + if (key === 'openrtb') { + oxVideoParams[key] = JSON.stringify(oxVideo[key]); + } else { + oxVideoParams[key] = oxVideo[key]; + } + }); + oxVideoParams['be'] = 'true'; + return oxVideoParams; +} + +function createVideoBidResponses(response, {bid, startTime}) { + let bidResponses = []; + + if (response !== undefined && response.vastUrl !== '' && response.pub_rev !== '') { + let bidResponse = {}; + bidResponse.requestId = bid.bidId; + bidResponse.bidderCode = BIDDER_CODE; + // default 5 mins + bidResponse.ttl = 300; + // true is net, false is gross + bidResponse.netRevenue = true; + bidResponse.currency = response.currency; + bidResponse.cpm = Number(response.pub_rev) / 1000; + bidResponse.width = response.width; + bidResponse.height = response.height; + bidResponse.creativeId = response.adid; + bidResponse.vastUrl = response.vastUrl; + bidResponse.mediaType = VIDEO; + + bidResponses.push(bidResponse); + } + + return bidResponses; +} + registerBidder(spec); diff --git a/modules/openxBidAdapter.md b/modules/openxBidAdapter.md index 5b3ad77ce6d..1f04c2fe466 100644 --- a/modules/openxBidAdapter.md +++ b/modules/openxBidAdapter.md @@ -16,6 +16,7 @@ Module that connects to OpenX's demand sources { code: 'test-div', sizes: [[728, 90]], // a display size + mediaType: 'banner', bids: [ { bidder: "openx", @@ -26,5 +27,22 @@ Module that connects to OpenX's demand sources } ] }, + { + code: 'video1', + sizes: [[640,480]], + mediaType: 'video', + bids: [ + { + bidder: 'openx', + params: { + unit: '539131525', + delDomain: 'zdo.com', + video: { + url: 'abc.com' + } + } + } + ] + } ]; ``` diff --git a/modules/orbitsoftBidAdapter.js b/modules/orbitsoftBidAdapter.js index e01f82a7097..87d881777f7 100644 --- a/modules/orbitsoftBidAdapter.js +++ b/modules/orbitsoftBidAdapter.js @@ -69,7 +69,7 @@ let OrbitsoftAdapter = function OrbitsoftAdapter() { jptCall += '?'; } - jptCall = utils.tryAppendQueryString(jptCall, 'callback', '$$PREBID_GLOBAL$$.handleOASCB'); + jptCall = utils.tryAppendQueryString(jptCall, 'callback', preBidNameSpace + '.handleOASCB'); jptCall = utils.tryAppendQueryString(jptCall, 'callback_uid', callbackId); jptCall = utils.tryAppendQueryString(jptCall, 'scid', placementId); diff --git a/modules/piximediaBidAdapter.js b/modules/piximediaBidAdapter.js index 48d2c9ee37b..8fdf8ad323b 100644 --- a/modules/piximediaBidAdapter.js +++ b/modules/piximediaBidAdapter.js @@ -60,7 +60,7 @@ var PiximediaAdapter = function PiximediaAdapter() { } } - url = tryAppendPixiQueryString(url, 'jsonp', '$$PREBID_GLOBAL$$.handlePiximediaCallback'); + url = tryAppendPixiQueryString(url, 'jsonp', preBidNameSpace + '.handlePiximediaCallback'); url = tryAppendPixiQueryString(url, 'sizes', encodeURIComponent(sizes.join(','))); url = tryAppendPixiQueryString(url, 'cbid', encodeURIComponent(cbid)); url = tryAppendPixiQueryString(url, 'rand', String(Math.floor(Math.random() * 1000000000))); diff --git a/modules/platformioBidAdapter.js b/modules/platformioBidAdapter.js index 2fb23ab92b3..fa841dc6026 100644 --- a/modules/platformioBidAdapter.js +++ b/modules/platformioBidAdapter.js @@ -42,13 +42,13 @@ function bidResponseAvailable(bidRequest, bidResponse) { const bids = []; Object.keys(idToImpMap).forEach(id => { if (idToBidMap[id]) { - const bid = { - requestId: id, - cpm: idToBidMap[id].price, - creative_id: id, - creativeId: id, - adId: id, - }; + const bid = {}; + bid.requestId = id; + bid.creativeId = idToBidMap[id].adid; + bid.cpm = idToBidMap[id].price; + bid.currency = bidResponse.cur; + bid.ttl = 360; + bid.netRevenue = true; bid.ad = idToBidMap[id].adm; bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid); bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_AD_ID(%7D|\})/gi, idToBidMap[id].adid); @@ -66,7 +66,7 @@ function impression(slot) { return { id: slot.bidId, banner: banner(slot), - bidfloor: '0.000001', + bidfloor: slot.params.bidFloor || '0.000001', tagid: slot.params.placementId.toString(), }; } diff --git a/modules/platformioBidAdapter.md b/modules/platformioBidAdapter.md index 74f6adbf256..0d019d1fe96 100644 --- a/modules/platformioBidAdapter.md +++ b/modules/platformioBidAdapter.md @@ -17,10 +17,11 @@ Please use ```platformio``` as the bidder code. bids: [{ bidder: 'platformio', params: { - pubId: '28082', - siteId: '26047', + pubId: '28082', // required + siteId: '26047', // required + size: '250X250', // required placementId: '123', - size: '250X250' + bidFloor: '0.001' } }] }]; diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 7120d67eb56..a4497b52b07 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -99,6 +99,25 @@ function PrebidServer() { } } }); + // will collect any custom params and place them under bid.params.keywords attribute in the following manner for pbs to ingest properly + // "keywords":[{"key":"randomKey","value":["123456789"]},{"key":"single_test"},{"key":"myMultiVar","value":["myValue","124578"]}] + let kwArray = []; + Object.keys(bid.params).forEach(key => { + if (bid.bidder === 'appnexus' && (key !== 'member' && key !== 'invCode' && key !== 'placementId')) { + let kvObj = {}; + kvObj.key = key + if (bid.params[key] !== null) { + if (Array.isArray(bid.params[key])) { + kvObj.value = bid.params[key].map(val => tryConvertString(val)); + } else { + kvObj.value = [tryConvertString(bid.params[key])]; + } + } + kwArray.push(kvObj); + delete bid.params[key]; + } + }); + bid.params.keywords = kwArray; }); }); } diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 8176052f9e2..f8a95a57e54 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -127,7 +127,7 @@ const PubmaticAdapter = function PubmaticAdapter() { elToAppend.insertBefore(iframe, elToAppend.firstChild); var iframeDoc = utils.getIframeDocument(iframe); var content = utils.createContentToExecuteExtScriptInFriendlyFrame(url); - content = content.replace(``, ``); + content = content.replace(``, ``); iframeDoc.write(content); iframeDoc.close(); } diff --git a/modules/pulsepointLiteBidAdapter.js b/modules/pulsepointLiteBidAdapter.js index 99a83871dd8..d851245402c 100644 --- a/modules/pulsepointLiteBidAdapter.js +++ b/modules/pulsepointLiteBidAdapter.js @@ -10,6 +10,10 @@ const NATIVE_DEFAULTS = { ICON_MIN: 50, }; +const DEFAULT_BID_TTL = 20; +const DEFAULT_CURRENCY = 'USD'; +const DEFAULT_NET_REVENUE = true; + /** * PulsePoint "Lite" Adapter. This adapter implementation is lighter than the * alternative/original PulsePointAdapter because it has no external @@ -89,6 +93,9 @@ function bidResponseAvailable(bidRequest, bidResponse) { creative_id: id, creativeId: id, adId: id, + ttl: DEFAULT_BID_TTL, + netRevenue: DEFAULT_NET_REVENUE, + currency: DEFAULT_CURRENCY }; if (idToImpMap[id]['native']) { bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); @@ -98,12 +105,21 @@ function bidResponseAvailable(bidRequest, bidResponse) { bid.width = idToImpMap[id].banner.w; bid.height = idToImpMap[id].banner.h; } + applyExt(bid, idToBidMap[id]) bids.push(bid); } }); return bids; } +function applyExt(bid, ortbBid) { + if (ortbBid && ortbBid.ext) { + bid.ttl = ortbBid.ext.ttl || bid.ttl; + bid.currency = ortbBid.ext.currency || bid.currency; + bid.netRevenue = ortbBid.ext.netRevenue != null ? ortbBid.ext.netRevenue : bid.netRevenue; + } +} + /** * Produces an OpenRTBImpression from a slot config. */ diff --git a/modules/realvuBidAdapter.js b/modules/realvuBidAdapter.js index dfed3d64370..51f7cc7d282 100644 --- a/modules/realvuBidAdapter.js +++ b/modules/realvuBidAdapter.js @@ -67,7 +67,7 @@ var RealVuAdapter = function RealVuAdapter() { var altReferrer = utils.getBidIdParameter('alt_referrer', bid.params); var jptCall = '//ib.adnxs.com/jpt?'; - jptCall = utils.tryAppendQueryString(jptCall, 'callback', '$$PREBID_GLOBAL$$.handleRvAnCB'); + jptCall = utils.tryAppendQueryString(jptCall, 'callback', preBidNameSpace + '.handleRvAnCB'); jptCall = utils.tryAppendQueryString(jptCall, 'callback_uid', callbackId); jptCall = utils.tryAppendQueryString(jptCall, 'psa', '0'); jptCall = utils.tryAppendQueryString(jptCall, 'id', placementId); diff --git a/modules/rhythmoneBidAdapter.js b/modules/rhythmoneBidAdapter.js index 6143c081562..6b6eb8ecd8d 100644 --- a/modules/rhythmoneBidAdapter.js +++ b/modules/rhythmoneBidAdapter.js @@ -146,7 +146,7 @@ function RhythmoneAdapter (bidManager, global, loader) { configuredPlacements = []; - p('hbv', global.$$PREBID_GLOBAL$$.version.replace(fat, '') + ',' + version.replace(fat, '')); + p('hbv', $$PREBID_GLOBAL$$.version.replace(fat, '') + ',' + version.replace(fat, '')); for (; i < bids.length; i++) { const th = []; @@ -200,7 +200,7 @@ function RhythmoneAdapter (bidManager, global, loader) { data.url = window.document.location.href.toString(); } - var prebid_instance = global.$$PREBID_GLOBAL$$; + var prebid_instance = $$PREBID_GLOBAL$$; data.prebid_version = prebid_instance.version.replace(fat, ''); data.response_ms = (new Date()).getTime() - loadStart; diff --git a/modules/roxotBidAdapter.js b/modules/roxotBidAdapter.js index a2b9b6ca6dc..f8a87f5b659 100644 --- a/modules/roxotBidAdapter.js +++ b/modules/roxotBidAdapter.js @@ -29,7 +29,7 @@ var RoxotAdapter = function RoxotAdapter() { } }; - var scriptUrl = '//' + roxotUrl + '?callback=$$PREBID_GLOBAL$$.roxotResponseHandler' + + var scriptUrl = '//' + roxotUrl + '?callback=' + preBidNameSpace + '.roxotResponseHandler' + '&src=' + CONSTANTS.REPO_AND_VERSION + '&br=' + encodeURIComponent(JSON.stringify(roxotBidReqs)); diff --git a/modules/sekindoUMBidAdapter.js b/modules/sekindoUMBidAdapter.js index ee36dd3c88a..3230a8a9887 100644 --- a/modules/sekindoUMBidAdapter.js +++ b/modules/sekindoUMBidAdapter.js @@ -73,7 +73,7 @@ function SekindoUMAdapter() { scriptSrc = utils.tryAppendQueryString(scriptSrc, 'pubUrl', pubUrl); scriptSrc = utils.tryAppendQueryString(scriptSrc, 'hbcb', callbackId); scriptSrc = utils.tryAppendQueryString(scriptSrc, 'hbver', '3'); - scriptSrc = utils.tryAppendQueryString(scriptSrc, 'hbobj', '$$PREBID_GLOBAL$$'); + scriptSrc = utils.tryAppendQueryString(scriptSrc, 'hbobj', preBidNameSpace); scriptSrc = utils.tryAppendQueryString(scriptSrc, 'dcpmflr', bidfloor); scriptSrc = utils.tryAppendQueryString(scriptSrc, 'hbto', config.getConfig('bidderTimeout')); scriptSrc = utils.tryAppendQueryString(scriptSrc, 'protocol', protocol); diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js index d815f69c752..3972a5a31db 100644 --- a/modules/smartadserverBidAdapter.js +++ b/modules/smartadserverBidAdapter.js @@ -38,7 +38,7 @@ var SmartAdServer = function SmartAdServer() { var adCall = url.parse(bid.params.domain); adCall.pathname = '/prebid'; adCall.search = { - 'pbjscbk': '$$PREBID_GLOBAL$$.' + generateCallback(bid), + 'pbjscbk': preBidNameSpace + '.' + generateCallback(bid), 'siteid': bid.params.siteId, 'pgid': bid.params.pageId, 'fmtid': bid.params.formatId, diff --git a/modules/sovrnBidAdapter.js b/modules/sovrnBidAdapter.js index a2fef49eaed..2ee4bfba78f 100644 --- a/modules/sovrnBidAdapter.js +++ b/modules/sovrnBidAdapter.js @@ -1,156 +1,83 @@ -var CONSTANTS = require('src/constants.json'); -var utils = require('src/utils.js'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader'); -var adaptermanager = require('src/adaptermanager'); - -/** - * Adapter for requesting bids from Sovrn - */ -var SovrnAdapter = function SovrnAdapter() { - var sovrnUrl = 'ap.lijit.com/rtb/bid'; - - function _callBids(params) { - var sovrnBids = params.bids || []; - - _requestBids(sovrnBids); - } - - function _requestBids(bidReqs) { - // build bid request object - var domain = window.location.host; - var page = window.location.pathname + location.search + location.hash; - - var sovrnImps = []; - - // build impression array for sovrn +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { BANNER } from 'src/mediaTypes'; +import { REPO_AND_VERSION } from 'src/constants'; + +export const spec = { + code: 'sovrn', + supportedMediaTypes: [BANNER], + + /** + * Check if the bid is a valid zone ID in either number or string form + * @param {object} bid the Sovrn bid to validate + * @return boolean for whether or not a bid is valid + */ + isBidRequestValid: function(bid) { + return !!(bid.params.tagid && !isNaN(parseFloat(bid.params.tagid)) && isFinite(bid.params.tagid)); + }, + + /** + * Format the bid request object for our endpoint + * @param {BidRequest[]} bidRequests Array of Sovrn bidders + * @return object of parameters for Prebid AJAX request + */ + buildRequests: function(bidReqs) { + let sovrnImps = []; utils._each(bidReqs, function (bid) { - var tagId = utils.getBidIdParameter('tagid', bid.params); - var bidFloor = utils.getBidIdParameter('bidfloor', bid.params); - var adW = 0; - var adH = 0; - - // sovrn supports only one size per tagid, so we just take the first size if there are more - // if we are a 2 item array of 2 numbers, we must be a SingleSize array - var bidSizes = Array.isArray(bid.params.sizes) ? bid.params.sizes : bid.sizes; - var sizeArrayLength = bidSizes.length; - if (sizeArrayLength === 2 && typeof bidSizes[0] === 'number' && typeof bidSizes[1] === 'number') { - adW = bidSizes[0]; - adH = bidSizes[1]; - } else { - adW = bidSizes[0][0]; - adH = bidSizes[0][1]; - } - - var imp = - { - id: bid.bidId, - banner: { - w: adW, - h: adH - }, - tagid: tagId, - bidfloor: bidFloor - }; - sovrnImps.push(imp); + sovrnImps.push({ + id: bid.bidId, + banner: { w: 1, h: 1 }, + tagid: utils.getBidIdParameter('tagid', bid.params), + bidfloor: utils.getBidIdParameter('bidfloor', bid.params) + }); }); - - // build bid request with impressions - var sovrnBidReq = { + const sovrnBidReq = { id: utils.getUniqueIdentifierStr(), imp: sovrnImps, site: { - domain: domain, - page: page + domain: window.location.host, + page: window.location.pathname + location.search + location.hash } }; - var scriptUrl = '//' + sovrnUrl + '?callback=window.$$PREBID_GLOBAL$$.sovrnResponse' + - '&src=' + CONSTANTS.REPO_AND_VERSION + - '&br=' + encodeURIComponent(JSON.stringify(sovrnBidReq)); - adloader.loadScript(scriptUrl); - } - - function addBlankBidResponses(impidsWithBidBack) { - var missing = utils.getBidderRequestAllAdUnits('sovrn'); - if (missing) { - missing = missing.bids.filter(bid => impidsWithBidBack.indexOf(bid.bidId) < 0); - } else { - missing = []; - } - - missing.forEach(function (bidRequest) { - // Add a no-bid response for this bid request. - var bid = {}; - bid = bidfactory.createBid(2, bidRequest); - bid.bidderCode = 'sovrn'; - bidmanager.addBidResponse(bidRequest.placementCode, bid); - }); - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.sovrnResponse = function (sovrnResponseObj) { - var impidsWithBidBack = []; - - // valid response object from sovrn - if (sovrnResponseObj && sovrnResponseObj.id && sovrnResponseObj.seatbid && sovrnResponseObj.seatbid.length !== 0 && - sovrnResponseObj.seatbid[0].bid && sovrnResponseObj.seatbid[0].bid.length !== 0) { - sovrnResponseObj.seatbid[0].bid.forEach(function (sovrnBid) { - var responseCPM; - var placementCode = ''; - var id = sovrnBid.impid; - var bid = {}; - - var bidObj = utils.getBidRequest(id); - - if (bidObj) { - placementCode = bidObj.placementCode; - bidObj.status = CONSTANTS.STATUS.GOOD; - - responseCPM = parseFloat(sovrnBid.price); - - if (responseCPM !== 0) { - sovrnBid.placementCode = placementCode; - sovrnBid.size = bidObj.sizes; - var responseAd = sovrnBid.adm; - - // build impression url from response - var responseNurl = ''; - - // store bid response - // bid status is good (indicating 1) - bid = bidfactory.createBid(1, bidObj); - bid.creative_id = sovrnBid.id; - bid.bidderCode = 'sovrn'; - bid.cpm = responseCPM; - - // set ad content + impression url - // sovrn returns ', - crid: '0', + crid: 'creative-id', h: 90, w: 728, + dealid: 'deal-id', ext: {sizeid: 225} }] }] @@ -67,15 +68,16 @@ let getDefaultBidRequest = () => { }; }; +let getPixels = () => { + return ''; +}; + describe('AolAdapter', () => { const MARKETPLACE_URL = 'adserver-us.adtech.advertising.com/pubapi/3.0/'; const NEXAGE_URL = 'hb.nexage.com/bidRequest?'; - let adapter; - - beforeEach(() => adapter = new AolAdapter()); - - function createBidderRequest({bids, params} = {}) { + function createCustomBidRequest({bids, params} = {}) { var bidderRequest = getDefaultBidRequest(); if (bids && Array.isArray(bids)) { bidderRequest.bids = bids; @@ -86,620 +88,437 @@ describe('AolAdapter', () => { return bidderRequest; } - describe('callBids()', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); + describe('interpretResponse()', () => { + let bidderSettingsBackup; + let bidResponse; + let bidRequest; + let logWarnSpy; + + beforeEach(() => { + bidderSettingsBackup = $$PREBID_GLOBAL$$.bidderSettings; + bidRequest = { + bidderCode: 'test-bidder-code', + bidId: 'bid-id' + }; + bidResponse = { + body: getDefaultBidResponse() + }; + logWarnSpy = sinon.spy(utils, 'logWarn'); }); - describe('bid request', () => { - 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(getDefaultBidRequest()); - expect(requests[0].url).to.contain(MARKETPLACE_URL); - }); - - it('should hit the Marketplace via onedisplay bidder code', () => { - let bidRequest = createBidderRequest({ - bids: [{ - bidder: 'onedisplay' - }], - params: getMarketplaceBidParams() - }); - - adapter.callBids(bidRequest); - expect(requests[0].url).to.contain(MARKETPLACE_URL); - }); - - it('should hit the Marketplace via onedisplay bidder code when Marketplace and Nexage params are present', () => { - let bidParams = Object.assign(getMarketplaceBidParams(), getNexageGetBidParams()); - let bidRequest = createBidderRequest({ - bids: [{ - bidder: 'onedisplay' - }], - params: bidParams - }); - - adapter.callBids(bidRequest); - expect(requests[0].url).to.contain(MARKETPLACE_URL); - }); - - it('should hit the Marketplace via onedisplay bidder code when Nexage params are present', () => { - let bidParams = Object.assign(getMarketplaceBidParams(), getNexageGetBidParams(), getNexagePostBidParams()); - let bidRequest = createBidderRequest({ - bids: [{ - bidder: 'onedisplay' - }], - params: bidParams - }); - - adapter.callBids(bidRequest); - expect(requests[0].url).to.contain(MARKETPLACE_URL); - }); - - it('should not resolve endpoint for onedisplay bidder code when only Nexage params are present', () => { - let bidParams = Object.assign(getNexageGetBidParams(), getNexagePostBidParams()); - - adapter.callBids(createBidderRequest({ - bids: [{ - bidder: 'onedisplay' - }], - params: bidParams - })); - expect(requests.length).to.equal(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(MARKETPLACE_URL); - }); - - 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(getDefaultBidRequest()); - expect(requests[0].url).to.contain('cmd=bid;'); - }); - - it('should be the version 2 of pubapi', () => { - adapter.callBids(getDefaultBidRequest()); - expect(requests[0].url).to.contain('v=2;'); - }); - - it('should contain cache busting', () => { - adapter.callBids(getDefaultBidRequest()); - 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='); - }); + afterEach(() => { + $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsBackup; + logWarnSpy.restore(); + }); - 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'); - }); + it('should return formatted bid response with required properties', () => { + let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); + expect(formattedBidResponse).to.deep.equal({ + bidderCode: bidRequest.bidderCode, + requestId: 'bid-id', + ad: '', + cpm: 0.09, + width: 728, + height: 90, + creativeId: 'creative-id', + pubapiId: '245730051428950632', + currency: 'USD', + dealId: 'deal-id', + netRevenue: true, + ttl: 300 }); + }); - describe('Nexage api', () => { - let xhr; - let requests; + it('should return formatted bid response including pixels', () => { + bidResponse.body.ext = { + pixels: '' + }; - beforeEach(() => { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = request => requests.push(request); - }); + let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); - afterEach(() => xhr.restore()); + expect(formattedBidResponse.ad).to.equal( + '' + + '' + ); + }); - it('requires parameters to be made', () => { - adapter.callBids({}); - expect(requests).to.be.empty; - }); + it('should show warning in the console', function() { + $$PREBID_GLOBAL$$.bidderSettings = { + aol: { + bidCpmAdjustment: function() {} + } + }; + spec.interpretResponse(bidResponse, bidRequest); + expect(utils.logWarn.calledOnce).to.be.true; + }); + }); - it('should hit the nexage api endpoint with the nexage config', () => { - adapter.callBids(createBidderRequest({ - params: getNexageGetBidParams() - })); + describe('buildRequests()', () => { + it('method exists and is a function', () => { + expect(spec.buildRequests).to.exist.and.to.be.a('function'); + }); - expect(requests[0].url).to.contain(NEXAGE_URL); - }); + describe('Marketplace', () => { + it('should not return request when no bids are present', () => { + let [request] = spec.buildRequests([]); + expect(request).to.be.empty; + }); - it('should hit the nexage api custom endpoint if specified in the nexage config', () => { - let bidParams = Object.assign({ - host: 'qa-hb.nexage.com' - }, getNexageGetBidParams()); + it('should return request for Marketplace endpoint', () => { + let bidRequest = getDefaultBidRequest(); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain(MARKETPLACE_URL); + }); - adapter.callBids(createBidderRequest({ - params: bidParams - })); - expect(requests[0].url).to.contain('qa-hb.nexage.com/bidRequest?'); + it('should return request for Marketplace via onedisplay bidder code', () => { + let bidRequest = createCustomBidRequest({ + bids: [{ + bidder: 'onedisplay' + }], + params: getMarketplaceBidParams() }); - it('should hit nexage api when nexage and marketplace params are present', () => { - let bidParams = Object.assign(getNexageGetBidParams(), getMarketplaceBidParams()); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain(MARKETPLACE_URL); + }); - adapter.callBids(createBidderRequest({ - params: bidParams - })); - expect(requests[0].url).to.contain(NEXAGE_URL); + it('should return Marketplace request via onedisplay bidder code when' + + 'Marketplace and One Mobile GET params are present', () => { + let bidParams = Object.assign(getMarketplaceBidParams(), getNexageGetBidParams()); + let bidRequest = createCustomBidRequest({ + bids: [{ + bidder: 'onedisplay' + }], + params: bidParams }); - it('should hit nexage api via onemobile bidder code when nexage and marketplace params are present', () => { - let bidParams = Object.assign(getNexageGetBidParams(), getMarketplaceBidParams()); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain(MARKETPLACE_URL); + }); - adapter.callBids(createBidderRequest({ - bids: [{ - bidder: 'onemobile' - }], - params: bidParams - })); - expect(requests[0].url).to.contain(NEXAGE_URL); + it('should return Marketplace request via onedisplay bidder code when' + + 'Marketplace and One Mobile GET + POST params are present', () => { + let bidParams = Object.assign(getMarketplaceBidParams(), getNexageGetBidParams(), getNexagePostBidParams()); + let bidRequest = createCustomBidRequest({ + bids: [{ + bidder: 'onedisplay' + }], + params: bidParams }); - it('should not resolve endpoint for onemobile bidder code when only Marketplace params are present', () => { - adapter.callBids(createBidderRequest({ - bids: [{ - bidder: 'onemobile' - }], - params: getMarketplaceBidParams() - })); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain(MARKETPLACE_URL); + }); - expect(requests.length).to.equal(0); + it('should not resolve endpoint for onedisplay bidder code ' + + 'when only One Mobile params are present', () => { + let bidParams = Object.assign(getNexageGetBidParams(), getNexagePostBidParams()); + let bidRequest = createCustomBidRequest({ + bids: [{ + bidder: 'onedisplay' + }], + params: bidParams }); - it('should contain required params - dcn & pos', () => { - adapter.callBids(createBidderRequest({ - params: getNexageGetBidParams() - })); - - expect(requests[0].url).to.contain(NEXAGE_URL + 'dcn=2c9d2b50015c5ce9db6aeeed8b9500d6&pos=header'); - }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request).to.be.empty; + }); - 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 return Marketplace URL for eu region', () => { + let bidRequest = createCustomBidRequest({ + params: { + placement: 1234567, + network: '9599.1', + region: 'eu' + } }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/'); + }); - 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 return Marketplace URL for eu region when server option is present', () => { + let bidRequest = createCustomBidRequest({ + params: { + placement: 1234567, + network: '9599.1', + server: 'adserver-eu.adtech.advertising.com' + } }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/'); + }); - it('should hit the nexage api endpoint with post data with the openrtb config', () => { - let bidConfig = getNexagePostBidParams(); - - adapter.callBids(createBidderRequest({ - params: bidConfig - })); - expect(requests[0].url).to.contain(NEXAGE_URL); - expect(requests[0].requestBody).to.deep.equal(bidConfig); - expect(requests[0].requestHeaders).to.have.property('x-openrtb-version'); + it('should return default Marketplace URL in case of unknown region config option', () => { + let bidRequest = createCustomBidRequest({ + params: { + placement: 1234567, + network: '9599.1', + region: 'an' + } }); - - it('should not hit the nexage api endpoint with post data with the openrtb config' + - ' if a required parameter is missing', () => { - let bidConfig = getNexagePostBidParams(); - - bidConfig.imp[0].id = null; - adapter.callBids(createBidderRequest({ - params: bidConfig - })); - expect(requests).to.be.empty; - }) - ; + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain(MARKETPLACE_URL); }); - }); - - describe('bid response', () => { - let server; - beforeEach(() => { - server = sinon.fakeServer.create(); - sinon.stub(bidmanager, 'addBidResponse'); + it('should return url with pubapi bid option', () => { + let bidRequest = getDefaultBidRequest(); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain('cmd=bid;'); }); - afterEach(() => { - server.restore(); - bidmanager.addBidResponse.restore(); + it('should return url with version 2 of pubapi', () => { + let bidRequest = getDefaultBidRequest(); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain('v=2;'); }); - it('should be added to bidmanager if returned from pubapi', () => { - server.respondWith(JSON.stringify(getDefaultBidResponse())); - adapter.callBids(getDefaultBidRequest()); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; + it('should return url with cache busting option', () => { + let bidRequest = getDefaultBidRequest(); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.match(/misc=\d+/); }); - it('should be added to bidmanager if returned from nexage GET bid request', () => { - server.respondWith(JSON.stringify(getDefaultBidResponse())); - adapter.callBids(createBidderRequest({ + it('should return url with default pageId and sizeId', () => { + let bidRequest = createCustomBidRequest({ params: { - dcn: '54321123', - pos: 'footer-2324' + placement: 1234567, + network: '9599.1' } - })); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain('/pubapi/3.0/9599.1/1234567/0/0/ADTECH;'); }); - it('should be added to bidmanager if returned from nexage POST bid request', () => { - server.respondWith(JSON.stringify(getDefaultBidResponse())); - adapter.callBids(createBidderRequest({ + it('should return url with custom pageId and sizeId when options are present', () => { + let bidRequest = createCustomBidRequest({ params: { - id: 'id-1', - imp: [{ - id: 'id-2', - banner: { - w: '100', - h: '100' - }, - tagid: 'header1' - }] + placement: 1234567, + network: '9599.1', + pageId: 1111, + sizeId: 2222 } - })); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - var bidResponse = bidmanager.addBidResponse.firstCall.args[1]; + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain('/pubapi/3.0/9599.1/1234567/1111/2222/ADTECH;'); }); - it('should be added to bidmanager with correct bidderCode', () => { - server.respondWith(JSON.stringify(getDefaultBidResponse())); - adapter.callBids(getDefaultBidRequest()); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - expect(bidmanager.addBidResponse.firstCall.args[1]).to.have.property('bidderCode', 'aol'); + it('should return url with default alias if alias param is missing', () => { + let bidRequest = getDefaultBidRequest(); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.match(/alias=\w+?;/); }); - it('should have adId matching the bidId from related bid request', () => { - server.respondWith(JSON.stringify(getDefaultBidResponse())); - adapter.callBids(getDefaultBidRequest()); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - expect(bidmanager.addBidResponse.firstCall.args[1]) - .to.have.property('adId', '84ab500420319d'); + it('should return url with custom alias if it is present', () => { + let bidRequest = createCustomBidRequest({ + params: { + placement: 1234567, + network: '9599.1', + alias: 'desktop_articlepage_something_box_300_250' + } + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain('alias=desktop_articlepage_something_box_300_250'); }); - it('should be added to bidmanager as invalid in case of empty response', () => { - server.respondWith(''); - adapter.callBids(getDefaultBidRequest()); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - expect(bidmanager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(2); + it('should return url without bidfloor option if is is missing', () => { + let bidRequest = getDefaultBidRequest(); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).not.to.contain('bidfloor='); }); - it('should be added to bidmanager as invalid in case of invalid JSON response', () => { - server.respondWith('{foo:{bar:{baz:'); - adapter.callBids(getDefaultBidRequest()); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - expect(bidmanager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(2); + it('should return url with bidFloor option if it is present', () => { + let bidRequest = createCustomBidRequest({ + params: { + placement: 1234567, + network: '9599.1', + bidFloor: 0.80 + } + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain('bidfloor=0.8'); }); - it('should be added to bidmanager as invalid in case of no bid data', () => { - let bidResponse = getDefaultBidResponse(); - bidResponse.seatbid = []; - server.respondWith(JSON.stringify(bidResponse)); - - adapter.callBids(getDefaultBidRequest()); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - expect(bidmanager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(2); + it('should return url with key values if keyValues param is present', () => { + let bidRequest = createCustomBidRequest({ + params: { + placement: 1234567, + network: '9599.1', + keyValues: { + age: 25, + height: 3.42, + test: 'key' + } + } + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain('kvage=25;kvheight=3.42;kvtest=key'); }); + }); - it('should have adId matching the bidId from bid request in case of no bid data', () => { - let bidResponse = getDefaultBidResponse(); - bidResponse.seatbid = []; - server.respondWith(JSON.stringify(bidResponse)); - - adapter.callBids(getDefaultBidRequest()); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - expect(bidmanager.addBidResponse.firstCall.args[1]) - .to.have.property('adId', '84ab500420319d'); + describe('One Mobile', () => { + it('should return One Mobile url when One Mobile get params are present', () => { + let bidRequest = createCustomBidRequest({ + params: getNexageGetBidParams() + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain(NEXAGE_URL); }); - it('should be added to bidmanager as invalid in case of empty price', () => { - let bidResponse = getDefaultBidResponse(); - bidResponse.seatbid[0].bid[0].price = undefined; - - server.respondWith(JSON.stringify(bidResponse)); - adapter.callBids(getDefaultBidRequest()); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - expect(bidmanager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(2); + it('should return One Mobile url with different host when host option is present', () => { + let bidParams = Object.assign({ + host: 'qa-hb.nexage.com' + }, getNexageGetBidParams()); + let bidRequest = createCustomBidRequest({ + params: bidParams + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain('qa-hb.nexage.com/bidRequest?'); }); - it('should be added to bidmanager with attributes from pubapi response', () => { - let bidResponse = getDefaultBidResponse(); - bidResponse.seatbid[0].bid[0].crid = '12345'; - - server.respondWith(JSON.stringify(bidResponse)); - adapter.callBids(getDefaultBidRequest()); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - let addedBidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(addedBidResponse.ad).to.equal(''); - expect(addedBidResponse.cpm).to.equal(0.09); - expect(addedBidResponse.width).to.equal(728); - expect(addedBidResponse.height).to.equal(90); - expect(addedBidResponse.creativeId).to.equal('12345'); - expect(addedBidResponse.pubapiId).to.equal('245730051428950632'); + it('should return One Mobile url when One Mobile and Marketplace params are present', () => { + let bidParams = Object.assign(getNexageGetBidParams(), getMarketplaceBidParams()); + let bidRequest = createCustomBidRequest({ + params: bidParams + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain(NEXAGE_URL); }); - it('should be added to bidmanager including pixels from pubapi response', () => { - let bidResponse = getDefaultBidResponse(); - bidResponse.ext = { - pixels: '' - }; - - server.respondWith(JSON.stringify(bidResponse)); - adapter.callBids(getDefaultBidRequest()); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - let addedBidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(addedBidResponse.ad).to.equal( - '' + - '' - ); + it('should return One Mobile url for onemobile bidder code ' + + 'when One Mobile GET and Marketplace params are present', () => { + let bidParams = Object.assign(getNexageGetBidParams(), getMarketplaceBidParams()); + let bidRequest = createCustomBidRequest({ + bids: [{ + bidder: 'onemobile' + }], + params: bidParams + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain(NEXAGE_URL); }); - it('should be added to bidmanager including dealid from pubapi response', () => { - let bidResponse = getDefaultBidResponse(); - bidResponse.seatbid[0].bid[0].dealid = '12345'; - - server.respondWith(JSON.stringify(bidResponse)); - adapter.callBids(getDefaultBidRequest()); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - let addedBidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(addedBidResponse.dealId).to.equal('12345'); + it('should not return any url for onemobile bidder code' + + 'when only Marketplace params are present', () => { + let bidRequest = createCustomBidRequest({ + bids: [{ + bidder: 'onemobile' + }], + params: getMarketplaceBidParams() + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request).to.be.empty; }); - it('should be added to bidmanager including encrypted price from pubapi response', () => { - let bidResponse = getDefaultBidResponse(); - bidResponse.seatbid[0].bid[0].ext.encp = 'a9334987'; - server.respondWith(JSON.stringify(bidResponse)); - - adapter.callBids(getDefaultBidRequest()); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - let addedBidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(addedBidResponse.cpm).to.equal('a9334987'); + it('should return One Mobile url with required params - dcn & pos', () => { + let bidRequest = createCustomBidRequest({ + params: getNexageGetBidParams() + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain(NEXAGE_URL + 'dcn=2c9d2b50015c5ce9db6aeeed8b9500d6&pos=header'); }); - it('should not render pixels on pubapi response when no parameter is set', () => { - let bidResponse = getDefaultBidResponse(); - bidResponse.ext = { - pixels: '' - }; - server.respondWith(JSON.stringify(bidResponse)); - adapter.callBids(getDefaultBidRequest()); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - expect(document.body.querySelectorAll('iframe[src="pixels.org"]').length).to.equal(0); + it('should return One Mobile url with cmd=bid option', () => { + let bidRequest = createCustomBidRequest({ + params: getNexageGetBidParams() + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain('cmd=bid'); }); - it('should render pixels from pubapi response when param userSyncOn is set with \'bidResponse\'', () => { - let bidResponse = getDefaultBidResponse(); - bidResponse.ext = { - pixels: '' - }; + it('should return One Mobile url with generic params if ext option is present', () => { + let bidRequest = createCustomBidRequest({ + params: { + dcn: '54321123', + pos: 'footer-2324', + ext: { + param1: 'val1', + param2: 'val2', + param3: 'val3', + param4: 'val4' + } + } + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain('hb.nexage.com/bidRequest?dcn=54321123&pos=footer-2324&cmd=bid' + + '¶m1=val1¶m2=val2¶m3=val3¶m4=val4'); + }); - server.respondWith(JSON.stringify(bidResponse)); - let bidRequest = getDefaultBidRequest(); - bidRequest.bids[0].params.userSyncOn = 'bidResponse'; - adapter.callBids(bidRequest); - server.respond(); + it('should return request object for One Mobile POST endpoint when POST configuration is present', () => { + let bidConfig = getNexagePostBidParams(); + let bidRequest = createCustomBidRequest({ + params: bidConfig + }); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; + let [request] = spec.buildRequests(bidRequest.bids); + expect(request.url).to.contain(NEXAGE_URL); + expect(request.method).to.equal('POST'); + expect(request.data).to.deep.equal(bidConfig); + expect(request.options).to.deep.equal({ + contentType: 'application/json', + customHeaders: { + 'x-openrtb-version': '2.2' + } + }); + }); - let assertPixelsItem = (pixelsItemSelector) => { - let pixelsItem = document.body.querySelectorAll(pixelsItemSelector)[0]; + it('should not return request object for One Mobile POST endpoint' + + 'if required parameterers are missed', () => { + let bidRequest = createCustomBidRequest({ + params: { + imp: [] + } + }); + let [request] = spec.buildRequests(bidRequest.bids); + expect(request).to.be.empty; + }); + }); + }); - expect(pixelsItem.width).to.equal('1'); - expect(pixelsItem.height).to.equal('1'); - expect(pixelsItem.style.display).to.equal('none'); - }; + describe('getUserSyncs()', () => { + let bidResponse; + let bidRequest; - assertPixelsItem('iframe[src="pixels.org"]'); - assertPixelsItem('iframe[src="pixels1.org"]'); - expect($$PREBID_GLOBAL$$.aolGlobals.pixelsDropped).to.be.true; + beforeEach(() => { + $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = false; + config.setConfig({ + aol: { + userSyncOn: 'bidResponse' + }, }); + bidResponse = getDefaultBidResponse(); + bidResponse.ext = { + pixels: getPixels() + }; + }); - it('should not render pixels if it was rendered before', () => { - $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = true; - let bidResponse = getDefaultBidResponse(); - bidResponse.ext = { - pixels: '' - }; - server.respondWith(JSON.stringify(bidResponse)); - - let bidRequest = getDefaultBidRequest(); - bidRequest.bids[0].params.userSyncOn = 'bidResponse'; - adapter.callBids(bidRequest); - server.respond(); + it('should return user syncs only if userSyncOn equals to "bidResponse"', () => { + let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; + expect($$PREBID_GLOBAL$$.aolGlobals.pixelsDropped).to.be.true; + expect(userSyncs).to.deep.equal([ + {type: 'image', url: 'img.org'}, + {type: 'iframe', url: 'pixels1.org'} + ]); + }); - let assertPixelsItem = (pixelsItemSelector) => { - let pixelsItems = document.body.querySelectorAll(pixelsItemSelector); + it('should not return user syncs if it has already been returned', () => { + $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = true; - expect(pixelsItems.length).to.equal(0); - }; + let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); - assertPixelsItem('iframe[src="test.com"]'); - assertPixelsItem('iframe[src="test2.com"]'); - }); + expect($$PREBID_GLOBAL$$.aolGlobals.pixelsDropped).to.be.true; + expect(userSyncs).to.deep.equal([]); }); - describe('when bidCpmAdjustment is set', () => { - let bidderSettingsBackup; - let server; + it('should not return user syncs if pixels are not present', () => { + bidResponse.ext.pixels = null; - beforeEach(() => { - bidderSettingsBackup = $$PREBID_GLOBAL$$.bidderSettings; - server = sinon.fakeServer.create(); - }); + let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); - afterEach(() => { - $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsBackup; - server.restore(); - if (utils.logWarn.restore) { - utils.logWarn.restore(); - } - }); - - it('should show warning in the console', function() { - sinon.spy(utils, 'logWarn'); - server.respondWith(JSON.stringify(getDefaultBidResponse())); - $$PREBID_GLOBAL$$.bidderSettings = { - aol: { - bidCpmAdjustment: function() {} - } - }; - adapter.callBids(getDefaultBidRequest()); - server.respond(); - expect(utils.logWarn.calledOnce).to.be.true; - }); + expect($$PREBID_GLOBAL$$.aolGlobals.pixelsDropped).to.be.false; + expect(userSyncs).to.deep.equal([]); }); }); }); diff --git a/test/spec/modules/indexExchangeBidAdapter_video_spec.js b/test/spec/modules/indexExchangeBidAdapter_video_spec.js index cfbb3aa52ef..913f39c590d 100644 --- a/test/spec/modules/indexExchangeBidAdapter_video_spec.js +++ b/test/spec/modules/indexExchangeBidAdapter_video_spec.js @@ -16,9 +16,9 @@ const EMPTY_MESSAGE = 'Bid returned empty or error response'; const ERROR_MESSAGE = 'Bid returned empty or error response'; const AVAILABLE_MESSAGE = 'Bid available'; -const CYGNUS_REQUEST_BASE_URL_INSECURE = 'http://as.casalemedia.com/cygnus?v=8&fn=$$PREBID_GLOBAL$$.handleCygnusResponse&s=6&r='; +const CYGNUS_REQUEST_BASE_URL_INSECURE = 'http://as.casalemedia.com/cygnus?v=8&fn=' + preBidNameSpace + '.handleCygnusResponse&s=6&r='; -const CYGNUS_REQUEST_BASE_URL_SECURE = 'https://as-sec.casalemedia.com/cygnus?v=8&fn=$$PREBID_GLOBAL$$.handleCygnusResponse&s=6&r='; +const CYGNUS_REQUEST_BASE_URL_SECURE = 'https://as-sec.casalemedia.com/cygnus?v=8&fn=' + preBidNameSpace + '.handleCygnusResponse&s=6&r='; const DEFAULT_MIMES_MAP = { FLASH: ['video/mp4', 'video/x-flv'], diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index cee521b2921..eabf1f81f32 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -3,6 +3,7 @@ import { spec } from 'modules/openxBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; const URLBASE = '/w/1.0/arj'; +const URLBASEVIDEO = '/v/1.0/avjp'; describe('OpenxAdapter', () => { const adapter = newBidder(spec); @@ -21,25 +22,69 @@ describe('OpenxAdapter', () => { 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', + 'mediaType': 'banner', 'sizes': [[300, 250], [300, 600]], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + let videoBid = { + 'bidder': 'openx', + 'params': { + 'unit': '12345678', + 'delDomain': 'test-del-domain', + 'video': { + 'be': 'true', + 'url': 'abc.com', + 'vtest': '1' + } + }, + 'adUnitCode': 'adunit-code', + 'mediaType': 'video', + 'sizes': [640, 480], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' + }; + + it('should return true when required params found for a banner ad', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed for a banner ad', () => { let bid = Object.assign({}, bid); delete bid.params; bid.params = {'unit': '12345678'}; expect(spec.isBidRequestValid(bid)).to.equal(false); }); + + it('should return true when required params found for a video ad', () => { + expect(spec.isBidRequestValid(videoBid)).to.equal(true); + }); + + it('should return false when required params are not passed for a video ad', () => { + let videoBid = Object.assign({}, videoBid); + delete videoBid.params; + videoBid.params = {}; + expect(spec.isBidRequestValid(videoBid)).to.equal(false); + }); }); - describe('buildRequests', () => { + describe('buildRequests for banner ads', () => { + let bidRequestsWithNoMediaType = [{ + 'bidder': 'openx', + 'params': { + 'unit': '12345678', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }]; let bidRequests = [{ 'bidder': 'openx', 'params': { @@ -47,21 +92,28 @@ describe('OpenxAdapter', () => { 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', + 'mediaType': 'banner', 'sizes': [[300, 250], [300, 600]], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', }]; + it('should send bid request to openx url via GET, even without mediaType specified', () => { + const request = spec.buildRequests(bidRequestsWithNoMediaType); + expect(request[0].url).to.equal('//' + bidRequests[0].params.delDomain + URLBASE); + expect(request[0].method).to.equal('GET'); + }); + it('should send bid request to openx url via GET', () => { const request = spec.buildRequests(bidRequests); - expect(request.url).to.equal('//' + bidRequests[0].params.delDomain + URLBASE); - expect(request.method).to.equal('GET'); + expect(request[0].url).to.equal('//' + bidRequests[0].params.delDomain + URLBASE); + expect(request[0].method).to.equal('GET'); }); it('should have the correct parameters', () => { const request = spec.buildRequests(bidRequests); - const dataParams = request.data; + const dataParams = request[0].data; expect(dataParams.auid).to.exist; expect(dataParams.auid).to.equal('12345678'); @@ -82,7 +134,7 @@ describe('OpenxAdapter', () => { ); const request = spec.buildRequests([bidRequest]); - const dataParams = request.data; + const dataParams = request[0].data; expect(dataParams.tps).to.exist; expect(dataParams.tps).to.equal(btoa('test1=testval1.&test2=testval2_,testval3')); @@ -101,7 +153,7 @@ describe('OpenxAdapter', () => { ); const request = spec.buildRequests([bidRequest]); - const dataParams = request.data; + const dataParams = request[0].data; expect(dataParams.aumfs).to.exist; expect(dataParams.aumfs).to.equal('1500'); @@ -120,14 +172,50 @@ describe('OpenxAdapter', () => { ); const request = spec.buildRequests([bidRequest]); - const dataParams = request.data; + const dataParams = request[0].data; expect(dataParams.bc).to.exist; expect(dataParams.bc).to.equal('hb_override'); }); }); - describe('interpretResponse', () => { + describe('buildRequests for video', () => { + let bidRequests = [{ + 'bidder': 'openx', + 'mediaType': 'video', + 'params': { + 'unit': '12345678', + 'delDomain': 'test-del-domain', + 'video': { + 'url': 'abc.com', + } + }, + 'adUnitCode': 'adunit-code', + 'sizes': [640, 480], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' + }]; + + it('should send bid request to openx url via GET', () => { + const request = spec.buildRequests(bidRequests); + expect(request[0].url).to.equal('http://' + bidRequests[0].params.delDomain + URLBASEVIDEO); + expect(request[0].method).to.equal('GET'); + }); + + it('should have the correct parameters', () => { + const request = spec.buildRequests(bidRequests); + const dataParams = request[0].data; + + expect(dataParams.auid).to.exist; + expect(dataParams.auid).to.equal('12345678'); + expect(dataParams.url).to.exist; + expect(dataParams.url).to.equal('abc.com'); + }); + }); + + describe('interpretResponse for banner ads', () => { let bids = [{ 'bidder': 'openx', 'params': { @@ -135,6 +223,7 @@ describe('OpenxAdapter', () => { 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', + 'mediaType': 'banner', 'sizes': [[300, 250], [300, 600]], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', @@ -203,7 +292,7 @@ describe('OpenxAdapter', () => { }); it('handles nobid responses', () => { - bidResponse = { + let bidResponse = { 'ads': { 'version': 1, @@ -217,4 +306,65 @@ describe('OpenxAdapter', () => { expect(result.length).to.equal(0); }); }); + + describe('interpretResponse for video ads', () => { + let bids = [{ + 'bidder': 'openx', + 'mediaType': 'video', + 'params': { + 'unit': '12345678', + 'delDomain': 'test-del-domain', + 'video': { + 'url': 'abc.com', + } + }, + 'adUnitCode': 'adunit-code', + 'sizes': [640, 480], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' + }]; + let bidRequest = { + method: 'GET', + url: 'url', + data: {}, + payload: {'bid': bids[0], 'startTime': new Date()} + }; + let bidResponse = { + 'pub_rev': '1', + 'width': '640', + 'height': '480', + 'adid': '5678', + 'vastUrl': 'http://testvast.com', + 'pixels': 'http://testpixels.net' + }; + + it('should return correct bid response', () => { + let expectedResponse = [ + { + 'requestId': '30b31c1838de1e', + 'bidderCode': 'openx', + 'cpm': 1, + 'width': '640', + 'height': '480', + 'mediaType': 'video', + 'creativeId': '5678', + 'vastUrl': 'http://testvast.com', + 'ttl': 300, + 'netRevenue': true, + 'currency': 'USD' + } + ]; + + let result = spec.interpretResponse({body: bidResponse}, bidRequest); + expect(JSON.stringify(Object.keys(result[0]).sort())).to.eql(JSON.stringify(Object.keys(expectedResponse[0]).sort())); + }); + + it('handles nobid responses', () => { + let bidResponse = {'vastUrl': '', 'pub_rev': '', 'width': '', 'height': '', 'adid': '', 'pixels': ''}; + let result = spec.interpretResponse({body: bidResponse}, bidRequest); + expect(result.length).to.equal(0); + }); + }); }); diff --git a/test/spec/modules/piximediaBidAdapter_spec.js b/test/spec/modules/piximediaBidAdapter_spec.js index 14834c81714..17f4da32e6b 100644 --- a/test/spec/modules/piximediaBidAdapter_spec.js +++ b/test/spec/modules/piximediaBidAdapter_spec.js @@ -96,7 +96,7 @@ describe('Piximedia adapter tests', function () { expect(parsedBidUrl.hostname).to.equal('static.adserver.pm'); expect(parsedBidUrl.query).to.equal(''); - expect(parsedBidUrl.pathname.replace(/cbid=[a-f0-9]+/, 'cbid=210af5668b1e23').replace(/rand=[0-9]+$/, 'rand=42')).to.equal('/prebid/site_id=TEST/placement_id=TEST/jsonp=$$PREBID_GLOBAL$$.handlePiximediaCallback/sizes=300x250/cbid=210af5668b1e23/rand=42'); + expect(parsedBidUrl.pathname.replace(/cbid=[a-f0-9]+/, 'cbid=210af5668b1e23').replace(/rand=[0-9]+$/, 'rand=42')).to.equal('/prebid/site_id=TEST/placement_id=TEST/jsonp=' + preBidNameSpace + '.handlePiximediaCallback/sizes=300x250/cbid=210af5668b1e23/rand=42'); }); it('should call the correct Prebid URL when using the default URL with a deal and custom data', function () { @@ -124,7 +124,7 @@ describe('Piximedia adapter tests', function () { expect(parsedBidUrl.hostname).to.equal('static.adserver.pm'); expect(parsedBidUrl.query).to.equal(''); - expect(parsedBidUrl.pathname.replace(/cbid=[a-f0-9]+/, 'cbid=210af5668b1e23').replace(/rand=[0-9]+$/, 'rand=42')).to.equal('/prebid/site_id=TEST/placement_id=TEST/l_id=1295/custom=bespoke/custom2=bespoke2/custom3=/custom4=/jsonp=$$PREBID_GLOBAL$$.handlePiximediaCallback/sizes=300x250/cbid=210af5668b1e23/rand=42'); + expect(parsedBidUrl.pathname.replace(/cbid=[a-f0-9]+/, 'cbid=210af5668b1e23').replace(/rand=[0-9]+$/, 'rand=42')).to.equal('/prebid/site_id=TEST/placement_id=TEST/l_id=1295/custom=bespoke/custom2=bespoke2/custom3=/custom4=/jsonp=' + preBidNameSpace + '.handlePiximediaCallback/sizes=300x250/cbid=210af5668b1e23/rand=42'); }); it('should call the correct Prebid URL when using the default URL and overridding sizes', function () { @@ -152,7 +152,7 @@ describe('Piximedia adapter tests', function () { expect(parsedBidUrl.hostname).to.equal('static.adserver.pm'); expect(parsedBidUrl.query).to.equal(''); - expect(parsedBidUrl.pathname.replace(/cbid=[a-f0-9]+/, 'cbid=210af5668b1e23').replace(/rand=[0-9]+$/, 'rand=42')).to.equal('/prebid/site_id=TEST/placement_id=TEST/jsonp=$$PREBID_GLOBAL$$.handlePiximediaCallback/sizes=300x600%2C728x90/cbid=210af5668b1e23/rand=42'); + expect(parsedBidUrl.pathname.replace(/cbid=[a-f0-9]+/, 'cbid=210af5668b1e23').replace(/rand=[0-9]+$/, 'rand=42')).to.equal('/prebid/site_id=TEST/placement_id=TEST/jsonp=' + preBidNameSpace + '.handlePiximediaCallback/sizes=300x600%2C728x90/cbid=210af5668b1e23/rand=42'); }); it('should call the correct Prebid URL when supplying a custom URL', function () { @@ -180,7 +180,7 @@ describe('Piximedia adapter tests', function () { expect(parsedBidUrl.hostname).to.equal('resources.pm'); expect(parsedBidUrl.query).to.equal(''); - expect(parsedBidUrl.pathname.replace(/cbid=[a-f0-9]+/, 'cbid=210af5668b1e23').replace(/rand=[0-9]+$/, 'rand=42')).to.equal('/tests/prebid/bids.js/site_id=TEST/placement_id=TEST/jsonp=$$PREBID_GLOBAL$$.handlePiximediaCallback/sizes=300x250/cbid=210af5668b1e23/rand=42'); + expect(parsedBidUrl.pathname.replace(/cbid=[a-f0-9]+/, 'cbid=210af5668b1e23').replace(/rand=[0-9]+$/, 'rand=42')).to.equal('/tests/prebid/bids.js/site_id=TEST/placement_id=TEST/jsonp=' + preBidNameSpace + '.handlePiximediaCallback/sizes=300x250/cbid=210af5668b1e23/rand=42'); }); }); diff --git a/test/spec/modules/platformioBidAdapter_spec.js b/test/spec/modules/platformioBidAdapter_spec.js index 86bf52cac72..d775229c9e3 100644 --- a/test/spec/modules/platformioBidAdapter_spec.js +++ b/test/spec/modules/platformioBidAdapter_spec.js @@ -11,7 +11,8 @@ describe('Platformio Adapter Tests', () => { pubId: '28082', siteId: '26047', placementId: '123', - size: '300x250' + size: '300x250', + bidFloor: '0.001' } }, { placementCode: '/DfpAccount2/slot2', @@ -44,11 +45,13 @@ describe('Platformio Adapter Tests', () => { expect(ortbRequest.imp[0].banner).to.not.equal(null); expect(ortbRequest.imp[0].banner.w).to.equal(300); expect(ortbRequest.imp[0].banner.h).to.equal(250); + expect(ortbRequest.imp[0].bidfloor).to.equal('0.001'); // slot 2 expect(ortbRequest.imp[1].tagid).to.equal('456'); expect(ortbRequest.imp[1].banner).to.not.equal(null); expect(ortbRequest.imp[1].banner.w).to.equal(250); expect(ortbRequest.imp[1].banner.h).to.equal(250); + expect(ortbRequest.imp[1].bidfloor).to.equal('0.000001'); }); it('Verify parse response', () => { @@ -59,9 +62,11 @@ describe('Platformio Adapter Tests', () => { bid: [{ impid: ortbRequest.imp[0].id, price: 1.25, - adm: 'This is an Ad' + adm: 'This is an Ad', + adid: '471810', }] - }] + }], + cur: 'USD' }; const bids = spec.interpretResponse({ body: ortbResponse }, request); expect(bids).to.have.lengthOf(1); @@ -71,9 +76,9 @@ describe('Platformio Adapter Tests', () => { expect(bid.ad).to.equal('This is an Ad'); expect(bid.width).to.equal(300); expect(bid.height).to.equal(250); - expect(bid.adId).to.equal('bid12345'); - expect(bid.creative_id).to.equal('bid12345'); - expect(bid.creativeId).to.equal('bid12345'); + expect(bid.creativeId).to.equal('471810'); + expect(bid.currency).to.equal('USD'); + expect(bid.ttl).to.equal(360); }); it('Verify full passback', () => { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 78eef4b016b..0403617a846 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -43,7 +43,10 @@ const REQUEST = { 'bidder': 'appnexus', 'params': { 'placementId': '10433394', - 'member': 123 + 'member': 123, + 'randomKey': 123456789, + 'single_test': null, + 'myMultiVar': ['myValue', 124578] } } ] @@ -201,6 +204,8 @@ describe('S2S Adapter', () => { const requestBid = JSON.parse(requests[0].requestBody); expect(requestBid.ad_units[0].bids[0].params.placementId).to.exist.and.to.be.a('number'); expect(requestBid.ad_units[0].bids[0].params.member).to.exist.and.to.be.a('string'); + expect(requestBid.ad_units[0].bids[0].params.keywords).to.exist.and.to.be.an('array').and.to.have.lengthOf(3); + expect(requestBid.ad_units[0].bids[0].params.keywords[0]).to.be.an('object').that.has.all.keys('key', 'value'); }); }); diff --git a/test/spec/modules/pulsepointLiteBidAdapter_spec.js b/test/spec/modules/pulsepointLiteBidAdapter_spec.js index 9731164cd50..2c6f5f0681f 100644 --- a/test/spec/modules/pulsepointLiteBidAdapter_spec.js +++ b/test/spec/modules/pulsepointLiteBidAdapter_spec.js @@ -100,6 +100,35 @@ describe('PulsePoint Lite Adapter Tests', () => { expect(bid.adId).to.equal('bid12345'); expect(bid.creative_id).to.equal('bid12345'); expect(bid.creativeId).to.equal('bid12345'); + expect(bid.netRevenue).to.equal(true); + expect(bid.currency).to.equal('USD'); + expect(bid.ttl).to.equal(20); + }); + + it('Verify use ttl in ext', () => { + const request = spec.buildRequests(slotConfigs); + const ortbRequest = JSON.parse(request.data); + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: 'This is an Ad', + ext: { + ttl: 30, + netRevenue: false, + currency: 'INR' + } + }] + }] + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + expect(bids).to.have.lengthOf(1); + // verify first bid + const bid = bids[0]; + expect(bid.ttl).to.equal(30); + expect(bid.netRevenue).to.equal(false); + expect(bid.currency).to.equal('INR'); }); it('Verify full passback', () => { diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index bfb89cf4ead..a14096ce174 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -73,7 +73,7 @@ describe('smartadserver adapter tests', function () { expect(parsedBidUrl.hostname).to.equal('www.smartadserver.com'); expect(parsedBidUrl.pathname).to.equal('/prebid'); - expect(parsedBidUrlQueryString).to.have.property('pbjscbk').and.to.equal('$$PREBID_GLOBAL$$.' + smartCallback); + expect(parsedBidUrlQueryString).to.have.property('pbjscbk').and.to.equal(preBidNameSpace + '.' + smartCallback); expect(parsedBidUrlQueryString).to.have.property('siteid').and.to.equal('1234'); expect(parsedBidUrlQueryString).to.have.property('pgid').and.to.equal('5678'); expect(parsedBidUrlQueryString).to.have.property('fmtid').and.to.equal('90'); diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index c5ad1b2cb25..c4eadd02738 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -1,178 +1,137 @@ -import {expect} from 'chai'; -import Adapter from 'modules/sovrnBidAdapter'; -import bidmanager from 'src/bidmanager'; -import adloader from 'src/adloader'; -var utils = require('src/utils'); - -describe('sovrn adapter tests', function () { - let adapter; - const bidderRequest = { - bidderCode: 'sovrn', - bids: [ - { - bidId: 'bidId1', - bidder: 'sovrn', - params: { - tagid: '315045', - bidfloor: 1.25 - }, - sizes: [[320, 50]], - placementCode: 'div-gpt-ad-12345-1' - }, - { - bidId: 'bidId2', - bidder: 'sovrn', - params: { - tagid: '315046' - }, - sizes: [[320, 50]], - placementCode: 'div-gpt-ad-12345-2' - }, - { - bidId: 'bidId3', - bidder: 'sovrn', - params: { - tagid: '315047' - }, - sizes: [[320, 50]], - placementCode: 'div-gpt-ad-12345-2' - }, - ] - }; +import { expect } from 'chai'; +import { spec } from 'modules/sovrnBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { REPO_AND_VERSION } from 'src/constants'; - beforeEach(() => adapter = new Adapter()); +const ENDPOINT = `//ap.lijit.com/rtb/bid?src=${REPO_AND_VERSION}`; - describe('requestBids', function () { - let stubLoadScript; +describe('sovrnBidAdapter', function() { + const adapter = newBidder(spec); - beforeEach(() => { - stubLoadScript = sinon.stub(adloader, 'loadScript'); + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'sovrn', + 'params': { + 'tagid': '403370' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(bid)).to.equal(true); }); - afterEach(() => { - stubLoadScript.restore(); + it('should return false when tagid not passed correctly', () => { + bid.params.tagid = 'ABCD'; + expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - - it('loads the request script', function () { - adapter.callBids(bidderRequest); - - let sovrnScript = decodeURIComponent(stubLoadScript.getCall(0).args[0]); - let firstExpectedImpObj = '{"id":"bidId1","banner":{"w":320,"h":50},"tagid":"315045","bidfloor":1.25}'; - let secondExpectedImpObj = '{"id":"bidId2","banner":{"w":320,"h":50},"tagid":"315046","bidfloor":""}'; - - expect(sovrnScript).to.contain(firstExpectedImpObj); - expect(sovrnScript).to.contain(secondExpectedImpObj); + it('should return false when require params are not passed', () => { + let bid = Object.assign({}, bid); + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); }); }); - describe('sovrnResponse', function () { - let stubAddBidResponse; - let getRequestStub; - let getRequestsStub; - - beforeEach(() => { - stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - getRequestStub = sinon.stub(utils, 'getBidRequest'); - getRequestStub.withArgs(bidderRequest.bids[0].bidId).returns(bidderRequest.bids[0]); - getRequestStub.withArgs(bidderRequest.bids[1].bidId).returns(bidderRequest.bids[1]); - getRequestStub.withArgs(bidderRequest.bids[2].bidId).returns(bidderRequest.bids[2]); - - getRequestsStub = sinon.stub(utils, 'getBidderRequestAllAdUnits'); - getRequestsStub.returns(bidderRequest); + describe('buildRequests', () => { + let bidRequests = [{ + 'bidder': 'sovrn', + 'params': { + 'tagid': '403370' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + + const request = spec.buildRequests(bidRequests); + + it('sends bid request to our endpoint via POST', () => { + expect(request.method).to.equal('POST'); }); - afterEach(() => { - stubAddBidResponse.restore(); - getRequestStub.restore(); - getRequestsStub.restore(); + it('attaches source and version to endpoint URL as query params', () => { + expect(request.url).to.equal(ENDPOINT) }); + }); - it('should exist and be a function', function () { - expect($$PREBID_GLOBAL$$.sovrnResponse).to.exist.and.to.be.a('function'); + describe('interpretResponse', () => { + let response = { + body: { + 'id': '37386aade21a71', + 'seatbid': [{ + 'bid': [{ + 'id': 'a_403370_332fdb9b064040ddbec05891bd13ab28', + 'impid': '263c448586f5a1', + 'price': 0.45882675, + 'nurl': '', + 'adm': '', + 'h': 90, + 'w': 728 + }] + }] + } + }; + + it('should get the correct bid response', () => { + let expectedResponse = [{ + 'requestId': '263c448586f5a1', + 'cpm': 0.45882675, + 'width': 728, + 'height': 90, + 'creativeId': 'a_403370_332fdb9b064040ddbec05891bd13ab28', + 'dealId': null, + 'currency': 'USD', + 'netRevenue': true, + 'mediaType': 'banner', + 'ad': decodeURIComponent(`>`), + 'ttl': 60000 + }]; + + let result = spec.interpretResponse(response); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('should add empty bid responses if no bids returned', function () { - let response = { - 'id': '54321', - 'seatbid': [] - }; - - $$PREBID_GLOBAL$$.sovrnResponse(response); - - let bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - let bidObject1 = stubAddBidResponse.getCall(0).args[1]; - let bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0]; - let bidObject2 = stubAddBidResponse.getCall(1).args[1]; - let bidPlacementCode3 = stubAddBidResponse.getCall(2).args[0]; - let bidObject3 = stubAddBidResponse.getCall(2).args[1]; - - expect(bidPlacementCode1).to.equal('div-gpt-ad-12345-1'); - expect(bidObject1.getStatusCode()).to.equal(2); - expect(bidObject1.bidderCode).to.equal('sovrn'); - - expect(bidPlacementCode2).to.equal('div-gpt-ad-12345-2'); - expect(bidObject2.getStatusCode()).to.equal(2); - expect(bidObject2.bidderCode).to.equal('sovrn'); - - expect(bidPlacementCode3).to.equal('div-gpt-ad-12345-2'); - expect(bidObject3.getStatusCode()).to.equal(2); - expect(bidObject3.bidderCode).to.equal('sovrn'); - - stubAddBidResponse.calledThrice; + it('should get correct bid response when dealId is passed', () => { + response.body.dealId = 'baking'; + + let expectedResponse = [{ + 'requestId': '263c448586f5a1', + 'cpm': 0.45882675, + 'width': 728, + 'height': 90, + 'creativeId': 'a_403370_332fdb9b064040ddbec05891bd13ab28', + 'dealId': 'baking', + 'currency': 'USD', + 'netRevenue': true, + 'mediaType': 'banner', + 'ad': decodeURIComponent(`>`), + 'ttl': 60000 + }]; + + let result = spec.interpretResponse(response); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('should add a bid response for bids returned and empty bid responses for the rest', function () { + it('handles empty bid response', () => { let response = { - 'id': '54321111', - 'seatbid': [ { - 'bid': [ { - 'id': '1111111', - 'impid': 'bidId2', - 'price': 0.09, - 'nurl': 'http://url', - 'adm': 'ad-code', - 'h': 250, - 'w': 300, - 'dealid': 'ADEAL123', - 'ext': { } - } ] - } ] + body: { + 'id': '37386aade21a71', + 'seatbid': [] + } }; - - $$PREBID_GLOBAL$$.sovrnResponse(response); - - let bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - let bidObject1 = stubAddBidResponse.getCall(0).args[1]; - let bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0]; - let bidObject2 = stubAddBidResponse.getCall(1).args[1]; - let bidPlacementCode3 = stubAddBidResponse.getCall(2).args[0]; - let bidObject3 = stubAddBidResponse.getCall(2).args[1]; - - expect(bidPlacementCode1).to.equal('div-gpt-ad-12345-2'); - expect(bidObject1.getStatusCode()).to.equal(1); - expect(bidObject1.bidderCode).to.equal('sovrn'); - expect(bidObject1.creative_id).to.equal('1111111'); - expect(bidObject1.cpm).to.equal(0.09); - expect(bidObject1.height).to.equal(250); - expect(bidObject1.width).to.equal(300); - expect(bidObject1.ad).to.equal('ad-code'); - expect(bidObject1.adId).to.equal('bidId2'); - expect(bidObject1.dealId).to.equal('ADEAL123'); - - expect(bidPlacementCode2).to.equal('div-gpt-ad-12345-1'); - expect(bidObject2.getStatusCode()).to.equal(2); - expect(bidObject2.bidderCode).to.equal('sovrn'); - - expect(bidPlacementCode3).to.equal('div-gpt-ad-12345-2'); - expect(bidObject3.getStatusCode()).to.equal(2); - expect(bidObject3.bidderCode).to.equal('sovrn'); - - stubAddBidResponse.calledThrice; + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); }); }); }); diff --git a/test/spec/modules/tapsenseBidAdapter_spec.js b/test/spec/modules/tapsenseBidAdapter_spec.js index 71f61af2a65..d48fc76bf96 100644 --- a/test/spec/modules/tapsenseBidAdapter_spec.js +++ b/test/spec/modules/tapsenseBidAdapter_spec.js @@ -184,8 +184,11 @@ describe('TapSenseAdapter', () => { expect(adloader.loadScript.firstCall.args[0]).to.match( /price_floor=0\.01&/ ); + + //TODO: need to fix this case expect(adloader.loadScript.firstCall.args[0]).to.match( - /callback=$$PREBID_GLOBAL$$\.tapsense\.callback_with_price_.+&/ + //callback=$$PREBID_GLOBAL$$\.tapsense\.callback_with_price_.+&/ + new RegExp('callback='+ preBidNameSpace +'.tapsense.callback_with_price_') ); }) }) diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js index 95658883fd0..51e07e5e1ba 100644 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -68,14 +68,14 @@ describe('triplelift adapter', () => { expect(secondBidScriptURL).to.contain(route); let firstScriptParams = parseURL(firstBidScriptURL).search; - expect(firstScriptParams).to.have.property('callback', '$$PREBID_GLOBAL$$.TLCB'); + expect(firstScriptParams).to.have.property('callback', preBidNameSpace + '.TLCB'); expect(firstScriptParams).to.have.property('callback_id', 'bidId1'); expect(firstScriptParams).to.have.property('inv_code', 'codeA'); expect(firstScriptParams).to.have.property('size', '728x90'); expect(firstScriptParams).to.have.property('referrer'); let secondScriptParams = parseURL(secondBidScriptURL).search; - expect(secondScriptParams).to.have.property('callback', '$$PREBID_GLOBAL$$.TLCB'); + expect(secondScriptParams).to.have.property('callback', preBidNameSpace + '.TLCB'); expect(secondScriptParams).to.have.property('callback_id', 'bidId2'); expect(secondScriptParams).to.have.property('inv_code', 'codeB'); expect(secondScriptParams).to.have.property('size', '300x600'); diff --git a/test/spec/modules/twengaBidAdapter_spec.js b/test/spec/modules/twengaBidAdapter_spec.js index dcead6c4578..28457fc8b8a 100644 --- a/test/spec/modules/twengaBidAdapter_spec.js +++ b/test/spec/modules/twengaBidAdapter_spec.js @@ -50,7 +50,7 @@ describe('twenga adapter tests', function () { expect(parsedBidUrl.pathname).to.equal('/Bid'); expect(parsedBidUrlQueryString).to.have.property('s').and.to.equal('h'); - expect(parsedBidUrlQueryString).to.have.property('callback').and.to.equal('$$PREBID_GLOBAL$$.handleTwCB'); + expect(parsedBidUrlQueryString).to.have.property('callback').and.to.equal(preBidNameSpace + '.handleTwCB'); expect(parsedBidUrlQueryString).to.have.property('callback_uid').and.to.equal('tw_abcd1234'); expect(parsedBidUrlQueryString).to.have.property('id').and.to.equal('test'); diff --git a/test/spec/modules/wideorbitBidAdapter_spec.js b/test/spec/modules/wideorbitBidAdapter_spec.js index 9ace04883e6..527a3cf78b5 100644 --- a/test/spec/modules/wideorbitBidAdapter_spec.js +++ b/test/spec/modules/wideorbitBidAdapter_spec.js @@ -98,7 +98,7 @@ describe('wideorbit adapter tests', function () { expect(parsedBidUrlQueryString).to.have.property('cts').to.have.length.above(0); expect(parsedBidUrlQueryString).to.have.property('arp').and.to.equal('0'); expect(parsedBidUrlQueryString).to.have.property('fl').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('jscb').and.to.equal('window.$$PREBID_GLOBAL$$.handleWideOrbitCallback'); + expect(parsedBidUrlQueryString).to.have.property('jscb').and.to.equal('window.' + preBidNameSpace + '.handleWideOrbitCallback'); expect(parsedBidUrlQueryString).to.have.property('mpp').and.to.equal('0'); expect(parsedBidUrlQueryString).to.have.property('cb').to.have.length.above(0); expect(parsedBidUrlQueryString).to.have.property('hb').and.to.equal('1'); @@ -174,7 +174,7 @@ describe('wideorbit adapter tests', function () { expect(parsedBidUrlQueryString).to.have.property('cts').to.have.length.above(0); expect(parsedBidUrlQueryString).to.have.property('arp').and.to.equal('0'); expect(parsedBidUrlQueryString).to.have.property('fl').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('jscb').and.to.equal('window.$$PREBID_GLOBAL$$.handleWideOrbitCallback'); + expect(parsedBidUrlQueryString).to.have.property('jscb').and.to.equal('window.' + preBidNameSpace + '.handleWideOrbitCallback'); expect(parsedBidUrlQueryString).to.have.property('mpp').and.to.equal('0'); expect(parsedBidUrlQueryString).to.have.property('cb').to.have.length.above(0); expect(parsedBidUrlQueryString).to.have.property('hb').and.to.equal('1'); @@ -247,7 +247,7 @@ describe('wideorbit adapter tests', function () { expect(parsedBidUrlQueryString).to.have.property('cts').to.have.length.above(0); expect(parsedBidUrlQueryString).to.have.property('arp').and.to.equal('0'); expect(parsedBidUrlQueryString).to.have.property('fl').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('jscb').and.to.equal('window.$$PREBID_GLOBAL$$.handleWideOrbitCallback'); + expect(parsedBidUrlQueryString).to.have.property('jscb').and.to.equal('window.' + preBidNameSpace + '.handleWideOrbitCallback'); expect(parsedBidUrlQueryString).to.have.property('mpp').and.to.equal('0'); expect(parsedBidUrlQueryString).to.have.property('cb').to.have.length.above(0); expect(parsedBidUrlQueryString).to.have.property('hb').and.to.equal('1'); diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js index d2a533be17e..812a080280d 100644 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ b/test/spec/modules/yieldmoBidAdapter_spec.js @@ -74,7 +74,7 @@ describe('Yieldmo adapter', () => { expect(parsedPlacementParams[1].sizes[1][1]).to.equal(250); // impression information - expect(requestParams).to.have.property('callback', '$$PREBID_GLOBAL$$.YMCB'); + expect(requestParams).to.have.property('callback', preBidNameSpace + '.YMCB'); expect(requestParams).to.have.property('page_url'); }); }); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index d6f1451b65c..5a91fe218ef 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -779,7 +779,7 @@ describe('Unit: Prebid Module', function () { adaptermanager.callBids.restore(); }); - it('should not callBids if a video adUnit has non-video bidders', () => { + it('should only request video bidders on video adunits', () => { sinon.spy(adaptermanager, 'callBids'); const videoAdaptersBackup = adaptermanager.videoAdapters; adaptermanager.videoAdapters = ['appnexusAst']; @@ -793,7 +793,35 @@ describe('Unit: Prebid Module', function () { }]; $$PREBID_GLOBAL$$.requestBids({adUnits}); - sinon.assert.notCalled(adaptermanager.callBids); + sinon.assert.calledOnce(adaptermanager.callBids); + + const spyArgs = adaptermanager.callBids.getCall(0); + const biddersCalled = spyArgs.args[0].adUnits[0].bids; + expect(biddersCalled.length).to.equal(1); + + adaptermanager.callBids.restore(); + adaptermanager.videoAdapters = videoAdaptersBackup; + }); + + it('should only request video bidders on video adunits configured with mediaTypes', () => { + sinon.spy(adaptermanager, 'callBids'); + const videoAdaptersBackup = adaptermanager.videoAdapters; + adaptermanager.videoAdapters = ['appnexusAst']; + const adUnits = [{ + code: 'adUnit-code', + mediaTypes: {video: {context: 'instream'}}, + bids: [ + {bidder: 'appnexus', params: {placementId: 'id'}}, + {bidder: 'appnexusAst', params: {placementId: 'id'}} + ] + }]; + + $$PREBID_GLOBAL$$.requestBids({adUnits}); + sinon.assert.calledOnce(adaptermanager.callBids); + + const spyArgs = adaptermanager.callBids.getCall(0); + const biddersCalled = spyArgs.args[0].adUnits[0].bids; + expect(biddersCalled.length).to.equal(1); adaptermanager.callBids.restore(); adaptermanager.videoAdapters = videoAdaptersBackup; diff --git a/webpack.conf.js b/webpack.conf.js index 38f4e5dadd7..ae80de1435f 100644 --- a/webpack.conf.js +++ b/webpack.conf.js @@ -19,7 +19,10 @@ module.exports = { ], }, output: { - jsonpFunction: prebid.globalVarName+"Chunk" + /* https://webpack.js.org/configuration/output/#output-jsonpfunction + This function dosen't affect any build process + */ + jsonpFunction: 'pbjsChunk' }, module: { rules: [