diff --git a/.babelrc b/.babelrc index 8726a848e2e..b366d78478e 100644 --- a/.babelrc +++ b/.babelrc @@ -1,4 +1,8 @@ { "presets": ["es2015"], - "plugins": ["transform-object-assign", "transform-es3-property-literals", "transform-es3-member-expression-literals"] + "plugins": [ + "transform-object-assign", + "transform-es3-property-literals", + "transform-es3-member-expression-literals" + ] } diff --git a/integrationExamples/gpt/hello_world.html b/integrationExamples/gpt/hello_world.html index 0f5e24a301a..aa4bf5ea782 100644 --- a/integrationExamples/gpt/hello_world.html +++ b/integrationExamples/gpt/hello_world.html @@ -12,91 +12,91 @@ --> - - - - - + + + - - - - - - - -

Prebid.js Test

-
Div-1
-
- -
- - + + function sendAdserverRequest() { + if (pbjs.adserverRequestSent) return; + pbjs.adserverRequestSent = true; + googletag.cmd.push(function() { + pbjs.que.push(function() { + pbjs.setTargetingForGPTAsync(); + googletag.pubads().refresh(); + }); + }); + } + + setTimeout(function() { + sendAdserverRequest(); + }, PREBID_TIMEOUT); + + + + + + + + + +

Prebid.js Test

+
Div-1
+
+ +
+ + \ No newline at end of file diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index b496a66d081..8e73d5c87b4 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -1,5 +1,6 @@ +import { userSync } from 'src/userSync' const { registerBidder } = require('../src/adapters/bidderFactory'); -const utils = require('../src/utils'); +const { config } = require('../src/config'); const BIDDER_CODE = '33across'; const END_POINT = 'https://ssc.33across.com/api/v1/hb'; @@ -38,9 +39,7 @@ function _createServerRequest(bidRequest) { } } - // Allowing site to be a test configuration object or just the id (former required for testing, - // latter when used by publishers) - ttxRequest.site = params.site || { id: params.siteId }; + ttxRequest.site = { id: params.siteId }; // Go ahead send the bidId in request to 33exchange so it's kept track of in the bid response and // therefore in ad targetting process @@ -51,28 +50,18 @@ function _createServerRequest(bidRequest) { withCredentials: false }; - if (bidRequest.params.customHeaders) { - options.customHeaders = bidRequest.params.customHeaders; - } + // Allow the ability to configure the HB endpoint for testing purposes. + const ttxSettings = config.getConfig('ttxSettings'); + const url = (ttxSettings && ttxSettings.url) || END_POINT; return { 'method': 'POST', - 'url': bidRequest.params.url || END_POINT, + 'url': url, 'data': JSON.stringify(ttxRequest), 'options': options } } -// Sync object will always be of type iframe for ttx -function _createSync(bid) { - const syncUrl = bid.params.syncUrl || SYNC_ENDPOINT; - - return { - type: 'iframe', - url: `${syncUrl}&id=${bid.params.siteId || bid.params.site.id}` - } -} - function _getFormatSize(sizeArr) { return { w: sizeArr[0], @@ -81,6 +70,24 @@ function _getFormatSize(sizeArr) { } } +// Register one sync per bid since each ad unit may potenitally be linked to a uniqe guid +// Sync type will always be 'iframe' for 33Across +function _registerUserSyncs(requestData) { + let ttxRequest; + try { + ttxRequest = JSON.parse(requestData); + } catch (err) { + // No point in trying to register sync since the requisite data cannot be parsed. + return; + } + const ttxSettings = config.getConfig('ttxSettings'); + + let syncUrl = (ttxSettings && ttxSettings.syncUrl) || SYNC_ENDPOINT; + + syncUrl = `${syncUrl}&id=${ttxRequest.site.id}`; + userSync.registerSync('iframe', BIDDER_CODE, syncUrl); +} + function isBidRequestValid(bid) { if (bid.bidder !== BIDDER_CODE || typeof bid.params === 'undefined') { return false; @@ -104,7 +111,12 @@ function buildRequests(bidRequests) { } // NOTE: At this point, the response from 33exchange will only ever contain one bid i.e. the highest bid -function interpretResponse(serverResponse) { +function interpretResponse(serverResponse, bidRequest) { + // Register user sync first + if (bidRequest && bidRequest.data) { + _registerUserSyncs(bidRequest.data); + } + const bidResponses = []; // If there are bids, look at the first bid of the first seatbid (see NOTE above for assumption about ttx) @@ -115,24 +127,11 @@ function interpretResponse(serverResponse) { return bidResponses; } -// Register one sync per bid since each ad unit may potenitally be linked to a uniqe guid -function getUserSyncs(syncOptions) { - let syncs = []; - const ttxBidRequests = utils.getBidderRequestAllAdUnits(BIDDER_CODE).bids; - - if (syncOptions.iframeEnabled) { - syncs = ttxBidRequests.map(_createSync); - } - - return syncs; -} - const spec = { code: BIDDER_CODE, isBidRequestValid, buildRequests, - interpretResponse, - getUserSyncs + interpretResponse } registerBidder(spec); diff --git a/modules/aardvarkBidAdapter.js b/modules/aardvarkBidAdapter.js deleted file mode 100644 index f52265e4d1d..00000000000 --- a/modules/aardvarkBidAdapter.js +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Adapter for requesting bids from RTK Aardvark - * To request an RTK Aardvark Header bidding account - * or for additional integration support please contact sales@rtk.io - */ - -var utils = require('src/utils.js'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var Adapter = require('src/adapter.js').default; -var constants = require('src/constants.json'); -var adaptermanager = require('src/adaptermanager'); - -const AARDVARK_CALLBACK_NAME = 'aardvarkResponse'; -const AARDVARK_REQUESTS_MAP = 'aardvarkRequests'; -const AARDVARK_BIDDER_CODE = 'aardvark'; -const DEFAULT_REFERRER = 'thor.rtk.io'; -const DEFAULT_ENDPOINT = 'thor.rtk.io'; - -var endpoint = DEFAULT_ENDPOINT; - -function requestBids(bidderCode, callbackName, bidReqs) { - var ref = utils.getTopWindowLocation(); - var ai = ''; - const scs = []; - const bidIds = []; - - ref = ref ? ref.host : DEFAULT_REFERRER; - - for (var i = 0, l = bidReqs.length, bid, _ai, _sc, _endpoint; i < l; i += 1) { - bid = bidReqs[i]; - _ai = utils.getBidIdParameter('ai', bid.params); - _sc = utils.getBidIdParameter('sc', bid.params); - if (!_ai || !_ai.length || !_sc || !_sc.length) { continue; } - - _endpoint = utils.getBidIdParameter('host', bid.params); - if (_endpoint) { endpoint = _endpoint; } - - if (!ai.length) { ai = _ai; } - if (_sc) { scs.push(_sc); } - - bidIds.push(_sc + '=' + bid.bidId); - - // Create the bidIdsMap for easier mapping back later - $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP][bidderCode][bid.bidId] = bid; - } - - if (!ai.length || !scs.length) { return utils.logWarn('Bad bid request params given for adapter $' + bidderCode + ' (' + AARDVARK_BIDDER_CODE + ')'); } - - adloader.loadScript([ - '//' + endpoint + '/', ai, '/', scs.join('_'), - '/aardvark/?jsonp=$$PREBID_GLOBAL$$.', callbackName, - '&rtkreferer=', ref, '&', bidIds.join('&') - ].join('')); -} - -function registerBidResponse(bidderCode, rawBidResponse) { - if (rawBidResponse.error) { return utils.logWarn('Aardvark bid received with an error, ignoring... [' + rawBidResponse.error + ']'); } - - if (!rawBidResponse.cid) { return utils.logWarn('Aardvark bid received without a callback id, ignoring...'); } - - var bidObj = $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP][bidderCode][rawBidResponse.cid]; - if (!bidObj) { return utils.logWarn('Aardvark request not found: ' + rawBidResponse.cid); } - - if (bidObj.params.sc !== rawBidResponse.id) { return utils.logWarn('Aardvark bid received with a non matching shortcode ' + rawBidResponse.id + ' instead of ' + bidObj.params.sc); } - - var bidResponse = bidfactory.createBid(constants.STATUS.GOOD, bidObj); - bidResponse.bidderCode = bidObj.bidder; - bidResponse.cpm = rawBidResponse.cpm; - bidResponse.ad = rawBidResponse.adm + utils.createTrackPixelHtml(decodeURIComponent(rawBidResponse.nurl)); - bidResponse.width = bidObj.sizes[0][0]; - bidResponse.height = bidObj.sizes[0][1]; - - bidmanager.addBidResponse(bidObj.placementCode, bidResponse); - $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP][bidderCode][rawBidResponse.cid].responded = true; -} - -function registerAardvarkCallback(bidderCode, callbackName) { - $$PREBID_GLOBAL$$[callbackName] = function(rtkResponseObj) { - rtkResponseObj.forEach(function(bidResponse) { - registerBidResponse(bidderCode, bidResponse); - }); - - for (var bidRequestId in $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP][bidderCode]) { - if ($$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP][bidderCode].hasOwnProperty(bidRequestId)) { - var bidRequest = $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP][bidderCode][bidRequestId]; - if (!bidRequest.responded) { - var bidResponse = bidfactory.createBid(constants.STATUS.NO_BID, bidRequest); - bidResponse.bidderCode = bidRequest.bidder; - bidmanager.addBidResponse(bidRequest.placementCode, bidResponse); - } - } - } - }; -} - -const AardvarkAdapter = function() { - var baseAdapter = new Adapter(AARDVARK_BIDDER_CODE); - - $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP] = $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP] || {}; - - baseAdapter.callBids = function (params) { - const bidderCode = baseAdapter.getBidderCode(); - var callbackName = AARDVARK_CALLBACK_NAME; - - if (bidderCode !== AARDVARK_BIDDER_CODE) { callbackName = [AARDVARK_CALLBACK_NAME, bidderCode].join('_'); } - - $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP][bidderCode] = {}; - - registerAardvarkCallback(bidderCode, callbackName); - - return requestBids(bidderCode, callbackName, params.bids || []); - }; - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode - }); -}; - -adaptermanager.registerBidAdapter(new AardvarkAdapter(), 'aardvark'); - -module.exports = AardvarkAdapter; diff --git a/modules/adbladeBidAdapter.js b/modules/adbladeBidAdapter.js deleted file mode 100644 index 50f50f515d9..00000000000 --- a/modules/adbladeBidAdapter.js +++ /dev/null @@ -1,135 +0,0 @@ -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 Adblade - * To request an Adblade Header partner account - * or for additional integration support please - * register at http://www.adblade.com. - */ -var AdbladeAdapter = function AdbladeAdapter() { - 'use strict'; - - const BIDDER_CODE = 'adblade'; - const BASE_URI = '//rtb.adblade.com/prebidjs/bid?'; - const DEFAULT_BID_FLOOR = 0.0000000001; - - function _callBids(params) { - var bids = params.bids || []; - var referrer = utils.getTopWindowUrl(); - var loc = utils.getTopWindowLocation(); - var domain = loc.hostname; - var partnerId = 0; - var bidRequests = {}; - - if (bids.length > 0) { - partnerId = '' + bids[0].params.partnerId; - } - - utils._each(bids, function(bid) { - // make sure the "sizes" are an array of arrays - if (!(bid.sizes[0] instanceof Array)) { - bid.sizes = [bid.sizes]; - } - utils._each(bid.sizes, function(size) { - let key = size[0] + 'x' + size[1]; - - bidRequests[key] = bidRequests[key] || { - 'site': { - 'id': partnerId, - 'page': referrer, - 'domain': domain, - 'publisher': { - 'id': partnerId, - 'name': referrer, - 'domain': domain - } - }, - 'id': params.requestId, - 'imp': [], - 'device': { - 'ua': window.navigator.userAgent, - }, - 'cur': ['USD'], - 'user': {} - }; - - bidRequests[key].imp.push({ - 'id': bid.bidId, - 'bidfloor': bid.params.bidFloor || DEFAULT_BID_FLOOR, - 'tag': bid.placementCode, - 'banner': { - 'w': size[0], - 'h': size[1], - }, - 'secure': 0 + (loc.protocol === 'https') - }); - }); - }); - - utils._each(bidRequests, function (bidRequest) { - adloader.loadScript( - utils.tryAppendQueryString( - utils.tryAppendQueryString( - BASE_URI, - 'callback', - '$$PREBID_GLOBAL$$.adbladeResponse' - ), - 'json', - JSON.stringify( - bidRequest - ) - ) - ); - }); - } - - $$PREBID_GLOBAL$$.adbladeResponse = function (response) { - var auctionIdRe = /\$(%7B|\{)AUCTION_ID(%7D|\})/gi; - var auctionPriceRe = /\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi; - var clickUrlRe = /\$(%7B|\{)CLICK_URL(%7D|\})/gi; - - if (typeof (response) === 'undefined' || !response.hasOwnProperty('seatbid') || utils.isEmpty(response.seatbid)) { - // handle empty bids - var bidsRequested = $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === BIDDER_CODE).bids; - if (bidsRequested.length > 0) { - let bid = bidfactory.createBid(2); - bid.bidderCode = BIDDER_CODE; - bidmanager.addBidResponse(bidsRequested[0].placementCode, bid); - } - - return; - } - - utils._each(response.seatbid, function(seatbid) { - utils._each(seatbid.bid, function(seatbidBid) { - var bidRequest = utils.getBidRequest(seatbidBid.impid); - var ad = seatbidBid.adm + utils.createTrackPixelHtml(seatbidBid.nurl); - - ad = ad.replace(auctionIdRe, seatbidBid.impid); - ad = ad.replace(clickUrlRe, ''); - ad = ad.replace(auctionPriceRe, seatbidBid.price); - - let bid = bidfactory.createBid(1); - - bid.bidderCode = BIDDER_CODE; - bid.cpm = seatbidBid.price; - bid.ad = ad; - bid.width = seatbidBid.w; - bid.height = seatbidBid.h; - bidmanager.addBidResponse(bidRequest.placementCode, bid); - }); - }); - }; - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new AdbladeAdapter(), 'adblade'); - -module.exports = AdbladeAdapter; diff --git a/modules/adbundBidAdapter.js b/modules/adbundBidAdapter.js deleted file mode 100644 index a40fc2b8057..00000000000 --- a/modules/adbundBidAdapter.js +++ /dev/null @@ -1,69 +0,0 @@ -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'); - -function AdBundAdapter() { - var timezone = (new Date()).getTimezoneOffset(); - var bidAPIs = [ - 'http://us-east-engine.adbund.xyz/prebid/ad/get', - 'http://us-west-engine.adbund.xyz/prebid/ad/get' - ]; - // Based on the time zone to select the interface to the server - var bidAPI = bidAPIs[timezone < 0 ? 0 : 1]; - - function _stringify(param) { - var result = []; - var key; - for (key in param) { - if (param.hasOwnProperty(key)) { - result.push(key + '=' + encodeURIComponent(param[key])); - } - } - return result.join('&'); - } - - function _createCallback(bid) { - return function (data) { - var response; - if (data && data.cpm) { - response = bidfactory.createBid(CONSTANTS.STATUS.GOOD); - response.bidderCode = 'adbund'; - Object.assign(response, data); - } else { - response = bidfactory.createBid(CONSTANTS.STATUS.NO_BID); - response.bidderCode = 'adbund'; - } - bidmanager.addBidResponse(bid.placementCode, response); - }; - } - - function _requestBids(bid) { - var info = { - referrer: utils.getTopWindowUrl(), - domain: utils.getTopWindowLocation().hostname, - ua: window.navigator.userAgent - }; - var param = Object.assign({}, bid.params, info); - param.sizes = JSON.stringify(param.sizes || bid.sizes); - param.callback = '$$PREBID_GLOBAL$$.adbundResponse'; - $$PREBID_GLOBAL$$.adbundResponse = _createCallback(bid); - adloader.loadScript(bidAPI + '?' + _stringify(param)); - } - - function _callBids(params) { - (params.bids || []).forEach(function (bid) { - _requestBids(bid); - }); - } - - return { - callBids: _callBids - }; -} - -adaptermanager.registerBidAdapter(new AdBundAdapter(), 'adbund'); - -module.exports = AdBundAdapter; diff --git a/modules/adequantBidAdapter.js b/modules/adequantBidAdapter.js deleted file mode 100644 index a12369d0a59..00000000000 --- a/modules/adequantBidAdapter.js +++ /dev/null @@ -1,80 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var utils = require('src/utils.js'); -var CONSTANTS = require('src/constants.json'); -var adaptermanager = require('src/adaptermanager'); - -function AdequantAdapter() { - var req_url_base = 'https://rex.adequant.com/rex/c2s_prebid?'; - - function _callBids(params) { - var req_url = []; - var publisher_id = null; - var sizes = []; - var cats = null; - var replies = []; - var placements = {}; - - var bids = params.bids || []; - for (var i = 0; i < bids.length; i++) { - var bid_request = bids[i]; - var br_params = bid_request.params || {}; - placements[bid_request.placementCode] = true; - - publisher_id = br_params.publisher_id.toString() || publisher_id; - var bidfloor = br_params.bidfloor || 0.01; - cats = br_params.cats || cats; - if (typeof (cats) === 'string') { cats = cats.split(' '); } - var br_sizes = utils.parseSizesInput(bid_request.sizes); - for (var j = 0; j < br_sizes.length; j++) { - sizes.push(br_sizes[j] + '_' + bidfloor); - replies.push(bid_request.placementCode); - } - } - // send out 1 bid request for all bids - if (publisher_id) { req_url.push('a=' + publisher_id); } - if (cats) { req_url.push('c=' + cats.join('+')); } - if (sizes) { req_url.push('s=' + sizes.join('+')); } - - adloader.loadScript(req_url_base + req_url.join('&'), function() { process_bids(replies, placements); }); - } - - function process_bids(replies, placements) { - var placement_code; - var bid; - const adequant_creatives = window.adequant_creatives; - if (adequant_creatives && adequant_creatives.seatbid) { - for (var i = 0; i < adequant_creatives.seatbid.length; i++) { - var bid_response = adequant_creatives.seatbid[i].bid[0]; - placement_code = replies[parseInt(bid_response.impid, 10) - 1]; - if (!placement_code || !placements[placement_code]) { continue; } - - bid = bidfactory.createBid(CONSTANTS.STATUS.GOOD); - bid.bidderCode = 'adequant'; - bid.cpm = bid_response.price; - bid.ad = bid_response.adm; - bid.width = bid_response.w; - bid.height = bid_response.h; - bidmanager.addBidResponse(placement_code, bid); - placements[placement_code] = false; - } - } - for (placement_code in placements) { - if (placements[placement_code]) { - bid = bidfactory.createBid(CONSTANTS.STATUS.NO_BID); - bid.bidderCode = 'adequant'; - bidmanager.addBidResponse(placement_code, bid); - utils.logMessage('No bid response from Adequant for placement code ' + placement_code); - } - } - } - - return { - callBids: _callBids - }; -} - -adaptermanager.registerBidAdapter(new AdequantAdapter(), 'adequant'); - -module.exports = AdequantAdapter; diff --git a/modules/adformBidAdapter.js b/modules/adformBidAdapter.js deleted file mode 100644 index 3a1d455b7e2..00000000000 --- a/modules/adformBidAdapter.js +++ /dev/null @@ -1,172 +0,0 @@ -var utils = require('src/utils'); -var adloader = require('src/adloader'); -var bidmanager = require('src/bidmanager'); -var bidfactory = require('src/bidfactory'); -var STATUSCODES = require('src/constants.json').STATUS; -var adaptermanager = require('src/adaptermanager'); -var Adapter = require('src/adapter').default; - -const ADFORM_BIDDER_CODE = 'adform'; - -function AdformAdapter() { - let baseAdapter = new Adapter(ADFORM_BIDDER_CODE); - - function _callBids(params) { - var bid, _value, _key, i, j, k, l, reqParams; - 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 ] ]; - - for (i = 0, l = bids.length; i < l; i++) { - bid = bids[i]; - - for (j = 0, k = globalParams.length; j < k; j++) { - _key = globalParams[j][0]; - _value = bid[_key] || bid.params[_key]; - if (_value) { - bid[_key] = bid.params[_key] = null; - globalParams[j][1] = _value; - } - } - - reqParams = bid.params; - reqParams.transactionId = bid.transactionId; - request.push(formRequestUrl(reqParams)); - } - - request.unshift('//' + globalParams[0][1] + '/adx/?rp=4'); - - request.push('auctionId=' + params.requestId); - for (i = 1, l = globalParams.length; i < l; i++) { - _key = globalParams[i][0]; - _value = globalParams[i][1]; - if (_value) { - request.push(globalParams[i][0] + '=' + encodeURIComponent(_value)); - } - } - - $$PREBID_GLOBAL$$[callbackName] = handleCallback(bids); - - adloader.loadScript(request.join('&')); - }; - - function formRequestUrl(reqData) { - var key; - var url = []; - - for (key in reqData) { - if (reqData.hasOwnProperty(key) && reqData[key]) { url.push(key, '=', reqData[key], '&'); } - } - - return encode64(url.join('').slice(0, -1)); - } - - function handleCallback(bids) { - return function handleResponse(adItems) { - var bidObject; - var bidder = baseAdapter.getBidderCode(); - var adItem; - var bid; - for (var i = 0, l = adItems.length; i < l; i++) { - adItem = adItems[i]; - bid = bids[i]; - if (adItem && adItem.response === 'banner' && - verifySize(adItem, bid.sizes)) { - bidObject = bidfactory.createBid(STATUSCODES.GOOD, bid); - bidObject.bidderCode = bidder; - bidObject.cpm = adItem.win_bid; - bidObject.cur = adItem.win_cur; - bidObject.ad = adItem.banner; - bidObject.width = adItem.width; - bidObject.height = adItem.height; - bidObject.dealId = adItem.deal_id; - bidObject.transactionId = bid.transactionId; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } else { - bidObject = bidfactory.createBid(STATUSCODES.NO_BID, bid); - bidObject.bidderCode = bidder; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } - } - }; - - function verifySize(adItem, validSizes) { - for (var j = 0, k = validSizes.length; j < k; j++) { - if (adItem.width === validSizes[j][0] && - adItem.height === validSizes[j][1]) { - return true; - } - } - - return false; - } - } - - function encode64(input) { - var out = []; - var chr1; - var chr2; - var chr3; - var enc1; - var enc2; - var enc3; - var enc4; - var i = 0; - var _keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_='; - - input = utf8_encode(input); - - while (i < input.length) { - chr1 = input.charCodeAt(i++); - chr2 = input.charCodeAt(i++); - chr3 = input.charCodeAt(i++); - - enc1 = chr1 >> 2; - enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); - enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); - enc4 = chr3 & 63; - - if (isNaN(chr2)) { - enc3 = enc4 = 64; - } else if (isNaN(chr3)) { - enc4 = 64; - } - - out.push(_keyStr.charAt(enc1), _keyStr.charAt(enc2)); - if (enc3 !== 64) { out.push(_keyStr.charAt(enc3)); } - if (enc4 !== 64) { out.push(_keyStr.charAt(enc4)); } - } - - return out.join(''); - } - - function utf8_encode(string) { - string = string.replace(/\r\n/g, '\n'); - var utftext = ''; - - for (var n = 0; n < string.length; n++) { - var c = string.charCodeAt(n); - - if (c < 128) { - utftext += String.fromCharCode(c); - } else if ((c > 127) && (c < 2048)) { - utftext += String.fromCharCode((c >> 6) | 192); - utftext += String.fromCharCode((c & 63) | 128); - } else { - utftext += String.fromCharCode((c >> 12) | 224); - utftext += String.fromCharCode(((c >> 6) & 63) | 128); - utftext += String.fromCharCode((c & 63) | 128); - } - } - - return utftext; - } - - return Object.assign(this, baseAdapter, { - callBids: _callBids - }); -} - -adaptermanager.registerBidAdapter(new AdformAdapter(), ADFORM_BIDDER_CODE); -module.exports = AdformAdapter; diff --git a/modules/adkernelAdnBidAdapter.js b/modules/adkernelAdnBidAdapter.js index b1c8bbf398b..28fb564320d 100644 --- a/modules/adkernelAdnBidAdapter.js +++ b/modules/adkernelAdnBidAdapter.js @@ -1,6 +1,7 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; import { BANNER, VIDEO } from 'src/mediaTypes'; +import includes from 'core-js/library/fn/array/includes'; const DEFAULT_ADKERNEL_DSP_DOMAIN = 'tag.adkernel.com'; const VIDEO_TARGETING = ['mimes', 'protocols', 'api']; @@ -28,7 +29,7 @@ function buildImp(bidRequest) { }; if (bidRequest.params.video) { Object.keys(bidRequest.params.video) - .filter(param => VIDEO_TARGETING.includes(param)) + .filter(param => includes(VIDEO_TARGETING, param)) .forEach(param => imp.video[param] = bidRequest.params.video[param]); } } else { diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index 095a6cec4b9..016cc5794fb 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -1,6 +1,8 @@ import * as utils from 'src/utils'; import { BANNER, VIDEO } from 'src/mediaTypes'; import {registerBidder} from 'src/adapters/bidderFactory'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; const VIDEO_TARGETING = ['mimes', 'minduration', 'maxduration', 'protocols', 'startdelay', 'linearity', 'boxingallowed', 'playbackmethod', 'delivery', @@ -63,7 +65,7 @@ export const spec = { .reduce((a, b) => a.concat(b), []); return rtbBids.map(rtbBid => { - let imp = rtbImps.find(imp => imp.id === rtbBid.impid); + let imp = find(rtbImps, imp => imp.id === rtbBid.impid); let prBid = { requestId: rtbBid.impid, cpm: rtbBid.price, @@ -119,7 +121,7 @@ function buildImp(bid) { imp.video = {w: size[0], h: size[1]}; if (bid.params.video) { Object.keys(bid.params.video) - .filter(param => VIDEO_TARGETING.includes(param)) + .filter(param => includes(VIDEO_TARGETING, param)) .forEach(param => imp.video[param] = bid.params.video[param]); } } else { diff --git a/modules/admediaBidAdapter.js b/modules/admediaBidAdapter.js deleted file mode 100644 index 4382870eef3..00000000000 --- a/modules/admediaBidAdapter.js +++ /dev/null @@ -1,107 +0,0 @@ -import { getBidRequest } from 'src/utils'; -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var utils = require('src/utils.js'); -var CONSTANTS = require('src/constants.json'); -var adaptermanager = require('src/adaptermanager'); - -/** - * Adapter for requesting bids from AdMedia. - * - */ -var AdmediaAdapter = function AdmediaAdapter() { - function _callBids(params) { - var bids; - const bidderUrl = (window.location.protocol) + '//b.admedia.com/banner/prebid/bidder/?'; - bids = params.bids || []; - for (var i = 0; i < bids.length; i++) { - var request_obj = {}; - var bid = bids[i]; - - if (bid.params.aid) { - request_obj.aid = bid.params.aid; - } else { - utils.logError('required param aid is missing', 'admedia'); - continue; - } - - // optional page_url macro - if (bid.params.page_url) { - request_obj.page_url = bid.params.page_url; - } - - // if set, return a test ad for all aids - if (bid.params.test_ad === 1) { - request_obj.test_ad = 1; - } - - var parsedSizes = utils.parseSizesInput(bid.sizes); - var parsedSizesLength = parsedSizes.length; - if (parsedSizesLength > 0) { - // first value should be "size" - request_obj.size = parsedSizes[0]; - if (parsedSizesLength > 1) { - // any subsequent values should be "promo_sizes" - var promo_sizes = []; - for (var j = 1; j < parsedSizesLength; j++) { - promo_sizes.push(parsedSizes[j]); - } - - request_obj.promo_sizes = promo_sizes.join(','); - } - } - - // detect urls - request_obj.siteDomain = window.location.host; - request_obj.sitePage = window.location.href; - request_obj.siteRef = document.referrer; - request_obj.topUrl = utils.getTopWindowUrl(); - - request_obj.callback = '$$PREBID_GLOBAL$$'; - request_obj.callbackId = bid.bidId; - - var endpoint = bidderUrl + utils.parseQueryStringParameters(request_obj); - - // utils.logMessage('Admedia request built: ' + endpoint); - - adloader.loadScript(endpoint); - } - } - - // expose the callback to global object - $$PREBID_GLOBAL$$.admediaHandler = function(response) { - var bidObject = {}; - var callback_id = response.callback_id; - var placementCode = ''; - var bidObj = getBidRequest(callback_id); - if (bidObj) { - placementCode = bidObj.placementCode; - } - - if (bidObj && response.cpm > 0 && !!response.ad) { - bidObject = bidfactory.createBid(CONSTANTS.STATUS.GOOD); - bidObject.bidderCode = bidObj.bidder; - bidObject.cpm = parseFloat(response.cpm); - bidObject.ad = response.ad; - bidObject.width = response.width; - bidObject.height = response.height; - } else { - bidObject = bidfactory.createBid(CONSTANTS.STATUS.NO_BID); - bidObject.bidderCode = bidObj.bidder; - utils.logMessage('No prebid response from Admedia for placement code ' + placementCode); - } - - bidmanager.addBidResponse(placementCode, bidObject); - }; - - // Export the callBids function, so that prebid.js can execute this function - // when the page asks to send out bid requests. - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new AdmediaAdapter(), 'admedia'); - -module.exports = AdmediaAdapter; diff --git a/modules/admixerBidAdapter.js b/modules/admixerBidAdapter.js deleted file mode 100644 index f7890e81143..00000000000 --- a/modules/admixerBidAdapter.js +++ /dev/null @@ -1,87 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var Ajax = require('src/ajax'); -var utils = require('src/utils.js'); -var adaptermanager = require('src/adaptermanager'); - -/** - * Adapter for requesting bids from Admixer. - * - * @returns {{callBids: _callBids,responseCallback: _responseCallback}} - */ -var AdmixerAdapter = function AdmixerAdapter() { - var invUrl = '//inv-nets.admixer.net/prebid.aspx'; - var invVastUrl = '//inv-nets.admixer.net/videoprebid.aspx'; - - function _callBids(data) { - var bids = data.bids || []; - for (var i = 0, ln = bids.length; i < ln; i++) { - var bid = bids[i]; - var params = { - 'sizes': utils.parseSizesInput(bid.sizes).join('-'), - 'zone': bid.params && bid.params.zone, - 'callback_uid': bid.placementCode - }; - if (params.zone) { - if (bid.mediaType === 'video') { - var videoParams = {}; - if (typeof bid.video === 'object') { - Object.assign(videoParams, bid.video); - } - Object.assign(videoParams, params); - _requestBid(invVastUrl, params); - } else { - _requestBid(invUrl, params); - } - } else { - var bidObject = bidfactory.createBid(2); - bidObject.bidderCode = 'admixer'; - bidmanager.addBidResponse(params.callback_uid, bidObject); - } - } - } - - function _requestBid(url, params) { - Ajax.ajax(url, _responseCallback, params, {method: 'GET', withCredentials: true}); - } - - function _responseCallback(adUnit) { - try { - adUnit = JSON.parse(adUnit); - } catch (_error) { - adUnit = {result: {cpm: 0}}; - utils.logError(_error); - } - var adUnitCode = adUnit.callback_uid; - var bid = adUnit.result; - var bidObject; - if (bid.cpm > 0) { - bidObject = bidfactory.createBid(1); - bidObject.bidderCode = 'admixer'; - bidObject.cpm = bid.cpm; - if (bid.vastUrl) { - bidObject.mediaType = 'video'; - bidObject.vastUrl = bid.vastUrl; - } else { - bidObject.ad = bid.ad; - } - bidObject.width = bid.width; - bidObject.height = bid.height; - } else { - bidObject = bidfactory.createBid(2); - bidObject.bidderCode = 'admixer'; - } - bidmanager.addBidResponse(adUnitCode, bidObject); - } - - return { - callBids: _callBids, - responseCallback: _responseCallback - }; -}; - -adaptermanager.registerBidAdapter(new AdmixerAdapter(), 'admixer', { - supportedMediaTypes: ['video'] -}); - -module.exports = AdmixerAdapter; diff --git a/modules/adomikAnalyticsAdapter.js b/modules/adomikAnalyticsAdapter.js index c9bd7990ec8..929a4d5deae 100644 --- a/modules/adomikAnalyticsAdapter.js +++ b/modules/adomikAnalyticsAdapter.js @@ -1,7 +1,8 @@ import adapter from 'src/AnalyticsAdapter'; import CONSTANTS from 'src/constants.json'; import adaptermanager from 'src/adaptermanager'; -// import utils from 'src/utils'; +import find from 'core-js/library/fn/array/find'; +import findIndex from 'core-js/library/fn/array/find-index'; // Events used in adomik analytics adapter const auctionInit = CONSTANTS.EVENTS.AUCTION_INIT; @@ -139,7 +140,7 @@ adomikAdapter.buildBidResponse = function (bid) { adomikAdapter.sizeUtils = { sizeAlreadyExists: (sizes, typedEventSize) => { - return sizes.find((size) => size.height === typedEventSize.height && size.width === typedEventSize.width); + return find(sizes, (size) => size.height === typedEventSize.height && size.width === typedEventSize.width); }, formatSize: (typedEventSize) => { return { @@ -160,7 +161,7 @@ adomikAdapter.buildTypedEvents = function () { const groupedTypedEvents = []; adomikAdapter.bucketEvents.forEach(function(typedEvent, i) { const [placementCode, type] = [typedEvent.event.placementCode, typedEvent.type]; - let existTypedEvent = groupedTypedEvents.findIndex((groupedTypedEvent) => groupedTypedEvent.placementCode === placementCode); + let existTypedEvent = findIndex(groupedTypedEvents, (groupedTypedEvent) => groupedTypedEvent.placementCode === placementCode); if (existTypedEvent === -1) { groupedTypedEvents.push({ diff --git a/modules/adsupplyBidAdapter.js b/modules/adsupplyBidAdapter.js deleted file mode 100644 index 041437cce98..00000000000 --- a/modules/adsupplyBidAdapter.js +++ /dev/null @@ -1,90 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader'); -var utils = require('src/utils'); -var adaptermanager = require('src/adaptermanager'); - -const ADSUPPLY_CODE = 'adsupply'; - -var AdSupplyAdapter = function AdSupplyAdapter() { - function _validateParams(params) { - if (!params || !params.siteId || !params.zoneId || !params.endpointUrl || !params.clientId) { - return false; - } - - if (typeof params.zoneId !== 'number' || params.zoneId <= 0) { - return false; - } - - return true; - } - - function _getRequestUrl(bid) { - var referrerUrl = encodeURIComponent(window.document.referrer); - var rand = encodeURIComponent(Math.floor(Math.random() * 100000 + 1)); - var time = encodeURIComponent(new Date().getTimezoneOffset()); - return '//' + bid.params.endpointUrl + '/banner.engine?id=' + bid.params.siteId + '&z=' + bid.params.zoneId + '&rand=' + rand + '&ver=async' + '&time=' + time + '&referrerurl=' + referrerUrl + '&abr=false' + '&hbt=1&cid=' + encodeURIComponent(bid.params.clientId); - } - - $$PREBID_GLOBAL$$.adSupplyResponseHandler = function (bidId) { - if (!bidId) return; - - var bidRequest = utils.getBidRequest(bidId); - - if (!bidRequest || !bidRequest.params) return; - - var clientId = bidRequest.params.clientId; - var zoneProp = 'b' + bidRequest.params.zoneId; - - if (!window[clientId] || !window[clientId][zoneProp]) return; - - var media = window[clientId][zoneProp].Media; - - if (!media) return; - - if (!media.Url || !media.Ecpm || typeof media.Ecpm !== 'number' || media.Ecpm <= 0) { - var noFillbject = bidfactory.createBid(2, bidRequest); - noFillbject.bidderCode = ADSUPPLY_CODE; - bidmanager.addBidResponse(bidRequest.placementCode, noFillbject); - } else { - var bidObject = bidfactory.createBid(1, bidRequest); - bidObject.bidderCode = ADSUPPLY_CODE; - bidObject.cpm = media.Ecpm; - bidObject.ad = ''; - bidObject.width = media.Width; - bidObject.height = media.Height; - bidmanager.addBidResponse(bidRequest.placementCode, bidObject); - } - }; - - function _makeCallBackHandler(bidId) { - return function () { - $$PREBID_GLOBAL$$.adSupplyResponseHandler(bidId); - }; - } - - function _callBids(params) { - var bids = params.bids || []; - for (var i = 0; i < bids.length; i++) { - var bid = bids[i]; - if (!_validateParams(bid.params)) continue; - - var clientId = bid.params.clientId; - var zoneProp = 'b' + bid.params.zoneId; - window[clientId] = window[clientId] || {}; - window.window[clientId][zoneProp] = window.window[clientId][zoneProp] || {}; - window.window[clientId][zoneProp].Media = {}; - - var requestUrl = _getRequestUrl(bid); - adloader.loadScript(requestUrl, _makeCallBackHandler(bid.bidId)); - } - } - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new AdSupplyAdapter(), 'adsupply'); - -module.exports = AdSupplyAdapter; diff --git a/modules/adxcgAnalyticsAdapter.js b/modules/adxcgAnalyticsAdapter.js index 5d2040c8e08..8de0a346ed6 100644 --- a/modules/adxcgAnalyticsAdapter.js +++ b/modules/adxcgAnalyticsAdapter.js @@ -1,12 +1,13 @@ import {ajax} from 'src/ajax'; import adapter from 'src/AnalyticsAdapter'; import adaptermanager from 'src/adaptermanager'; +import CONSTANTS from 'src/constants.json'; import * as url from 'src/url'; import * as utils from 'src/utils'; const emptyUrl = ''; const analyticsType = 'endpoint'; -const adxcgAnalyticsVersion = 'v1.04'; +const adxcgAnalyticsVersion = 'v1.05'; let initOptions; let auctionTimestamp; @@ -22,23 +23,23 @@ var adxcgAnalyticsAdapter = Object.assign(adapter( }), { track({eventType, args}) { if (typeof args !== 'undefined') { - if (eventType === 'bidTimeout') { - events.bidTimeout = args; - } else if (eventType === 'auctionInit') { + if (eventType === CONSTANTS.EVENTS.BID_TIMEOUT) { + events.bidTimeout = args.map(item => item.bidder).filter(utils.uniques); + } else if (eventType === CONSTANTS.EVENTS.AUCTION_INIT) { events.auctionInit = args; auctionTimestamp = args.timestamp; - } else if (eventType === 'bidRequested') { + } else if (eventType === CONSTANTS.EVENTS.BID_REQUESTED) { events.bidRequests.push(args); - } else if (eventType === 'bidResponse') { + } else if (eventType === CONSTANTS.EVENTS.BID_RESPONSE) { events.bidResponses.push(mapBidResponse(args)); - } else if (eventType === 'bidWon') { + } else if (eventType === CONSTANTS.EVENTS.BID_WON) { send({ bidWon: mapBidResponse(args) }); } } - if (eventType === 'auctionEnd') { + if (eventType === CONSTANTS.EVENTS.AUCTION_END) { send(events); } } diff --git a/modules/adyoulikeBidAdapter.js b/modules/adyoulikeBidAdapter.js deleted file mode 100644 index 5192270a94e..00000000000 --- a/modules/adyoulikeBidAdapter.js +++ /dev/null @@ -1,202 +0,0 @@ -import Adapter from 'src/adapter'; -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import * as utils from 'src/utils'; -import { format } from 'src/url'; -import { ajax } from 'src/ajax'; -import { STATUS } from 'src/constants'; -import adaptermanager from 'src/adaptermanager'; - -var AdyoulikeAdapter = function AdyoulikeAdapter() { - const _VERSION = '0.2'; - - const baseAdapter = new Adapter('adyoulike'); - - baseAdapter.callBids = function (bidRequest) { - const bidRequests = {}; - const bids = bidRequest.bids || []; - - const validBids = bids.filter(valid); - validBids.forEach(bid => { bidRequests[bid.params.placement] = bid; }); - - const placements = validBids.map(bid => bid.params.placement); - if (!utils.isEmpty(placements)) { - const body = createBody(bidRequests, placements); - const endpoint = createEndpoint(); - ajax(endpoint, - (response) => { - handleResponse(bidRequests, response); - }, body, { - contentType: 'text/json', - withCredentials: true - }); - } - }; - - /* Create endpoint url */ - function createEndpoint() { - return format({ - protocol: (document.location.protocol === 'https:') ? 'https' : 'http', - host: 'hb-api.omnitagjs.com', - pathname: '/hb-api/prebid', - search: createEndpointQS() - }); - } - - /* Create endpoint query string */ - function createEndpointQS() { - const qs = {}; - - const ref = getReferrerUrl(); - if (ref) { - qs.RefererUrl = encodeURIComponent(ref); - } - - const can = getCanonicalUrl(); - if (can) { - qs.CanonicalUrl = encodeURIComponent(can); - } - - return qs; - } - - /* Create request body */ - function createBody(bidRequests, placements) { - const body = { - Version: _VERSION, - Placements: placements, - TransactionIds: {} - }; - - // performance isn't supported by mobile safari iOS7. window.performance works, but - // evaluates to true on a unit test which expects false. - // - // try/catch was added to un-block the Prebid 0.25 release, but the adyoulike adapter - // maintainers should revisit this and see if it's really what they want. - try { - if (performance && performance.navigation) { - body.PageRefreshed = performance.navigation.type === performance.navigation.TYPE_RELOAD; - } - } catch (e) { - body.PageRefreshed = false; - } - - placements.forEach(placement => { body.TransactionIds[placement] = bidRequests[placement].transactionId; }); - - return JSON.stringify(body); - } - - /* Response handler */ - function handleResponse(bidRequests, response) { - let responses = []; - try { - responses = JSON.parse(response); - } catch (error) { utils.logError(error); } - - const bidResponses = {}; - responses.forEach(response => { - bidResponses[response.Placement] = response; - }); - - Object.keys(bidRequests).forEach(placement => { - addResponse(placement, bidRequests[placement], bidResponses[placement]); - }); - } - - /* Check that a bid has required parameters */ - function valid(bid) { - const sizes = getSize(bid.sizes); - if (!bid.params.placement || !sizes.width || !sizes.height) { - return false; - } - return true; - } - - /* Get current page referrer url */ - function getReferrerUrl() { - let referer = ''; - if (window.self !== window.top) { - try { - referer = window.top.document.referrer; - } catch (e) { } - } else { - referer = document.referrer; - } - return referer; - } - - /* Get current page canonical url */ - function getCanonicalUrl() { - let link; - if (window.self !== window.top) { - try { - link = window.top.document.head.querySelector('link[rel="canonical"][href]'); - } catch (e) { } - } else { - link = document.head.querySelector('link[rel="canonical"][href]'); - } - - if (link) { - return link.href; - } - return ''; - } - - /* Get parsed size from request size */ - function getSize(requestSizes) { - const parsed = {}; - const size = utils.parseSizesInput(requestSizes)[0]; - - if (typeof size !== 'string') { - return parsed; - } - - const parsedSize = size.toUpperCase().split('X'); - const width = parseInt(parsedSize[0], 10); - if (width) { - parsed.width = width; - } - - const height = parseInt(parsedSize[1], 10); - if (height) { - parsed.height = height; - } - - return parsed; - } - - /* Create bid from response */ - function createBid(placementId, bidRequest, response) { - let bid; - if (!response || !response.Banner) { - bid = bidfactory.createBid(STATUS.NO_BID, bidRequest); - } else { - bid = bidfactory.createBid(STATUS.GOOD, bidRequest); - const size = getSize(bidRequest.sizes); - bid.width = size.width; - bid.height = size.height; - bid.cpm = response.Price; - bid.ad = response.Banner; - } - - bid.bidderCode = baseAdapter.getBidderCode(); - - return bid; - } - - /* Add response to bidmanager */ - function addResponse(placementId, bidRequest, response) { - const bid = createBid(placementId, bidRequest, response); - const placement = bidRequest.placementCode; - bidmanager.addBidResponse(placement, bid); - } - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - }); -}; - -adaptermanager.registerBidAdapter(new AdyoulikeAdapter(), 'adyoulike'); - -module.exports = AdyoulikeAdapter; diff --git a/modules/aerservBidAdapter.js b/modules/aerservBidAdapter.js deleted file mode 100644 index 01966351a82..00000000000 --- a/modules/aerservBidAdapter.js +++ /dev/null @@ -1,116 +0,0 @@ -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import * as utils from 'src/utils'; -import {ajax} from 'src/ajax'; -import {STATUS} from 'src/constants'; -import adaptermanager from 'src/adaptermanager'; - -const BIDDER_CODE = 'aerserv'; - -const AerServAdapter = function AerServAdapter() { - const ENVIRONMENTS = { - local: '127.0.0.1:8080', - dev: 'dev-ads.aerserv.com', - stage: 'staging-ads.aerserv.com', - prod: 'ads.aerserv.com' - }; - - const BANNER_PATH = '/as/json/pbjs/v1?'; - const VIDEO_PATH = '/as/json/pbjsvast/v1?'; - const REQUIRED_PARAMS = ['plc']; - - function _isResponseValid(bidRequest, response) { - return ((bidRequest.mediaType === 'video' && response.vastUrl) || (bidRequest.mediaType !== 'video' && response.adm)) && - response.cpm && response.cpm > 0; - } - - function _createBid(bidRequest, response) { - if (_isResponseValid(bidRequest, response)) { - let bid = bidfactory.createBid(1, bidRequest); - bid.bidderCode = BIDDER_CODE; - bid.cpm = response.cpm; - bid.width = response.w; - bid.height = response.h; - if (bidRequest.mediaType === 'video') { - bid.vastUrl = response.vastUrl; - bid.mediaType = 'video'; - } else { - bid.ad = response.adm; - } - bidmanager.addBidResponse(bidRequest.placementCode, bid); - } else { - bidmanager.addBidResponse(bidRequest.placementCode, bidfactory.createBid(STATUS.NO_BID, bidRequest)); - } - } - - function _getFirstSize(sizes) { - let sizeObj = {}; - if (utils.isArray(sizes) && sizes.length > 0 && utils.isArray(sizes[0]) && sizes[0].length === 2) { - sizeObj['vpw'] = sizes[0][0]; - sizeObj['vph'] = sizes[0][1]; - } - return sizeObj; - } - - function _buildQueryParameters(bid, requestParams) { - Object.keys(bid.params).filter(param => param !== 'video') - .forEach(param => requestParams[param] = bid.params[param]); - - if (bid.mediaType === 'video') { - let videoDimensions = _getFirstSize(bid.sizes); - Object.keys(videoDimensions).forEach(param => requestParams[param] = videoDimensions[param]); - Object.keys(bid.params.video || {}).forEach(param => requestParams[param] = bid.params.video[param]); - } - - return utils.parseQueryStringParameters(requestParams); - } - - function _handleResponse(bidRequest) { - return response => { - if (!response && response.length <= 0) { - bidmanager.addBidResponse(bidRequest.placementCode, bidfactory.createBid(STATUS.NO_BID, bidRequest)); - utils.logError('Empty response'); - return; - } - - try { - response = JSON.parse(response); - } catch (e) { - bidmanager.addBidResponse(bidRequest.placementCode, bidfactory.createBid(STATUS.NO_BID, bidRequest)); - utils.logError('Invalid JSON in response'); - return; - } - - _createBid(bidRequest, response); - }; - } - - function _callBids(bidRequests) { - let currentUrl = (window.parent !== window) ? document.referrer : window.location.href; - currentUrl = currentUrl && encodeURIComponent(currentUrl); - - let bids = bidRequests.bids || []; - bids.forEach(bid => { - if (utils.hasValidBidRequest(bid.params, REQUIRED_PARAMS, BIDDER_CODE)) { - let env = ENVIRONMENTS[bid.params['env']] || ENVIRONMENTS['prod']; - let requestPath = bid.mediaType === 'video' ? VIDEO_PATH : BANNER_PATH; - let pageParameters = {url: currentUrl}; - let parameterStr = _buildQueryParameters(bid, pageParameters); - - let url = `//${env}${requestPath}${parameterStr}`; - utils.logMessage('sending request to: ' + url); - ajax(url, _handleResponse(bid), null, {withCredentials: true}); - } else { - bidmanager.addBidResponse(bid.placementCode, bidfactory.createBid(STATUS.NO_BID, bid)); - } - }); - } - - return { - callBids: _callBids - } -}; - -adaptermanager.registerBidAdapter(new AerServAdapter(), BIDDER_CODE, {supportedMediaTypes: ['video']}); - -module.exports = AerServAdapter; diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js index c76bd1ccfd6..71b1e4f7902 100644 --- a/modules/aolBidAdapter.js +++ b/modules/aolBidAdapter.js @@ -61,12 +61,18 @@ let showCpmAdjustmentWarning = (function () { }; })(); +function isInteger(value) { + return typeof value === 'number' && + isFinite(value) && + Math.floor(value) === value; +} + 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]; + let value = isInteger(key) ? values[key] : dict[key]; result.push(value, strings[i + 1]); }); return result.join(''); diff --git a/modules/appnexusAstBidAdapter.js b/modules/appnexusAstBidAdapter.js deleted file mode 100644 index 94a028f9868..00000000000 --- a/modules/appnexusAstBidAdapter.js +++ /dev/null @@ -1,430 +0,0 @@ -import { Renderer } from 'src/Renderer'; -import * as utils from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes'; - -const BIDDER_CODE = 'appnexusAst'; -const URL = '//ib.adnxs.com/ut/v3/prebid'; -const VIDEO_TARGETING = ['id', 'mimes', 'minduration', 'maxduration', - 'startdelay', 'skippable', 'playback_method', 'frameworks']; -const USER_PARAMS = ['age', 'external_uid', 'segments', 'gender', 'dnt', 'language']; -const NATIVE_MAPPING = { - body: 'description', - cta: 'ctatext', - image: { - serverName: 'main_image', - requiredParams: { required: true }, - minimumParams: { sizes: [{}] }, - }, - icon: { - serverName: 'icon', - requiredParams: { required: true }, - minimumParams: { sizes: [{}] }, - }, - sponsoredBy: 'sponsored_by', -}; -const SOURCE = 'pbjs'; - -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER, VIDEO, NATIVE], - - /** - * Determines whether or not the given bid request is valid. - * - * @param {object} bid The bid to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ - isBidRequestValid: function(bid) { - return !!(bid.params.placementId || (bid.params.member && bid.params.invCode)); - }, - - /** - * Make a server request from the list of BidRequests. - * - * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. - * @return ServerRequest Info describing the request to the server. - */ - buildRequests: function(bidRequests, bidderRequest) { - const tags = bidRequests.map(bidToTag); - const userObjBid = bidRequests.find(hasUserInfo); - let userObj; - if (userObjBid) { - userObj = {}; - Object.keys(userObjBid.params.user) - .filter(param => USER_PARAMS.includes(param)) - .forEach(param => userObj[param] = userObjBid.params.user[param]); - } - - const memberIdBid = bidRequests.find(hasMemberId); - const member = memberIdBid ? parseInt(memberIdBid.params.member, 10) : 0; - - const payload = { - tags: [...tags], - user: userObj, - sdk: { - source: SOURCE, - version: '$prebid.version$' - } - }; - if (member > 0) { - payload.member_id = member; - } - const payloadString = JSON.stringify(payload); - return { - method: 'POST', - url: URL, - data: payloadString, - bidderRequest - }; - }, - - /** - * Unpack the response from the server into a list of bids. - * - * @param {*} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ - interpretResponse: function(serverResponse, {bidderRequest}) { - serverResponse = serverResponse.body; - const bids = []; - if (!serverResponse || serverResponse.error) { - let errorMessage = `in response for ${bidderRequest.bidderCode} adapter`; - if (serverResponse && serverResponse.error) { errorMessage += `: ${serverResponse.error}`; } - utils.logError(errorMessage); - return bids; - } - - if (serverResponse.tags) { - serverResponse.tags.forEach(serverBid => { - const rtbBid = getRtbBid(serverBid); - if (rtbBid) { - if (rtbBid.cpm !== 0 && this.supportedMediaTypes.includes(rtbBid.ad_type)) { - const bid = newBid(serverBid, rtbBid); - bid.mediaType = parseMediaType(rtbBid); - bids.push(bid); - } - } - }); - } - return bids; - }, - - getUserSyncs: function(syncOptions) { - if (syncOptions.iframeEnabled) { - return [{ - type: 'iframe', - url: '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html' - }]; - } - } -} - -function newRenderer(adUnitCode, rtbBid) { - const renderer = Renderer.install({ - id: rtbBid.renderer_id, - url: rtbBid.renderer_url, - config: { adText: `AppNexus Outstream Video Ad via Prebid.js` }, - loaded: false, - }); - - try { - renderer.setRender(outstreamRender); - } catch (err) { - utils.logWarn('Prebid Error calling setRender on renderer', err); - } - - renderer.setEventHandlers({ - impression: () => utils.logMessage('AppNexus outstream video impression event'), - loaded: () => utils.logMessage('AppNexus outstream video loaded event'), - ended: () => { - utils.logMessage('AppNexus outstream renderer video event'); - document.querySelector(`#${adUnitCode}`).style.display = 'none'; - } - }); - return renderer; -} - -/* Turn keywords parameter into ut-compatible format */ -function getKeywords(keywords) { - let arrs = []; - - utils._each(keywords, (v, k) => { - if (utils.isArray(v)) { - let values = []; - utils._each(v, (val) => { - val = utils.getValueString('keywords.' + k, val); - if (val) { values.push(val); } - }); - v = values; - } else { - v = utils.getValueString('keywords.' + k, v); - if (utils.isStr(v)) { - v = [v]; - } else { - return; - } // unsuported types - don't send a key - } - arrs.push({key: k, value: v}); - }); - - return arrs; -} - -/** - * Unpack the Server's Bid into a Prebid-compatible one. - * @param serverBid - * @param rtbBid - * @return Bid - */ -function newBid(serverBid, rtbBid) { - const bid = { - requestId: serverBid.uuid, - cpm: rtbBid.cpm, - creativeId: rtbBid.creative_id, - dealId: rtbBid.deal_id, - currency: 'USD', - netRevenue: true, - ttl: 300 - }; - - if (rtbBid.rtb.video) { - Object.assign(bid, { - width: rtbBid.rtb.video.player_width, - height: rtbBid.rtb.video.player_height, - vastUrl: rtbBid.rtb.video.asset_url, - ttl: 3600 - }); - // This supports Outstream Video - if (rtbBid.renderer_url) { - Object.assign(bid, { - adResponse: serverBid, - renderer: newRenderer(bid.adUnitCode, rtbBid) - }); - bid.adResponse.ad = bid.adResponse.ads[0]; - bid.adResponse.ad.video = bid.adResponse.ad.rtb.video; - } - } else if (rtbBid.rtb[NATIVE]) { - const nativeAd = rtbBid.rtb[NATIVE]; - bid[NATIVE] = { - title: nativeAd.title, - body: nativeAd.desc, - cta: nativeAd.ctatext, - sponsoredBy: nativeAd.sponsored, - image: { - url: nativeAd.main_img && nativeAd.main_img.url, - height: nativeAd.main_img && nativeAd.main_img.height, - width: nativeAd.main_img && nativeAd.main_img.width, - }, - icon: { - url: nativeAd.icon && nativeAd.icon.url, - height: nativeAd.icon && nativeAd.icon.height, - width: nativeAd.icon && nativeAd.icon.width, - }, - clickUrl: nativeAd.link.url, - clickTrackers: nativeAd.link.click_trackers, - impressionTrackers: nativeAd.impression_trackers, - }; - } else { - Object.assign(bid, { - width: rtbBid.rtb.banner.width, - height: rtbBid.rtb.banner.height, - ad: rtbBid.rtb.banner.content - }); - try { - const url = rtbBid.rtb.trackers[0].impression_urls[0]; - const tracker = utils.createTrackPixelHtml(url); - bid.ad += tracker; - } catch (error) { - utils.logError('Error appending tracking pixel', error); - } - } - - return bid; -} - -function bidToTag(bid) { - const tag = {}; - tag.sizes = transformSizes(bid.sizes); - tag.primary_size = tag.sizes[0]; - tag.ad_types = []; - tag.uuid = bid.bidId; - if (bid.params.placementId) { - tag.id = parseInt(bid.params.placementId, 10); - } else { - tag.code = bid.params.invCode; - } - tag.allow_smaller_sizes = bid.params.allowSmallerSizes || false; - tag.use_pmt_rule = bid.params.usePaymentRule || false - tag.prebid = true; - tag.disable_psa = true; - if (bid.params.reserve) { - tag.reserve = bid.params.reserve; - } - if (bid.params.position) { - tag.position = {'above': 1, 'below': 2}[bid.params.position] || 0; - } - if (bid.params.trafficSourceCode) { - tag.traffic_source_code = bid.params.trafficSourceCode; - } - if (bid.params.privateSizes) { - tag.private_sizes = getSizes(bid.params.privateSizes); - } - if (bid.params.supplyType) { - tag.supply_type = bid.params.supplyType; - } - if (bid.params.pubClick) { - tag.pubclick = bid.params.pubClick; - } - if (bid.params.extInvCode) { - tag.ext_inv_code = bid.params.extInvCode; - } - if (bid.params.externalImpId) { - tag.external_imp_id = bid.params.externalImpId; - } - if (!utils.isEmpty(bid.params.keywords)) { - tag.keywords = getKeywords(bid.params.keywords); - } - - if (bid.mediaType === NATIVE || utils.deepAccess(bid, 'mediaTypes.native')) { - tag.ad_types.push(NATIVE); - - if (bid.nativeParams) { - const nativeRequest = buildNativeRequest(bid.nativeParams); - tag[NATIVE] = {layouts: [nativeRequest]}; - } - } - - const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); - const context = utils.deepAccess(bid, 'mediaTypes.video.context'); - - if (bid.mediaType === VIDEO || videoMediaType) { - tag.ad_types.push(VIDEO); - } - - // instream gets vastUrl, outstream gets vastXml - if (bid.mediaType === VIDEO || (videoMediaType && context !== 'outstream')) { - tag.require_asset_url = true; - } - - if (bid.params.video) { - tag.video = {}; - // place any valid video params on the tag - Object.keys(bid.params.video) - .filter(param => VIDEO_TARGETING.includes(param)) - .forEach(param => tag.video[param] = bid.params.video[param]); - } - - if ( - (utils.isEmpty(bid.mediaType) && utils.isEmpty(bid.mediaTypes)) || - (bid.mediaType === BANNER || (bid.mediaTypes && bid.mediaTypes[BANNER])) - ) { - tag.ad_types.push(BANNER); - } - - return tag; -} - -/* Turn bid request sizes into ut-compatible format */ -function transformSizes(requestSizes) { - let sizes = []; - let sizeObj = {}; - - if (utils.isArray(requestSizes) && requestSizes.length === 2 && - !utils.isArray(requestSizes[0])) { - sizeObj.width = parseInt(requestSizes[0], 10); - sizeObj.height = parseInt(requestSizes[1], 10); - sizes.push(sizeObj); - } else if (typeof requestSizes === 'object') { - for (let i = 0; i < requestSizes.length; i++) { - let size = requestSizes[i]; - sizeObj = {}; - sizeObj.width = parseInt(size[0], 10); - sizeObj.height = parseInt(size[1], 10); - sizes.push(sizeObj); - } - } - - return sizes; -} - -function hasUserInfo(bid) { - return !!bid.params.user; -} - -function hasMemberId(bid) { - return !!parseInt(bid.params.member, 10); -} - -function getRtbBid(tag) { - return tag && tag.ads && tag.ads.length && tag.ads.find(ad => ad.rtb); -} - -function buildNativeRequest(params) { - const request = {}; - - // map standard prebid native asset identifier to /ut parameters - // e.g., tag specifies `body` but /ut only knows `description`. - // mapping may be in form {tag: ''} or - // {tag: {serverName: '', requiredParams: {...}}} - Object.keys(params).forEach(key => { - // check if one of the forms is used, otherwise - // a mapping wasn't specified so pass the key straight through - const requestKey = - (NATIVE_MAPPING[key] && NATIVE_MAPPING[key].serverName) || - NATIVE_MAPPING[key] || - key; - - // required params are always passed on request - const requiredParams = NATIVE_MAPPING[key] && NATIVE_MAPPING[key].requiredParams; - request[requestKey] = Object.assign({}, requiredParams, params[key]); - - // minimum params are passed if no non-required params given on adunit - const minimumParams = NATIVE_MAPPING[key] && NATIVE_MAPPING[key].minimumParams; - - if (requiredParams && minimumParams) { - // subtract required keys from adunit keys - const adunitKeys = Object.keys(params[key]); - const requiredKeys = Object.keys(requiredParams); - const remaining = adunitKeys.filter(key => !requiredKeys.includes(key)); - - // if none are left over, the minimum params needs to be sent - if (remaining.length === 0) { - request[requestKey] = Object.assign({}, request[requestKey], minimumParams); - } - } - }); - - return request; -} - -function outstreamRender(bid) { - // push to render queue because ANOutstreamVideo may not be loaded yet - bid.renderer.push(() => { - window.ANOutstreamVideo.renderAd({ - tagId: bid.adResponse.tag_id, - sizes: [bid.getSize().split('x')], - targetId: bid.adUnitCode, // target div id to render video - uuid: bid.adResponse.uuid, - adResponse: bid.adResponse, - rendererOptions: bid.renderer.getConfig() - }, handleOutstreamRendererEvents.bind(null, bid)); - }); -} - -function handleOutstreamRendererEvents(bid, id, eventName) { - bid.renderer.handleVideoEvent({ id, eventName }); -} - -function parseMediaType(rtbBid) { - const adType = rtbBid.ad_type; - if (adType === VIDEO) { - return VIDEO; - } else if (adType === NATIVE) { - return NATIVE; - } else { - return BANNER; - } -} - -registerBidder(spec); diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 1fb48b68fc4..d46be776b59 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -1,237 +1,422 @@ -import { getBidRequest } from 'src/utils'; -import adaptermanager from 'src/adaptermanager'; - -var CONSTANTS = require('src/constants'); -var utils = require('src/utils'); -var adloader = require('src/adloader'); -var bidmanager = require('src/bidmanager'); -var bidfactory = require('src/bidfactory'); -var Adapter = require('src/adapter').default; - -var AppNexusAdapter; -AppNexusAdapter = function AppNexusAdapter() { - var baseAdapter = new Adapter('appnexus'); - var usersync = false; - - baseAdapter.callBids = function (params) { - // var bidCode = baseAdapter.getBidderCode(); - - var anArr = params.bids; - - // var bidsCount = anArr.length; - - // set expected bids count for callback execution - // bidmanager.setExpectedBidsCount(bidCode, bidsCount); +import { Renderer } from 'src/Renderer'; +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { NATIVE, VIDEO } from 'src/mediaTypes'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; + +const BIDDER_CODE = 'appnexus'; +const URL = '//ib.adnxs.com/ut/v3/prebid'; +const SUPPORTED_AD_TYPES = ['banner', 'video', 'native']; +const VIDEO_TARGETING = ['id', 'mimes', 'minduration', 'maxduration', + 'startdelay', 'skippable', 'playback_method', 'frameworks']; +const USER_PARAMS = ['age', 'external_uid', 'segments', 'gender', 'dnt', 'language']; +const NATIVE_MAPPING = { + body: 'description', + cta: 'ctatext', + image: { + serverName: 'main_image', + requiredParams: { required: true }, + minimumParams: { sizes: [{}] }, + }, + icon: { + serverName: 'icon', + requiredParams: { required: true }, + minimumParams: { sizes: [{}] }, + }, + sponsoredBy: 'sponsored_by', +}; +const SOURCE = 'pbjs'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['appnexusAst', 'brealtime', 'pagescience', 'defymedia', 'gourmetads', 'matomy', 'featureforward', 'oftmedia'], + supportedMediaTypes: [VIDEO, NATIVE], + + /** + * Determines whether or not the given bid request is valid. + * + * @param {object} bid The bid to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: function(bid) { + return !!(bid.params.placementId || (bid.params.member && bid.params.invCode)); + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(bidRequests, bidderRequest) { + const tags = bidRequests.map(bidToTag); + const userObjBid = find(bidRequests, hasUserInfo); + let userObj; + if (userObjBid) { + userObj = {}; + Object.keys(userObjBid.params.user) + .filter(param => includes(USER_PARAMS, param)) + .forEach(param => userObj[param] = userObjBid.params.user[param]); + } - for (var i = 0; i < anArr.length; i++) { - var bidRequest = anArr[i]; - var callbackId = bidRequest.bidId; - adloader.loadScript(buildJPTCall(bidRequest, callbackId)); + const memberIdBid = find(bidRequests, hasMemberId); + const member = memberIdBid ? parseInt(memberIdBid.params.member, 10) : 0; - // store a reference to the bidRequest from the callback id - // bidmanager.pbCallbackMap[callbackId] = bidRequest; + const payload = { + tags: [...tags], + user: userObj, + sdk: { + source: SOURCE, + version: '$prebid.version$' + } + }; + if (member > 0) { + payload.member_id = member; } - }; - - function buildJPTCall(bid, callbackId) { - // determine tag params - var placementId = utils.getBidIdParameter('placementId', bid.params); - - // memberId will be deprecated, use member instead - var memberId = utils.getBidIdParameter('memberId', bid.params); - var member = utils.getBidIdParameter('member', bid.params); - var inventoryCode = utils.getBidIdParameter('invCode', bid.params); - var query = utils.getBidIdParameter('query', bid.params); - var referrer = utils.getBidIdParameter('referrer', bid.params); - var altReferrer = utils.getBidIdParameter('alt_referrer', bid.params); - 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_uid', callbackId); - jptCall = utils.tryAppendQueryString(jptCall, 'psa', '0'); - jptCall = utils.tryAppendQueryString(jptCall, 'id', placementId); - jptCall = utils.tryAppendQueryString(jptCall, 'use_pmt_rule', usePaymentRule); - - if (member) { - jptCall = utils.tryAppendQueryString(jptCall, 'member', member); - } else if (memberId) { - jptCall = utils.tryAppendQueryString(jptCall, 'member', memberId); - utils.logMessage('appnexus.callBids: "memberId" will be deprecated soon. Please use "member" instead'); + const payloadString = JSON.stringify(payload); + return { + method: 'POST', + url: URL, + data: payloadString, + bidderRequest + }; + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} serverResponse A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function(serverResponse, {bidderRequest}) { + serverResponse = serverResponse.body; + const bids = []; + if (!serverResponse || serverResponse.error) { + let errorMessage = `in response for ${bidderRequest.bidderCode} adapter`; + if (serverResponse && serverResponse.error) { errorMessage += `: ${serverResponse.error}`; } + utils.logError(errorMessage); + return bids; } - jptCall = utils.tryAppendQueryString(jptCall, 'code', inventoryCode); - jptCall = utils.tryAppendQueryString(jptCall, 'traffic_source_code', (utils.getBidIdParameter('trafficSourceCode', bid.params))); - - // sizes takes a bit more logic - var sizeQueryString = ''; - var parsedSizes = utils.parseSizesInput(bid.sizes); - - // combine string into proper querystring for impbus - var parsedSizesLength = parsedSizes.length; - if (parsedSizesLength > 0) { - // first value should be "size" - sizeQueryString = 'size=' + parsedSizes[0]; - if (parsedSizesLength > 1) { - // any subsequent values should be "promo_sizes" - sizeQueryString += '&promo_sizes='; - for (var j = 1; j < parsedSizesLength; j++) { - sizeQueryString += parsedSizes[j] += ','; + if (serverResponse.tags) { + serverResponse.tags.forEach(serverBid => { + const rtbBid = getRtbBid(serverBid); + if (rtbBid) { + if (rtbBid.cpm !== 0 && includes(SUPPORTED_AD_TYPES, rtbBid.ad_type)) { + const bid = newBid(serverBid, rtbBid); + bid.mediaType = parseMediaType(rtbBid); + bids.push(bid); + } } - - // remove trailing comma - if (sizeQueryString && sizeQueryString.charAt(sizeQueryString.length - 1) === ',') { - sizeQueryString = sizeQueryString.slice(0, sizeQueryString.length - 1); - } - } + }); } - - if (sizeQueryString) { - jptCall += sizeQueryString + '&'; + return bids; + }, + + getUserSyncs: function(syncOptions) { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html' + }]; } + } +} + +function newRenderer(adUnitCode, rtbBid) { + const renderer = Renderer.install({ + id: rtbBid.renderer_id, + url: rtbBid.renderer_url, + config: { adText: `AppNexus Outstream Video Ad via Prebid.js` }, + loaded: false, + }); - // this will be deprecated soon - var targetingParams = utils.parseQueryStringParameters(query); - - if (targetingParams) { - // don't append a & here, we have already done it in parseQueryStringParameters - jptCall += targetingParams; - } + try { + renderer.setRender(outstreamRender); + } catch (err) { + utils.logWarn('Prebid Error calling setRender on renderer', err); + } - // append custom attributes: - var paramsCopy = Object.assign({}, bid.params); - - // delete attributes already used - delete paramsCopy.placementId; - delete paramsCopy.memberId; - delete paramsCopy.invCode; - delete paramsCopy.query; - delete paramsCopy.referrer; - delete paramsCopy.alt_referrer; - delete paramsCopy.member; - delete paramsCopy.usePaymentRule; - - // get the reminder - var queryParams = utils.parseQueryStringParameters(paramsCopy); - - // append - if (queryParams) { - jptCall += queryParams; + renderer.setEventHandlers({ + impression: () => utils.logMessage('AppNexus outstream video impression event'), + loaded: () => utils.logMessage('AppNexus outstream video loaded event'), + ended: () => { + utils.logMessage('AppNexus outstream renderer video event'); + document.querySelector(`#${adUnitCode}`).style.display = 'none'; } - - // append referrer - if (referrer === '') { - referrer = utils.getTopWindowUrl(); + }); + return renderer; +} + +/* Turn keywords parameter into ut-compatible format */ +function getKeywords(keywords) { + let arrs = []; + + utils._each(keywords, (v, k) => { + if (utils.isArray(v)) { + let values = []; + utils._each(v, (val) => { + val = utils.getValueString('keywords.' + k, val); + if (val) { values.push(val); } + }); + v = values; + } else { + v = utils.getValueString('keywords.' + k, v); + if (utils.isStr(v)) { + v = [v]; + } else { + return; + } // unsuported types - don't send a key } + arrs.push({key: k, value: v}); + }); - jptCall = utils.tryAppendQueryString(jptCall, 'referrer', referrer); - jptCall = utils.tryAppendQueryString(jptCall, 'alt_referrer', altReferrer); + return arrs; +} + +/** + * Unpack the Server's Bid into a Prebid-compatible one. + * @param serverBid + * @param rtbBid + * @return Bid + */ +function newBid(serverBid, rtbBid) { + const bid = { + requestId: serverBid.uuid, + cpm: rtbBid.cpm, + creativeId: rtbBid.creative_id, + dealId: rtbBid.deal_id, + currency: 'USD', + netRevenue: true, + ttl: 300 + }; - // remove the trailing "&" - if (jptCall.lastIndexOf('&') === jptCall.length - 1) { - jptCall = jptCall.substring(0, jptCall.length - 1); + if (rtbBid.rtb.video) { + Object.assign(bid, { + width: rtbBid.rtb.video.player_width, + height: rtbBid.rtb.video.player_height, + vastUrl: rtbBid.rtb.video.asset_url, + descriptionUrl: rtbBid.rtb.video.asset_url, + ttl: 3600 + }); + // This supports Outstream Video + if (rtbBid.renderer_url) { + Object.assign(bid, { + adResponse: serverBid, + renderer: newRenderer(bid.adUnitCode, rtbBid) + }); + bid.adResponse.ad = bid.adResponse.ads[0]; + bid.adResponse.ad.video = bid.adResponse.ad.rtb.video; } + } else if (rtbBid.rtb['native']) { + const nativeAd = rtbBid.rtb['native']; + bid['native'] = { + title: nativeAd.title, + body: nativeAd.desc, + cta: nativeAd.ctatext, + sponsoredBy: nativeAd.sponsored, + image: { + url: nativeAd.main_img && nativeAd.main_img.url, + height: nativeAd.main_img && nativeAd.main_img.height, + width: nativeAd.main_img && nativeAd.main_img.width, + }, + icon: { + url: nativeAd.icon && nativeAd.icon.url, + height: nativeAd.icon && nativeAd.icon.height, + width: nativeAd.icon && nativeAd.icon.width, + }, + clickUrl: nativeAd.link.url, + clickTrackers: nativeAd.link.click_trackers, + impressionTrackers: nativeAd.impression_trackers, + }; + } else { + Object.assign(bid, { + width: rtbBid.rtb.banner.width, + height: rtbBid.rtb.banner.height, + ad: rtbBid.rtb.banner.content + }); + try { + const url = rtbBid.rtb.trackers[0].impression_urls[0]; + const tracker = utils.createTrackPixelHtml(url); + bid.ad += tracker; + } catch (error) { + utils.logError('Error appending tracking pixel', error); + } + } - // @if NODE_ENV='debug' - utils.logMessage('jpt request built: ' + jptCall); - - // @endif + return bid; +} + +function bidToTag(bid) { + const tag = {}; + tag.sizes = transformSizes(bid.sizes); + tag.primary_size = tag.sizes[0]; + tag.uuid = bid.bidId; + if (bid.params.placementId) { + tag.id = parseInt(bid.params.placementId, 10); + } else { + tag.code = bid.params.invCode; + } + tag.allow_smaller_sizes = bid.params.allowSmallerSizes || false; + tag.use_pmt_rule = bid.params.usePaymentRule || false + tag.prebid = true; + tag.disable_psa = true; + if (bid.params.reserve) { + tag.reserve = bid.params.reserve; + } + if (bid.params.position) { + tag.position = {'above': 1, 'below': 2}[bid.params.position] || 0; + } + if (bid.params.trafficSourceCode) { + tag.traffic_source_code = bid.params.trafficSourceCode; + } + if (bid.params.privateSizes) { + tag.private_sizes = getSizes(bid.params.privateSizes); + } + if (bid.params.supplyType) { + tag.supply_type = bid.params.supplyType; + } + if (bid.params.pubClick) { + tag.pubclick = bid.params.pubClick; + } + if (bid.params.extInvCode) { + tag.ext_inv_code = bid.params.extInvCode; + } + if (bid.params.externalImpId) { + tag.external_imp_id = bid.params.externalImpId; + } + if (!utils.isEmpty(bid.params.keywords)) { + tag.keywords = getKeywords(bid.params.keywords); + } - // append a timer here to track latency - bid.startTime = new Date().getTime(); + if (bid.mediaType === 'native' || utils.deepAccess(bid, 'mediaTypes.native')) { + tag.ad_types = ['native']; - return jptCall; + if (bid.nativeParams) { + const nativeRequest = buildNativeRequest(bid.nativeParams); + tag['native'] = {layouts: [nativeRequest]}; + } } - // expose the callback to the global object: - $$PREBID_GLOBAL$$.handleAnCB = function (jptResponseObj) { - var bidCode; - - if (jptResponseObj && jptResponseObj.callback_uid) { - var responseCPM; - var id = jptResponseObj.callback_uid; - var placementCode = ''; - var bidObj = getBidRequest(id); - if (bidObj) { - bidCode = bidObj.bidder; + const videoMediaType = utils.deepAccess(bid, 'mediaTypes.video'); + const context = utils.deepAccess(bid, 'mediaTypes.video.context'); - placementCode = bidObj.placementCode; + if (bid.mediaType === 'video' || (videoMediaType && context !== 'outstream')) { + tag.require_asset_url = true; + } - // set the status - bidObj.status = CONSTANTS.STATUS.GOOD; - } + if (bid.params.video) { + tag.video = {}; + // place any valid video params on the tag + Object.keys(bid.params.video) + .filter(param => includes(VIDEO_TARGETING, param)) + .forEach(param => tag.video[param] = bid.params.video[param]); + } - // @if NODE_ENV='debug' - utils.logMessage('JSONP callback function called for ad ID: ' + id); - - // @endif - var bid = []; - if (jptResponseObj.result && jptResponseObj.result.cpm && jptResponseObj.result.cpm !== 0) { - responseCPM = parseInt(jptResponseObj.result.cpm, 10); - - // CPM response from /jpt is dollar/cent multiplied by 10000 - // in order to avoid using floats - // switch CPM to "dollar/cent" - responseCPM = responseCPM / 10000; - - // store bid response - // bid status is good (indicating 1) - var adId = jptResponseObj.result.creative_id; - bid = bidfactory.createBid(1, bidObj); - bid.creative_id = adId; - bid.bidderCode = bidCode; - bid.cpm = responseCPM; - bid.adUrl = jptResponseObj.result.ad; - bid.width = jptResponseObj.result.width; - bid.height = jptResponseObj.result.height; - bid.dealId = jptResponseObj.result.deal_id; - - bidmanager.addBidResponse(placementCode, bid); - } else { - // no response data - // @if NODE_ENV='debug' - utils.logMessage('No prebid response from AppNexus for placement code ' + placementCode); - - // @endif - // indicate that there is no bid for this placement - bid = bidfactory.createBid(2, bidObj); - bid.bidderCode = bidCode; - bidmanager.addBidResponse(placementCode, bid); - } + return tag; +} + +/* Turn bid request sizes into ut-compatible format */ +function transformSizes(requestSizes) { + let sizes = []; + let sizeObj = {}; + + if (utils.isArray(requestSizes) && requestSizes.length === 2 && + !utils.isArray(requestSizes[0])) { + sizeObj.width = parseInt(requestSizes[0], 10); + sizeObj.height = parseInt(requestSizes[1], 10); + sizes.push(sizeObj); + } else if (typeof requestSizes === 'object') { + for (let i = 0; i < requestSizes.length; i++) { + let size = requestSizes[i]; + sizeObj = {}; + sizeObj.width = parseInt(size[0], 10); + sizeObj.height = parseInt(size[1], 10); + sizes.push(sizeObj); + } + } - if (!usersync) { - var iframe = utils.createInvisibleIframe(); - iframe.src = '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html'; - try { - document.body.appendChild(iframe); - } catch (error) { - utils.logError(error); - } - usersync = true; + return sizes; +} + +function hasUserInfo(bid) { + return !!bid.params.user; +} + +function hasMemberId(bid) { + return !!parseInt(bid.params.member, 10); +} + +function getRtbBid(tag) { + return tag && tag.ads && tag.ads.length && find(tag.ads, ad => ad.rtb); +} + +function buildNativeRequest(params) { + const request = {}; + + // map standard prebid native asset identifier to /ut parameters + // e.g., tag specifies `body` but /ut only knows `description`. + // mapping may be in form {tag: ''} or + // {tag: {serverName: '', requiredParams: {...}}} + Object.keys(params).forEach(key => { + // check if one of the forms is used, otherwise + // a mapping wasn't specified so pass the key straight through + const requestKey = + (NATIVE_MAPPING[key] && NATIVE_MAPPING[key].serverName) || + NATIVE_MAPPING[key] || + key; + + // required params are always passed on request + const requiredParams = NATIVE_MAPPING[key] && NATIVE_MAPPING[key].requiredParams; + request[requestKey] = Object.assign({}, requiredParams, params[key]); + + // minimum params are passed if no non-required params given on adunit + const minimumParams = NATIVE_MAPPING[key] && NATIVE_MAPPING[key].minimumParams; + + if (requiredParams && minimumParams) { + // subtract required keys from adunit keys + const adunitKeys = Object.keys(params[key]); + const requiredKeys = Object.keys(requiredParams); + const remaining = adunitKeys.filter(key => !includes(requiredKeys, key)); + + // if none are left over, the minimum params needs to be sent + if (remaining.length === 0) { + request[requestKey] = Object.assign({}, request[requestKey], minimumParams); } - } else { - // no response data - // @if NODE_ENV='debug' - utils.logMessage('No prebid response for placement %%PLACEMENT%%'); - - // @endif } - }; - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - buildJPTCall: buildJPTCall }); -}; -adaptermanager.registerBidAdapter(new AppNexusAdapter(), 'appnexus'); -adaptermanager.aliasBidAdapter('appnexus', 'brealtime'); -adaptermanager.aliasBidAdapter('appnexus', 'pagescience'); -adaptermanager.aliasBidAdapter('appnexus', 'defymedia'); -adaptermanager.aliasBidAdapter('appnexus', 'gourmetads'); -adaptermanager.aliasBidAdapter('appnexus', 'matomy'); -adaptermanager.aliasBidAdapter('appnexus', 'featureforward'); -adaptermanager.aliasBidAdapter('appnexus', 'oftmedia'); + return request; +} + +function outstreamRender(bid) { + // push to render queue because ANOutstreamVideo may not be loaded yet + bid.renderer.push(() => { + window.ANOutstreamVideo.renderAd({ + tagId: bid.adResponse.tag_id, + sizes: [bid.getSize().split('x')], + targetId: bid.adUnitCode, // target div id to render video + uuid: bid.adResponse.uuid, + adResponse: bid.adResponse, + rendererOptions: bid.renderer.getConfig() + }, handleOutstreamRendererEvents.bind(null, bid)); + }); +} + +function handleOutstreamRendererEvents(bid, id, eventName) { + bid.renderer.handleVideoEvent({ id, eventName }); +} + +function parseMediaType(rtbBid) { + const adType = rtbBid.ad_type; + if (adType === 'video') { + return 'video'; + } else if (adType === 'native') { + return 'native'; + } else { + return 'banner'; + } +} -module.exports = AppNexusAdapter; +registerBidder(spec); diff --git a/modules/appnexusAstBidAdapter.md b/modules/appnexusBidAdapter.md similarity index 87% rename from modules/appnexusAstBidAdapter.md rename to modules/appnexusBidAdapter.md index 2b370e11616..58f260cdfc8 100644 --- a/modules/appnexusAstBidAdapter.md +++ b/modules/appnexusBidAdapter.md @@ -1,7 +1,7 @@ # Overview ``` -Module Name: AppnexusAst Bid Adapter +Module Name: Appnexus Bid Adapter Module Type: Bidder Adapter Maintainer: info@prebid.org ``` @@ -10,7 +10,7 @@ Maintainer: info@prebid.org Connects to Appnexus exchange for bids. -AppnexusAst bid adapter supports Banner, Video (instream and outstream) and Native. +Appnexus bid adapter supports Banner, Video (instream and outstream) and Native. # Test Parameters ``` @@ -20,7 +20,7 @@ var adUnits = [ code: 'banner-div', sizes: [[300, 250], [300,600]], bids: [{ - bidder: 'appnexusAst', + bidder: 'appnexus', params: { placementId: '10433394' } @@ -51,7 +51,7 @@ var adUnits = [ } }, bids: [{ - bidder: 'appnexusAst', + bidder: 'appnexus', params: { placementId: '9880618' } @@ -67,7 +67,7 @@ var adUnits = [ }, }, bids: [{ - bidder: 'appnexusAst', + bidder: 'appnexus', params: { placementId: '9333431', video: { @@ -88,7 +88,7 @@ var adUnits = [ }, bids: [ { - bidder: 'appnexusAst', + bidder: 'appnexus', params: { placementId: '5768085', video: { diff --git a/modules/atomxBidAdapter.js b/modules/atomxBidAdapter.js deleted file mode 100644 index 69bb04a227b..00000000000 --- a/modules/atomxBidAdapter.js +++ /dev/null @@ -1,81 +0,0 @@ -var CONSTANTS = require('src/constants.json'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var Ajax = require('src/ajax'); -var utils = require('src/utils.js'); -var adaptermanager = require('src/adaptermanager'); - -/** - * Adapter for requesting bids from Atomx. - * - * @returns {{callBids: _callBids, responseCallback: _responseCallback}} - */ -var AtomxAdapter = function AtomxAdapter() { - function _callBids(data) { - if (!window.atomx_prebid) { - adloader.loadScript(window.location.protocol + '//s.ato.mx/b.js', function() { _bid(data); }, true); - } else { - _bid(data); - } - } - - function _bid(data) { - var url = window.atomx_prebid(); - var bids = data.bids || []; - for (var i = 0, ln = bids.length; i < ln; i++) { - var bid = bids[i]; - if (bid.params && bid.params.id) { - var sizes = utils.parseSizesInput(bid.sizes); - for (var j = 0; j < sizes.length; j++) { - Ajax.ajax(url, _responseCallback.bind(this, bid), { - id: bid.params.id, - size: sizes[j], - prebid: bid.placementCode - }, {method: 'GET', noDecodeWholeURL: true}); - } - } else { - var bidObject = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, bid); - bidObject.bidderCode = 'atomx'; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } - } - } - - function _responseCallback(bid, data) { - var bidObject; - try { - data = JSON.parse(data); - - if (data.cpm && data.cpm > 0) { - bidObject = bidfactory.createBid(CONSTANTS.STATUS.GOOD, bid); - bidObject.bidderCode = 'atomx'; - bidObject.cpm = data.cpm * 1000; - if (data.adm) { - bidObject.ad = data.adm; - } else { - bidObject.adUrl = data.url; - } - bidObject.width = data.width; - bidObject.height = data.height; - bidmanager.addBidResponse(bid.placementCode, bidObject); - return; - } - } catch (_error) { - utils.logError(_error); - } - - bidObject = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, bid); - bidObject.bidderCode = 'atomx'; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } - - return { - callBids: _callBids, - responseCallback: _responseCallback - }; -}; - -adaptermanager.registerBidAdapter(new AtomxAdapter(), 'atomx'); - -module.exports = AtomxAdapter; diff --git a/modules/audienceNetworkBidAdapter.js b/modules/audienceNetworkBidAdapter.js index 04df8e845c9..41ca539ccba 100644 --- a/modules/audienceNetworkBidAdapter.js +++ b/modules/audienceNetworkBidAdapter.js @@ -5,6 +5,8 @@ import { registerBidder } from 'src/adapters/bidderFactory'; import { config } from 'src/config'; import { formatQS } from 'src/url'; import { getTopWindowUrl } from 'src/utils'; +import findIndex from 'core-js/library/fn/array/find-index'; +import includes from 'core-js/library/fn/array/includes'; const code = 'audienceNetwork'; const currency = 'USD'; @@ -47,7 +49,7 @@ const expandSize = size => size.split('x').map(Number); * @param {String} size * @returns {Boolean} */ -const isValidSize = size => ['300x250', '320x50'].includes(size); +const isValidSize = size => includes(['300x250', '320x50'], size); /** * Is this a video format? @@ -139,7 +141,7 @@ const buildRequests = bids => { pageurl, sdk }; - const video = adformats.findIndex(isVideo); + const video = findIndex(adformats, isVideo); if (video !== -1) { [search.playerwidth, search.playerheight] = sizes[video].split('x').map(Number) } diff --git a/modules/bidfluenceBidAdapter.js b/modules/bidfluenceBidAdapter.js deleted file mode 100644 index 73b548a4993..00000000000 --- a/modules/bidfluenceBidAdapter.js +++ /dev/null @@ -1,58 +0,0 @@ -const bidmanager = require('src/bidmanager'); -const bidfactory = require('src/bidfactory'); -const utils = require('src/utils'); -const adloader = require('src/adloader'); -const adaptermanager = require('src/adaptermanager'); - -var BidfluenceAdapter = function BidfluenceAdapter() { - const scriptUrl = '//cdn.bidfluence.com/forge.js'; - - $$PREBID_GLOBAL$$.bfPbjsCB = function (bfr) { - var bidRequest = utils.getBidRequest(bfr.cbID); - var bidObject = null; - if (bfr.cpm > 0) { - bidObject = bidfactory.createBid(1, bidRequest); - bidObject.bidderCode = 'bidfluence'; - bidObject.cpm = bfr.cpm; - bidObject.ad = bfr.ad; - bidObject.width = bfr.width; - bidObject.height = bfr.height; - } else { - bidObject = bidfactory.createBid(2, bidRequest); - bidObject.bidderCode = 'bidfluence'; - } - - bidmanager.addBidResponse(bfr.placementCode, bidObject); - }; - - function _callBids(params) { - var bfbids = params.bids || []; - for (var i = 0; i < bfbids.length; i++) { - var bid = bfbids[i]; - call(bid); - } - } - function call(bid) { - var adunitId = utils.getBidIdParameter('adunitId', bid.params); - var publisherId = utils.getBidIdParameter('pubId', bid.params); - var reservePrice = utils.getBidIdParameter('reservePrice', bid.params); - var pbjsBfobj = { - placementCode: bid.placementCode, - cbID: bid.bidId - }; - - var cb = function () { - /* globals FORGE */ - FORGE.init([adunitId, publisherId, pbjsBfobj, reservePrice]); - }; - - adloader.loadScript(scriptUrl, cb); - } - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new BidfluenceAdapter(), 'bidfluence'); - -module.exports = BidfluenceAdapter; diff --git a/modules/bridgewellBidAdapter.js b/modules/bridgewellBidAdapter.js index d224355c3a5..ec70342c964 100644 --- a/modules/bridgewellBidAdapter.js +++ b/modules/bridgewellBidAdapter.js @@ -1,5 +1,6 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; +import find from 'core-js/library/fn/array/find'; const BIDDER_CODE = 'bridgewell'; const REQUEST_ENDPOINT = '//rec.scupio.com/recweb/prebid.aspx'; @@ -58,8 +59,8 @@ export const spec = { return; } - let matchedResponse = serverResponse.body.find(function(res) { - return !!res && !res.consumed && req.sizes.find(function(size) { + let matchedResponse = find(serverResponse.body, function(res) { + return !!res && !res.consumed && find(req.sizes, function(size) { return res.width === size[0] && res.height === size[1]; }); }); diff --git a/modules/brightcomBidAdapter.js b/modules/brightcomBidAdapter.js deleted file mode 100644 index f1256edeab8..00000000000 --- a/modules/brightcomBidAdapter.js +++ /dev/null @@ -1,205 +0,0 @@ -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 Brightcom - */ -var BrightcomAdapter = function BrightcomAdapter() { - // Set Brightcom Bidder URL - var brightcomUrl = 'hb.iselephant.com/auc/ortb'; - - // Define the bidder code - 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'; - - // Manage the requested and received ad units' codes, to know which are invalid (didn't return) - const reqAdUnitsCode = []; - const resAdUnitsCode = []; - - function _callBids(params) { - var bidRequests = params.bids || []; - - // Get page data - var siteDomain = window.location.host; - var sitePage = window.location.href; - - // Prepare impressions object - var brightcomImps = []; - - // Prepare a variable for publisher id - var pubId = ''; - - // Go through the requests and build array of impressions - utils._each(bidRequests, function(bid) { - // Get impression details - var tagId = utils.getBidIdParameter('tagId', bid.params); - var ref = utils.getBidIdParameter('ref', bid.params); - var adWidth = 0; - var adHeight = 0; - - // If no publisher id is set, use the current - if (pubId === '') { - // Get the current publisher id (if it doesn't exist, it'll return '') - pubId = utils.getBidIdParameter('pubId', bid.params); - } - - // Brightcom supports only 1 size per impression - // Check if the array contains 1 size or array of sizes - if (bid.sizes.length === 2 && typeof bid.sizes[0] === 'number' && typeof bid.sizes[1] === 'number') { - // The array contains 1 size (the items are the values) - adWidth = bid.sizes[0]; - adHeight = bid.sizes[1]; - } else { - // The array contains array of sizes, use the first size - adWidth = bid.sizes[0][0]; - adHeight = bid.sizes[0][1]; - } - - // Build the impression - var imp = { - id: utils.getUniqueIdentifierStr(), - banner: { - w: adWidth, - h: adHeight - }, - tagid: tagId - }; - - // If ref exists, create it (in the "ext" object) - if (ref !== '') { - imp.ext = { - refoverride: ref - }; - } - - // Add current impression to collection - brightcomImps.push(imp); - // Add mapping to current bid via impression id - // bidmanager.pbCallbackMap[imp.id] = bid; - - // Add current ad unit's code to tracking - reqAdUnitsCode.push(bid.placementCode); - }); - - // Build the bid request - var brightcomBidReq = { - id: utils.getUniqueIdentifierStr(), - imp: brightcomImps, - site: { - publisher: { - id: pubId - }, - domain: siteDomain, - page: sitePage - } - }; - - // Add timeout data, if available - var PREBID_TIMEOUT = PREBID_TIMEOUT || 0; - var curTimeout = PREBID_TIMEOUT; - if (curTimeout > 0) { - brightcomBidReq.tmax = curTimeout; - } - - // Define the bid request call URL - var bidRequestCallUrl = 'https://' + brightcomUrl + - '?callback=' + encodeURIComponent(brightcomCallbackFunction) + - '&request=' + encodeURIComponent(JSON.stringify(brightcomBidReq)); - - // Add the call to get the bid - adloader.loadScript(bidRequestCallUrl); - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.brightcomResponse = function(brightcomResponseObj) { - var bid = {}; - - // Make sure response is valid - if ( - (brightcomResponseObj) && (brightcomResponseObj.id) && - (brightcomResponseObj.seatbid) && (brightcomResponseObj.seatbid.length !== 0) && - (brightcomResponseObj.seatbid[0].bid) && (brightcomResponseObj.seatbid[0].bid.length !== 0) - ) { - // Go through the received bids - brightcomResponseObj.seatbid[0].bid.forEach(function(curBid) { - // Get the bid request data - var bidRequest = $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === 'brightcom').bids[0]; // this assumes a single request only - - // Make sure the bid exists - if (bidRequest) { - var placementCode = bidRequest.placementCode; - bidRequest.status = CONSTANTS.STATUS.GOOD; - - curBid.placementCode = placementCode; - curBid.size = bidRequest.sizes; - - // Get the creative - var responseCreative = curBid.adm; - // Build the NURL element - var responseNurl = ''; - // Build the ad to display: - var responseAd = decodeURIComponent(responseCreative + responseNurl); - - // Create a valid bid - bid = bidfactory.createBid(1); - - // Set the bid data - bid.creative_id = curBid.Id; - bid.bidderCode = brightcomBidderCode; - bid.cpm = parseFloat(curBid.price); - - // Brightcom tag is in `; - } - } else { - // width and height are only relevant with non-native requests. - // native requests will always return a 2x2 zone size. - bidObject.width = bidResponse.width; - bidObject.height = bidResponse.height; - bidObject.ad = bidResponse.creative; - } - } else { - bidObject = _invalidBidResponse(); - } - return bidObject; - } - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new CriteoAdapter(), 'criteo'); - -module.exports = CriteoAdapter; diff --git a/modules/currency.js b/modules/currency.js index 19e7d2903f4..f5da02d5d72 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -2,8 +2,8 @@ import bidfactory from 'src/bidfactory'; import { STATUS } from 'src/constants'; import { ajax } from 'src/ajax'; import * as utils from 'src/utils'; -import bidmanager from 'src/bidmanager'; import { config } from 'src/config'; +import { hooks } from 'src/hook.js'; const DEFAULT_CURRENCY_RATE_URL = 'http://currency.prebid.org/latest.json'; const CURRENCY_RATE_PRECISION = 4; @@ -80,7 +80,7 @@ function initCurrency(url) { utils.logInfo('Installing addBidResponse decorator for currency module', arguments); - bidmanager.addBidResponse.addHook(addBidResponseHook, 100); + hooks['addBidResponse'].addHook(addBidResponseHook, 100); if (!currencyRates.conversions) { ajax(url, function (response) { @@ -99,7 +99,7 @@ function initCurrency(url) { function resetCurrency() { utils.logInfo('Uninstalling addBidResponse decorator for currency module', arguments); - bidmanager.addBidResponse.removeHook(addBidResponseHook); + hooks['addBidResponse'].removeHook(addBidResponseHook, 100); adServerCurrency = 'USD'; conversionCache = {}; diff --git a/modules/dfpAdServerVideo.js b/modules/dfpAdServerVideo.js index 591b8f7baf3..609e9f46234 100644 --- a/modules/dfpAdServerVideo.js +++ b/modules/dfpAdServerVideo.js @@ -3,7 +3,7 @@ */ import { registerVideoSupport } from '../src/adServerManager'; -import { getWinningBids } from '../src/targeting'; +import { targeting } from '../src/targeting'; import { formatQS, format as buildUrl, parse } from '../src/url'; import { deepAccess, isEmpty, logError, parseSizesInput } from '../src/utils'; import { config } from '../src/config'; @@ -63,7 +63,7 @@ export default function buildDfpVideoUrl(options) { } const adUnit = options.adUnit; - const bid = options.bid || getWinningBids(adUnit.code)[0]; + const bid = options.bid || targeting.getWinningBids(adUnit.code)[0]; let urlComponents = {}; @@ -138,7 +138,7 @@ function buildUrlFromAdserverUrlComponents(components, bid) { * @return {string | undefined} The encoded vast url if it exists, or undefined */ function getDescriptionUrl(bid, components, prop) { - if (config.getConfig('usePrebidCache')) { return; } + if (config.getConfig('cache.url')) { return; } if (!deepAccess(components, `${prop}.description_url`)) { const vastUrl = bid && bid.vastUrl; diff --git a/modules/districtmDMXBidAdapter.js b/modules/districtmDMXBidAdapter.js deleted file mode 100644 index 1eed5f2150e..00000000000 --- a/modules/districtmDMXBidAdapter.js +++ /dev/null @@ -1,56 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adLoader = require('src/adloader'); -var adaptermanager = require('src/adaptermanager'); - -var DistrictmAdaptor = function districtmAdaptor() { - let districtmUrl = window.location.protocol + '//prebid.districtm.ca/lib.js'; - this.callBids = params => { - if (!window.hb_dmx_res) { - adLoader.loadScript(districtmUrl, () => { - this.sendBids(params); - }); - } else { - this.sendBids(params); - } - return params; - }; - - this.handlerRes = function(response, bidObject) { - let bid; - if (parseFloat(response.result.cpm) > 0) { - bid = bidfactory.createBid(1, bidObject); - bid.bidderCode = bidObject.bidder; - bid.cpm = response.result.cpm; - bid.width = response.result.width; - bid.height = response.result.height; - bid.ad = response.result.banner; - bidmanager.addBidResponse(bidObject.placementCode, bid); - } else { - bid = bidfactory.createBid(2, bidObject); - bid.bidderCode = bidObject.bidder; - bidmanager.addBidResponse(bidObject.placementCode, bid); - } - - return bid; - }; - - this.sendBids = function(params) { - var bids = params.bids; - for (var i = 0; i < bids.length; i++) { - bids[i].params.sizes = window.hb_dmx_res.auction.fixSize(bids[i].sizes); - } - window.hb_dmx_res.auction.run(window.hb_dmx_res.ssp, bids, this.handlerRes); - return bids; - }; - - return { - callBids: this.callBids, - sendBids: this.sendBids, - handlerRes: this.handlerRes - }; -}; - -adaptermanager.registerBidAdapter(new DistrictmAdaptor(), 'districtmDMX'); - -module.exports = DistrictmAdaptor; diff --git a/modules/eplanningBidAdapter.js b/modules/eplanningBidAdapter.js deleted file mode 100644 index 9c09fd3b782..00000000000 --- a/modules/eplanningBidAdapter.js +++ /dev/null @@ -1,310 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adaptermanager = require('src/adaptermanager'); - -function EPlanningAdapter() { - (function() { - const win = window; - const doc = win.document; - const pbjsVar = win.$$PREBID_GLOBAL$$; - const _global = {}; - const _default = { 'sv': 'ads.us.e-planning.net', 't': 0 }; - var rnd; - const FILE = 'file'; - const CALLBACK_FUNCTION = 'hbpb.rH'; - const NULL_SIZE = '1x1'; - const _csRequested = []; - const PROTO = location.protocol === 'https:' ? 'https:' : 'http:'; - const ISV = 'aklc.img.e-planning.net'; - function Hbpb() { - var slots = (function() { - var _data = []; - function Slot(slotId) { - var data = _data[slotId]; - function hasAds() { - return _data[slotId].ads.length; - } - function getSizes() { - return data.sizes; - } - function getSizesString() { - const s = []; - var i; - const sizes = getSizes(); - if (sizes && sizes.length) { - if (typeof sizes[0] === 'object') { - for (i = 0; i < sizes.length; i++) { - s.push(sizes[i][0] + 'x' + sizes[i][1]); - } - } else { - s.push(sizes[0] + 'x' + sizes[1]); - } - } else { - return NULL_SIZE; - } - return s.join(','); - } - return { - getPlacementCode: function() { - return data.placementCode; - }, - getString: function() { - return this.getPlacementCode() + ':' + getSizesString(); - }, - addAd: function(ad) { - _data[slotId].ads.push(ad); - }, - getFormatedResponse: function() { - var ad; - const that = this; - if (hasAds()) { - ad = data.ads[0]; - return { - 'placementCode': that.getPlacementCode(), - 'ad': { - 'ad': ad.adm, - 'cpm': ad.pr, - 'width': ad.size.w, - 'height': ad.size.h - } - }; - } else { - return { 'placementCode': that.getPlacementCode() }; - } - } - }; - } - function findAll() { - var i = 0; - const r = []; - for (i = 0; i < _data.length; i++) { - r.push(new Slot(i)); - } - return r; - } - return { - add: function(slot) { - slot.ads = []; - _data.push(slot); - }, - get: function(slotId) { - return new Slot(slotId); - }, - getString: function() { - const _slots = []; - var i; - var slot; - for (i = 0; i < _data.length; i++) { - slot = this.get(i); - _slots.push(slot.getString()); - } - return _slots.join('+'); - }, - findByPlacementCode: function(placementCode) { - var i; - const _slots = findAll(); - for (i = 0; i < _slots.length; i++) { - if (_slots[i].getPlacementCode() === placementCode) { - return _slots[i]; - } - } - }, - getFormatedResponse: function() { - const _slots = findAll(); - var i; - const r = []; - for (i = 0; i < _slots.length; i++) { - r.push(_slots[i].getFormatedResponse()); - } - return { - 'bids': r - }; - } - }; - })(); - function call(params) { - var i; - const bids = params.bids; - for (i = 0; i < bids.length; i++) { - slots.add({ - _raw: bids[i], - placementCode: bids[i].placementCode, - sizes: bids[i].sizes - }); - setGlobalParam('sv', bids[i]); - setGlobalParam('ci', bids[i]); - setGlobalParam('t', bids[i]); - } - doRequest(); - } - function setGlobalParam(param, bid) { - if (!_global[param]) { - if (bid && bid.params && bid.params[param]) { - _global[param] = bid.params[param]; - } - } - } - function getGlobalParam(param) { - return (_global[param] || _default[param]); - } - function getRandom() { - if (!rnd) { - rnd = Math.random(); - } - return rnd; - } - function getDocURL() { - return escape(win.location.href || FILE); - } - function getReferrerURL() { - return doc.referrer; - } - function getCallbackFunction() { - return CALLBACK_FUNCTION; - } - function doRequest() { - const clienteId = getGlobalParam('ci'); - var url; - const dfpClienteId = '1'; - const sec = 'ROS'; - const params = []; - const t = getGlobalParam('t'); - if (clienteId && !t) { - url = PROTO + '//' + getGlobalParam('sv') + '/hb/1/' + clienteId + '/' + dfpClienteId + '/' + (win.location.hostname || FILE) + '/' + sec + '?'; - params.push('rnd=' + getRandom()); - params.push('e=' + slots.getString()); - if (getDocURL()) { - params.push('ur=' + getDocURL()); - } - if (getReferrerURL()) { - params.push('fr=' + getReferrerURL()); - } - params.push('cb=' + getCallbackFunction()); - params.push('r=pbjs'); - url += params.join('&'); - load(url); - } else if (t) { - url = PROTO + '//' + ISV + '/layers/t_pbjs_' + t + '.js'; - load(url); - } - } - function load(url) { - var script = doc.createElement('script'); - script.src = url; - doc.body.appendChild(script); - } - function callback(response) { - if (pbjsVar && pbjsVar.processEPlanningResponse && typeof pbjsVar.processEPlanningResponse === 'function') { - pbjsVar.processEPlanningResponse(response); - } - } - function syncUsers(cs) { - var i, e, d; - for (i = 0; i < cs.length; i++) { - if (typeof cs[i] === 'string' && _csRequested.indexOf(cs[i]) === -1) { - (new Image()).src = cs[i]; - _csRequested.push(cs[i]); - } else if (typeof cs[i] === 'object' && _csRequested.indexOf(cs[i].u) === -1) { - if (cs[i].j) { - e = doc.createElement('script'); - e.src = cs[i].u; - } else if (cs[i].ifr) { - e = doc.createElement('iframe'); - e.src = cs[i].u; - e.style.width = e.style.height = '1px'; - e.display = 'none'; - } - if (cs[i].data) { - for (d in cs[i].data) { - if (cs[i].data.hasOwnProperty(d)) { - e.setAttribute('data-' + d, cs[i].data[d]); - } - } - } - doc.body.appendChild(e); - _csRequested.push(cs[i].u); - } - } - } - function rH(response) { - var slot, i, o; - if (response && response.sp && response.sp.length) { - for (i = 0; i < response.sp.length; i++) { - if (response.sp[i].a) { - slot = slots.findByPlacementCode(response.sp[i].k); - if (slot) { - for (o = 0; o < response.sp[i].a.length; o++) { - slot.addAd({ - 'adm': response.sp[i].a[o].adm, - 'pr': response.sp[i].a[o].pr, - 'size': { - 'w': response.sp[i].a[o].w, - 'h': response.sp[i].a[o].h - } - }); - } - } - } - } - callback(slots.getFormatedResponse()); - } - if (response && response.cs && response.cs.length) { - syncUsers(response.cs); - } - } - return { - call: function(params) { - return call(params); - }, - rH: function(response) { - return rH(response); - } - }; - } - win.hbpb = win.hbpb || new Hbpb(); - })(); - - window.$$PREBID_GLOBAL$$ = window.$$PREBID_GLOBAL$$ || {}; - window.$$PREBID_GLOBAL$$.processEPlanningResponse = function(response) { - var bids, bidObject, i; - if (response) { - bids = response.bids; - for (i = 0; i < bids.length; i++) { - if (bids[i].ad) { - bidObject = getBidObject(bids[i]); - bidmanager.addBidResponse(bids[i].placementCode, bidObject); - } else { - bidObject = bidfactory.createBid(2); - bidObject.bidderCode = 'eplanning'; - bidmanager.addBidResponse(bids[i].placementCode, bidObject); - } - } - } - }; - - function getBidObject(bid) { - const bidObject = bidfactory.createBid(1); - var i; - bidObject.bidderCode = 'eplanning'; - for (i in bid.ad) { - if (bid.ad.hasOwnProperty(i)) { - bidObject[i] = bid.ad[i]; - } - } - return bidObject; - } - - function _callBids(params) { - if (window.hbpb) { - window.hbpb.call(params); - } - } - - return { - callBids: _callBids - }; -} - -adaptermanager.registerBidAdapter(new EPlanningAdapter(), 'eplanning'); - -module.exports = EPlanningAdapter; diff --git a/modules/essensBidAdapter.js b/modules/essensBidAdapter.js deleted file mode 100644 index 1b4df4d1685..00000000000 --- a/modules/essensBidAdapter.js +++ /dev/null @@ -1,170 +0,0 @@ -const CONSTANTS = require('src/constants.json') -const utils = require('src/utils.js') -const bidfactory = require('src/bidfactory.js') -const bidmanager = require('src/bidmanager.js') -const adloader = require('src/adloader') -const Adapter = require('src/adapter.js').default -const adaptermanager = require('src/adaptermanager') - -// Essens Prebid Adapter -function EssensAdapter () { - let baseAdapter = new Adapter('essens') - - const ENDPOINT = 'bid.essrtb.com/bid/prebid_call' - - let receivedBidRequests = {} - - baseAdapter.callBids = function (bidRequest) { - if (!bidRequest) { - utils.logError('empty bid request received') - return - } - receivedBidRequests = bidRequest - - const bids = bidRequest.bids || [] - - const essensBids = bids - .filter(bid => isPlacementBidComplete(bid)) - .map(bid => { - let essensBid = {} - essensBid.impressionId = bid.bidId - essensBid.sizes = utils.parseSizesInput(bid.sizes) - essensBid.placementId = bid.params.placementId - - if (bid.params.dealId) { - essensBid.deal = bid.params.dealId - } - - if (bid.params.floorPrice) { - essensBid.floorPrice = bid.params.floorPrice - } - - return essensBid - }) - - const bidderRequestId = bidRequest.bidderRequestId - const cur = ['USD'] - const urlParam = utils.getTopWindowUrl() - const uaParam = getUa() - - if (!utils.isEmpty(essensBids)) { - const payloadJson = {bidderRequestId: bidderRequestId, cur: cur, url: urlParam, ua: uaParam, imp: essensBids} - - const scriptUrl = '//' + ENDPOINT + '?callback=$$PREBID_GLOBAL$$.essensResponseHandler' + - '&bid=' + encodeURIComponent(JSON.stringify(payloadJson)) - adloader.loadScript(scriptUrl) - } else { - sendEmptyResponseForAllPlacement() - } - - function isPlacementBidComplete (bid) { - if (bid.bidId && bid.params && bid.params.placementId) { - return true - } else { - utils.logError('bid requires missing essential params for essens') - } - } - - function getUa () { - return window.navigator.userAgent - } - } - - function sendEmptyResponseForAllPlacement () { - if (receivedBidRequests && receivedBidRequests.bids) { - receivedBidRequests.bids.forEach(registerEmptyResponse) - } - } - - function registerEmptyResponse (bidRequest) { - const bid = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, bidRequest) - bid.bidderCode = 'essens' - bidmanager.addBidResponse(bidRequest.placementCode, bid) - } - - $$PREBID_GLOBAL$$.essensResponseHandler = function (essensResponse) { - utils.logInfo('received bid request from Essens') - if (!isValidResponse(essensResponse)) { - sendEmptyResponseForAllPlacement() - return - } - - registerBids(essensResponse) - - function isValidResponse (essensResponse) { - return !!(essensResponse && essensResponse.id && essensResponse.seatbid) - } - - function registerBids (essensResponses) { - const requestHasResponse = [] - - if (essensResponses.seatbid.length > 0) { - essensResponses.seatbid.filter(isValidSeat).forEach( - seat => seat.bid.forEach(sendResponse)) - } - - receivedBidRequests.bids.filter(request => !hasResponse(request)) - .forEach(registerEmptyResponse) - - function sendResponse (bidCandidate) { - const bidRequest = getBidRequest(bidCandidate.impid) - - const bidsToBeRegister = getBid(bidRequest, bidCandidate) - - if (bidsToBeRegister) { - requestHasResponse.push(bidRequest) - bidmanager.addBidResponse(bidRequest.placementCode, bidsToBeRegister) - } - } - - function hasResponse (request) { - return utils.contains(requestHasResponse, request) - } - - function isValidSeat (seatbid) { - return ((seatbid.bid && seatbid.bid.length !== 0)) - } - - function getBidRequest (id) { - return receivedBidRequests.bids.find(bid => bid.bidId === id) - } - } - - function getBid (pbBidReq, bidCandidate) { - if (!validBid(bidCandidate)) { - return - } - const bid = bidfactory.createBid(CONSTANTS.STATUS.GOOD, pbBidReq) - - bid.creative_id = bidCandidate.crid - bid.adUrl = bidCandidate.ext.adUrl - bid.bidderCode = 'essens' - bid.cpm = parseFloat(bidCandidate.price) - bid.width = parseInt(bidCandidate.w) - bid.height = parseInt(bidCandidate.h) - - if (bidCandidate.dealid) { - bid.dealId = bidCandidate.dealid - } - return bid - } - - function validBid (bid) { - return !!((bid.price && - bid.crid && bid.ext && bid.ext.adUrl && - bid.w && - bid.h && - bid.impid)) - } - } - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - getBidderCode: baseAdapter.getBidderCode - }) -} - -adaptermanager.registerBidAdapter(new EssensAdapter(), 'essens') - -module.exports = EssensAdapter diff --git a/modules/featureforwardBidAdapter.js b/modules/featureforwardBidAdapter.js deleted file mode 100644 index 53a3a7c5a08..00000000000 --- a/modules/featureforwardBidAdapter.js +++ /dev/null @@ -1,92 +0,0 @@ -import {createBid} from 'src/bidfactory'; -import {addBidResponse} from 'src/bidmanager'; -import {registerBidAdapter} from 'src/adaptermanager'; -import {logError, getTopWindowLocation} from 'src/utils'; -import {ajax} from 'src/ajax'; -import {STATUS} from 'src/constants'; - -function FeatureForwardAdapter() { - const bidUrl = window.location.protocol + '//prmbdr.featureforward.com/newbidder/bidder1_prm.php?'; - const ajaxOptions = { - method: 'POST', - withCredentials: true, - contentType: 'text/plain' - }; - - function _callBids(bidderRequest) { - bidderRequest.bids.forEach(bidRequest => { - var i = 0; - try { - while (bidRequest.sizes[i] !== undefined) { - var params = Object.assign({}, environment(), bidRequest.params, {'size': bidRequest.sizes[i]}); - var postRequest = JSON.stringify(params); - var url = bidUrl; - i++; - ajax(url, (bidResponse) => { - bidResponseAvailable(bidRequest, bidResponse); - }, postRequest, ajaxOptions); - } - } catch (e) { - // register passback on any exceptions while attempting to fetch response. - logError('featureforward.requestBid', 'ERROR', e); - bidResponseAvailable(bidRequest); - } - }); - } - - function environment() { - return { - ca: 'BID', - 'if': 0, - url: getTopWindowLocation().href, - refurl: referrer(), - ew: document.documentElement.clientWidth, - eh: document.documentElement.clientHeight, - ln: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage) - }; - } - - function referrer() { - try { - return window.top.document.referrer; - } catch (e) { - return document.referrer; - } - } - - function bidResponseAvailable(bidRequest, rawResponse) { - if (rawResponse) { - var bidResponse = parse(rawResponse); - if (bidResponse) { - var bid = createBid(STATUS.GOOD, bidRequest); - bid.bidderCode = bidRequest.bidder; - bid.cpm = bidResponse.bidCpm; - bid.ad = bidResponse.html; - bid.width = bidResponse.width; - bid.height = bidResponse.height; - addBidResponse(bidRequest.placementCode, bid); - return; - } - } - var passback = createBid(STATUS.NO_BID, bidRequest); - passback.bidderCode = bidRequest.bidder; - addBidResponse(bidRequest.placementCode, passback); - } - - function parse(rawResponse) { - try { - return JSON.parse(rawResponse); - } catch (ex) { - logError('featureforward.safeParse', 'ERROR', ex); - return null; - } - } - - return { - callBids: _callBids - }; -} - -registerBidAdapter(new FeatureForwardAdapter(), 'featureforward'); - -module.exports = FeatureForwardAdapter; diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js deleted file mode 100644 index 521dfabfb2d..00000000000 --- a/modules/gumgumBidAdapter.js +++ /dev/null @@ -1,176 +0,0 @@ -const bidfactory = require('src/bidfactory'); -const bidmanager = require('src/bidmanager'); -const utils = require('src/utils'); -const adloader = require('src/adloader'); -var adaptermanager = require('src/adaptermanager'); - -const BIDDER_CODE = 'gumgum'; -const CALLBACKS = {}; - -const GumgumAdapter = function GumgumAdapter() { - const bidEndpoint = `https://g2.gumgum.com/hbid/imp`; - - let topWindow; - let topScreen; - let pageViewId; - const requestCache = {}; - const throttleTable = {}; - const defaultThrottle = 3e4; - const dtCredentials = { member: 'YcXr87z2lpbB' }; - - try { - topWindow = global.top; - topScreen = topWindow.screen; - } catch (error) { - return utils.logError(error); - } - - function _getTimeStamp() { - return new Date().getTime(); - } - - function _getDigiTrustQueryParams() { - function getDigiTrustId () { - var digiTrustUser = (window.DigiTrust && window.DigiTrust.getUser) ? window.DigiTrust.getUser(dtCredentials) : {}; - return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || ''; - }; - - let digiTrustId = getDigiTrustId(); - // Verify there is an ID and this user has not opted out - if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { - return {}; - } - return { - 'dt': digiTrustId.id - }; - } - - function _callBids({ bids }) { - const browserParams = { - vw: topWindow.innerWidth, - vh: topWindow.innerHeight, - sw: topScreen.width, - sh: topScreen.height, - pu: topWindow.location.href, - ce: navigator.cookieEnabled, - dpr: topWindow.devicePixelRatio || 1 - }; - - utils._each(bids, bidRequest => { - const { bidId - , params = {} - , placementCode - } = bidRequest; - const timestamp = _getTimeStamp(); - const trackingId = params.inScreen; - const nativeId = params['native']; - const slotId = params.inSlot; - const bid = { tmax: $$PREBID_GLOBAL$$.cbTimeout }; - - /* slot/native ads need the placement id */ - switch (true) { - case !!(params.inImage): bid.pi = 1; break; - case !!(params.inScreen): bid.pi = 2; break; - case !!(params.inSlot): bid.pi = 3; break; - case !!(params['native']): bid.pi = 5; break; - default: return utils.logWarn( - `[GumGum] No product selected for the placement ${placementCode}` + - ', please check your implementation.' - ); - } - - /* throttle based on the latest request for this product */ - const productId = bid.pi; - const requestKey = productId + '|' + placementCode; - const throttle = throttleTable[productId]; - const latestRequest = requestCache[requestKey]; - if (latestRequest && throttle && (timestamp - latestRequest) < throttle) { - return utils.logWarn( - `[GumGum] The refreshes for "${placementCode}" with the params ` + - `${JSON.stringify(params)} should be at least ${throttle / 1e3}s apart.` - ); - } - /* update the last request */ - requestCache[requestKey] = timestamp; - - /* tracking id is required for in-image and in-screen */ - if (trackingId) bid.t = trackingId; - /* native ads require a native placement id */ - if (nativeId) bid.ni = nativeId; - /* slot ads require a slot id */ - if (slotId) bid.si = slotId; - - /* include the pageViewId, if any */ - if (pageViewId) bid.pv = pageViewId; - - const cachedBid = Object.assign({ - placementCode, - id: bidId - }, bid); - - const callback = { jsonp: `$$PREBID_GLOBAL$$.handleGumGumCB['${bidId}']` }; - CALLBACKS[bidId] = _handleGumGumResponse(cachedBid); - const query = Object.assign(callback, browserParams, bid, _getDigiTrustQueryParams()); - const bidCall = `${bidEndpoint}?${utils.parseQueryStringParameters(query)}`; - adloader.loadScript(bidCall); - }); - } - - const _handleGumGumResponse = cachedBidRequest => (bidResponse = {}) => { - const { pi: productId - } = cachedBidRequest; - const { ad = {} - , pag = {} - , thms: throttle - } = bidResponse; - /* cache the pageViewId */ - if (pag && pag.pvid) pageViewId = pag.pvid; - if (ad && ad.id) { - /* set the new throttle */ - throttleTable[productId] = throttle || defaultThrottle; - /* create the bid */ - const bid = bidfactory.createBid(1); - const { t: trackingId - } = pag; - bidResponse.request = cachedBidRequest; - const encodedResponse = encodeURIComponent(JSON.stringify(bidResponse)); - const gumgumAdLoader = ``; - Object.assign(bid, { - cpm: ad.price, - ad: gumgumAdLoader, - width: ad.width, - height: ad.height, - bidderCode: BIDDER_CODE - }); - bidmanager.addBidResponse(cachedBidRequest.placementCode, bid); - } else { - const noBid = bidfactory.createBid(2); - noBid.bidderCode = BIDDER_CODE; - bidmanager.addBidResponse(cachedBidRequest.placementCode, noBid); - } - delete CALLBACKS[cachedBidRequest.id]; - }; - - window.$$PREBID_GLOBAL$$.handleGumGumCB = CALLBACKS; - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new GumgumAdapter(), 'gumgum'); - -module.exports = GumgumAdapter; diff --git a/modules/hiromediaBidAdapter.js b/modules/hiromediaBidAdapter.js deleted file mode 100644 index f99b3553dfc..00000000000 --- a/modules/hiromediaBidAdapter.js +++ /dev/null @@ -1,374 +0,0 @@ -/** - * Adapter for HIRO Media - * - * @module HiroMediaAdapter - * - * @requires src/ajax - * @requires src/bidfactory - * @requires src/bidmanager - * @requires src/constants - * @requires src/utils - */ -var Ajax = require('src/ajax'); -var bidfactory = require('src/bidfactory'); -var bidmanager = require('src/bidmanager'); -var utils = require('src/utils'); -var STATUS = require('src/constants').STATUS; -var adaptermanager = require('src/adaptermanager'); - -var HiroMediaAdapter = function HiroMediaAdapter() { - 'use strict'; - - /** - * Bidder code - * - * @memberof module:HiroMediaAdapter~ - * @constant {string} - * @private - */ - var BIDDER_CODE = 'hiromedia'; - - /** - * Adapter version - * - * @memberof module:HiroMediaAdapter~ - * @constant {number} - * @private - */ - var ADAPTER_VERSION = 3; - - /** - * Default bid param values - * - * @memberof module:HiroMediaAdapter~ - * @constant {array.} - * @private - */ - var REQUIRED_BID_PARAMS = ['accountId']; - - /** - * Default bid param values - * - * @memberof module:HiroMediaAdapter~ - * @constant {module:HiroMediaAdapter~bidParams} - * @private - */ - var DEFAULT_BID_PARAMS = { - bidUrl: 'https://hb-rtb.ktdpublishers.com/bid/get' - }; - - /** - * Returns true if the given value is `undefined` - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @param {*} value value to check - * @return {boolean} true if the given value is `undefined`, false otherwise - */ - function isUndefined(value) { - return typeof value === 'undefined'; - } - - /** - * Call bidmanager.addBidResponse - * - * Simple wrapper that will create a bid object with the correct status - * and add the response for the placement. - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @param {object} bid bid object connected to the response - * @param {object|boolean} [bidResponse] response object for bid, if not - * set the response will be an empty bid response. - */ - function addBidResponse(bid, bidResponse) { - var placementCode = bid.placementCode; - var bidStatus = bidResponse ? STATUS.GOOD : STATUS.NO_BID; - var bidObject = bidfactory.createBid(bidStatus, bid); - - bidObject.bidderCode = BIDDER_CODE; - - if (bidResponse) { - bidObject.cpm = bidResponse.cpm; - bidObject.ad = bidResponse.ad; - bidObject.width = bidResponse.width; - bidObject.height = bidResponse.height; - } - - utils.logMessage('hiromedia.callBids, addBidResponse for ' + placementCode + ' status: ' + bidStatus); - bidmanager.addBidResponse(placementCode, bidObject); - } - - /** - * Return `true` if sampling is larger than a newly created random value - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @param {number} sampling the value to check - * @return {boolean} `true` if the sampling is larger, `false` otherwise - */ - function checkChance(sampling) { - return Math.random() < sampling; - } - - /** - * Apply a response for all pending bids that have the same response batch key - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @param {object} response bid response object - * @param {object} bid bid object connected to response - */ - function handleResponse(response, bid) { - // Sample the bid responses according to `response.chance`, - // if `response.chance` is not provided, sample at 100%. - if (isUndefined(response.chance) || checkChance(response.chance)) { - addBidResponse(bid, response); - } else { - addBidResponse(bid, false); - } - } - - /** - * Find browser name and version - * - * Super basic UA parser for the major browser configurations. - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @return {module:HiroMediaAdapter~browserInfo} object containing name and version of browser - * or empty strings. - */ - function getBrowser() { - var ua = navigator.userAgent; - var browsers = [{ - name: 'Mobile', - stringSearch: 'Mobi' - }, { - name: 'Edge' - }, { - name: 'Chrome' - }, { - name: 'Firefox' - }, { - name: 'IE', - versionSearch: /MSIE\s(\d+)/ - }, { - name: 'IE', - stringSearch: 'Trident', - versionSearch: /rv:(\d+)/ - }]; - - var name = ''; - var version = ''; - - browsers.some(function (browser) { - var nameSearch = browser.stringSearch || browser.name; - var defaultVersionSearch = nameSearch + '\\/(\\d+)'; - var versionSearch = browser.versionSearch || defaultVersionSearch; - var versionMatch; - - if (ua.indexOf(nameSearch) !== -1) { - name = browser.name; - versionMatch = ua.match(versionSearch); - if (versionMatch) { - version = versionMatch && versionMatch[1]; - } - return true; - } - }); - - return { - name: name, - version: version - }; - } - - /** - * Return top context domain - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @return {string} domain of top context url. - */ - function getDomain() { - var a = document.createElement('a'); - a.href = utils.getTopWindowUrl(); - return a.hostname; - } - - /** - * Apply default parameters to an object if the parameters are not set - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @param {module:HiroMediaAdapter~bidParams} bidParams custom parameters for bid - * @return {module:HiroMediaAdapter~bidParams} `bidParams` shallow merged with - * {@linkcode module:HiroMediaAdapter~DEFAULT_BID_PARAMS|DEFAULT_BID_PARAMS} - */ - function defaultParams(bidParams) { - return Object.assign({}, DEFAULT_BID_PARAMS, bidParams); - } - - /** - * Build a {@linkcode module:HiroMediaAdapter~bidInfo|bidInfo} object based on a - * bid sent to {@linkcode module:HiroMediaAdapter#callBids|callBids} - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @param {object} bid bid from `Prebid.js` - * @return {module:HiroMediaAdapter~bidInfo} information for bid request - */ - function processBid(bid) { - var sizes = utils.parseSizesInput(bid.sizes); - var bidParams = defaultParams(bid.params); - var hasValidBidRequest = utils.hasValidBidRequest(bidParams, REQUIRED_BID_PARAMS, BIDDER_CODE); - var shouldBid = hasValidBidRequest; - var bidInfo = { - bidParams: bidParams, - shouldBid: shouldBid, - selectedSize: sizes[0], - additionalSizes: sizes.slice(1).join(',') - }; - - return bidInfo; - } - - /** - * Wrapper around `JSON.parse()` that returns false on error - * - * @memberof module:HiroMediaAdapter~ - * @private - * - * @param {string} text potential JSON string to convert to object - * @return {object|boolean} object parsed from text or `false` in case of and error - */ - function tryJson(text) { - var object = false; - - try { - object = JSON.parse(text); - } catch (ignore) { - // Ignored - } - - return object; - } - - /** - * Receive a set of bid placements and create bid requests and responses accordingly - * - * @alias module:HiroMediaAdapter#callBids - * - * @param {object} params placement and bid data from `Prebid.js` - */ - function _callBids(params) { - var browser = getBrowser(); - var domain = getDomain(); - var bids = params && params.bids; - var ajaxOptions = { - method: 'GET', - withCredentials: true - }; - - // Fixed data, shared by all requests - var fixedRequest = { - adapterVersion: ADAPTER_VERSION, - browser: browser.name, - browserVersion: browser.version, - domain: domain - }; - - utils.logMessage('hiromedia.callBids'); - - if (bids && bids.length) { - bids.forEach(function (bid) { - var bidInfo = processBid(bid); - var bidParams = bidInfo.bidParams; - utils.logMessage('hiromedia.callBids, bidInfo ' + bid.placementCode + ' ' + bidInfo.shouldBid); - if (bidInfo.shouldBid) { - var url = bidParams.bidUrl; - var requestParams = Object.assign({}, fixedRequest, bidInfo.bidParams, { - placementCode: bid.placementCode, - selectedSize: bidInfo.selectedSize, - additionalSizes: bidInfo.additionalSizes - }); - - Object.keys(requestParams).forEach(function (key) { - if (requestParams[key] === '' || isUndefined(requestParams[key])) { - delete requestParams[key]; - } - }); - - utils.logMessage('hiromedia.callBids, bid request ' + url + ' ' + JSON.stringify(bidInfo.bidRequest)); - - Ajax.ajax(url, { - - success: function(responseText) { - var response = tryJson(responseText); - handleResponse(response, bid); - }, - - error: function(err, xhr) { - utils.logError('hiromedia.callBids, bid request error', xhr.status, err); - addBidResponse(bid, false); - } - - }, requestParams, ajaxOptions); - } else { - // No bid - addBidResponse(bid, false); - } - }); - } - } - - return { - callBids: _callBids - }; - - // JSDoc typedefs - - /** - * Parameters for bids to HIRO Media adapter - * - * @typedef {object} module:HiroMediaAdapter~bidParams - * @private - * - * @property {string} bidUrl the bid server endpoint url - */ - - /** - * Bid object wrapper - * - * @typedef {object} module:HiroMediaAdapter~bidInfo - * @private - * - * @property {string} selectedSize the first size in the the placement sizes array - * @property {string} additionalSizes list of sizes in the placement sizes array besides the first - * @property {module:HiroMediaAdapter~bidParams} bidParams original params passed for bid in #callBids - * @property {boolean} shouldBid flag to determine if the bid is valid for bidding or not - */ - - /** - * browserInfo - * - * @typedef {object} module:HiroMediaAdapter~browserInfo - * @private - * - * @property {string} name browser name (e.g. `'Chrome'` or `'Firefox'`) - * @property {string} version browser major version (e.g. `'53'`) - */ -}; - -adaptermanager.registerBidAdapter(new HiroMediaAdapter(), 'hiromedia'); - -module.exports = HiroMediaAdapter; diff --git a/modules/imonomyBidAdapter.js b/modules/imonomyBidAdapter.js deleted file mode 100644 index 7026c28ba6d..00000000000 --- a/modules/imonomyBidAdapter.js +++ /dev/null @@ -1,185 +0,0 @@ -/* imonomy.js v3.1.0 -Updated : 2017-03-15 */ - -var utils = require('src/utils.js'); -var adloader = require('src/adloader.js'); -var bidmanager = require('src/bidmanager.js'); -var bidfactory = require('src/bidfactory.js'); -const adaptermanager = require('src/adaptermanager'); -var STATUSCODES = require('src/constants.json').STATUS; - -function ImonomyAdapter() { - return { - callBids: _callBids - }; - - function _callBids(params) { - var request = []; - var siteRef = ''; - var screen_w = ''; - var screen_h = ''; - var language = ''; - var pxr = ''; - var keywords = ''; - var connectiontype = ''; - var domain = ''; - var page = ''; - var bid, i, l; - var bids = params.bids; - var imonomy_domain = 'b.imonomy.com'; - var callbackName = '_hb_' + utils.getUniqueIdentifierStr(); - - try { siteRef = document.referrer } catch (e) { } - try { domain = window.location.host } catch (e) { } - try { pxr = window.devicePixelRatio } catch (e) { } - try { screen_w = screen.width || document.body.clientWidth || 0 } catch (e) { } - try { screen_h = screen.height || document.body.clientHeight || 0 } catch (e) { } - try { page = window.location.pathname + location.search + location.hash } catch (e) { } - - try { - var meta = document.getElementsByTagName('meta') || {}; - keywords = ('keywords' in meta) ? meta['keywords'].content : '' - } catch (e) {} - - try { - var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection; - connectiontype = (connection != undefined) ? connection.type : ''; - } catch (e) {} - - try { - var language_tmp = document.documentElement.lang || navigator.language || navigator.userLanguage || ''; - language = language_tmp.split('-')[0] - } catch (e) {} - - try { - var data = { - pxr: pxr, - page: page, - domain: domain, - siteRef: siteRef, - screen_w: screen_w, - screen_h: screen_h, - language: language, - keywords: keywords, - connectiontype: connectiontype, - requestId: params['requestId'], - bidderRequestId: params['bidderRequestId'], - callback: '$$PREBID_GLOBAL$$.' + callbackName, - publisher_id: params['bids'][0]['params']['publisher_id'], - bids: encodeURIComponent(JSON.stringify(params['bids'])) - }; - - var protocol = (document.location.protocol === 'https:') ? 'https' : 'http'; - request.unshift(protocol + '://' + imonomy_domain + '/openrtb/hb/' + params['bids'][0]['params']['publisher_id'] + '?id=' + utils.getUniqueIdentifierStr()); - - for (var key in data) { - if (data.hasOwnProperty(key)) { - request.push(key + '=' + encodeURIComponent(data[key])); - } - } - - for (i = 0, l = bids.length; i < l; i++) { - bid = bids[i]; - request.push(formRequestUrl(bid.params)); - } - - $$PREBID_GLOBAL$$[callbackName] = handleCallback(bids); - - adloader.loadScript(request.join('&')); - } catch (e) { - } - } - - function formRequestUrl(reqData) { - var key; - var url = []; - - for (key in reqData) { - if (reqData.hasOwnProperty(key) && reqData[key]) { - url.push(key, '=', reqData[key], '&'); - } - } - - return btoa(url.join('').slice(0, -1)); - } - - function handleCallback(bids) { - return function handleResponse(adItems) { - try { - var bidObject; - var bidder = 'imonomy'; - var adItem; - var bid; - - try { - if (adItems.um_list) { - _processUserMatchings(adItems.um_list); - } - } catch (e) { } - - adItems = adItems.ads; - - for (var i = 0, l = bids.length; i < l; i++) { - bid = bids[i]; - adItem = getAdItem(adItems, bids[i].bidId); - - if (adItem) { - bidObject = bidfactory.createBid(STATUSCODES.GOOD, bid); - bidObject.bidderCode = bidder; - bidObject.ad = adItem.ad; - bidObject.cpm = adItem.cpm; - bidObject.cur = adItem.cur; - bidObject.width = adItem.width; - bidObject.height = adItem.height; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } else { - bidObject = bidfactory.createBid(STATUSCODES.NO_BID, bid); - bidObject.bidderCode = bidder; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } - } - } catch (e) { - } - }; - } - - function _processUserMatchings(userMatchings) { - var headElem = document.getElementsByTagName('head')[0]; - var createdElem; - - utils._each(userMatchings, function (userMatching) { - createdElem = undefined; - switch (userMatching.type) { - case 'redirect': - createdElem = document.createElement('img'); - break; - case 'iframe': - createdElem = utils.createInvisibleIframe(); - break; - case 'js': - createdElem = document.createElement('script'); - createdElem.type = 'text/javascript'; - createdElem.async = true; - break; - } - if (createdElem) { - createdElem.src = decodeURIComponent(userMatching.Url); - headElem.insertBefore(createdElem, headElem.firstChild); - } - }); - } - - function getAdItem(adItems, imp) { - adItems = adItems || [] - for (var i = 0, l = adItems.length; i < l; i++) { - if (adItems[i].impression_id == imp) { - return adItems[i]; - } - } - - return null; - } -} - -adaptermanager.registerBidAdapter(new ImonomyAdapter(), 'imonomy'); -module.exports = ImonomyAdapter; diff --git a/modules/indexExchangeBidAdapter.js b/modules/indexExchangeBidAdapter.js deleted file mode 100644 index 3ecabf649e0..00000000000 --- a/modules/indexExchangeBidAdapter.js +++ /dev/null @@ -1,1132 +0,0 @@ -// Factory for creating the bidderAdaptor -// jshint ignore:start -import Adapter from 'src/adapter'; -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import * as utils from 'src/utils'; -import { STATUS } from 'src/constants'; -import * as url from 'src/url'; -import adloader from 'src/adloader'; -import adaptermanager from 'src/adaptermanager'; - -var ADAPTER_NAME = 'INDEXEXCHANGE'; -var ADAPTER_CODE = 'indexExchange'; - -var CONSTANTS = { - 'INDEX_DEBUG_MODE': { - 'queryParam': 'pbjs_ix_debug', - 'mode': { - 'sandbox': { - 'topFrameLimit': 10, - 'queryValue': 'sandbox', - 'siteID': '999990' - } - } - } -}; - -var OPEN_MARKET = 'IOM'; -var PRIVATE_MARKET = 'IPM'; - -const VIDEO_REQUIRED_PARAMS_MAP = { - siteID: true, - playerType: true, - protocols: true, - maxduration: true -}; -const VIDEO_OPTIONAL_PARAMS_MAP = { - minduration: 0, - startdelay: 'preroll', - linearity: 'linear', - mimes: [], - allowVPAID: true, - apiList: [] -}; -const SUPPORTED_PLAYER_TYPES_MAP = { - HTML5: true, - FLASH: true -}; -const SUPPORTED_PROTOCOLS_MAP = { - 'VAST2': [2, 5], - 'VAST3': [3, 6] -}; -const SUPPORTED_API_MAP = { - FLASH: [1, 2], - HTML5: [2] -}; -const LINEARITY_MAP = { - linear: 1, - nonlinear: 2 -}; -const START_DELAY_MAP = { - preroll: 0, - midroll: -1, - postroll: -2 -}; -const SLOT_ID_PREFIX_MAP = { - preroll: 'pr', - midroll: 'm', - postroll: 'po' -}; -const DEFAULT_MIMES_MAP = { - FLASH: ['video/mp4', 'video/x-flv'], - HTML5: ['video/mp4', 'video/webm'] -}; -const DEFAULT_VPAID_MIMES_MAP = { - FLASH: ['application/x-shockwave-flash'], - 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`; - -window.cygnus_index_parse_res = function(response) { - try { - if (response) { - if (typeof _IndexRequestData !== 'object' || typeof _IndexRequestData.impIDToSlotID !== 'object' || typeof _IndexRequestData.impIDToSlotID[response.id] === 'undefined') { - return; - } - var targetMode = 1; - var callbackFn; - if (typeof _IndexRequestData.reqOptions === 'object' && typeof _IndexRequestData.reqOptions[response.id] === 'object') { - if (typeof _IndexRequestData.reqOptions[response.id].callback === 'function') { - callbackFn = _IndexRequestData.reqOptions[response.id].callback; - } - if (typeof _IndexRequestData.reqOptions[response.id].targetMode === 'number') { - targetMode = _IndexRequestData.reqOptions[response.id].targetMode; - } - } - - _IndexRequestData.lastRequestID = response.id; - _IndexRequestData.targetIDToBid = {}; - _IndexRequestData.targetIDToResp = {}; - _IndexRequestData.targetIDToCreative = {}; - - var allBids = []; - var seatbidLength = typeof response.seatbid === 'undefined' ? 0 : response.seatbid.length; - for (var i = 0; i < seatbidLength; i++) { - for (var j = 0; j < response.seatbid[i].bid.length; j++) { - var bid = response.seatbid[i].bid[j]; - if (typeof bid.ext !== 'object' || typeof bid.ext.pricelevel !== 'string') { - continue; - } - if (typeof _IndexRequestData.impIDToSlotID[response.id][bid.impid] === 'undefined') { - continue; - } - var slotID = _IndexRequestData.impIDToSlotID[response.id][bid.impid]; - var targetID; - var noTargetModeTargetID; - var targetPrefix; - if (typeof bid.ext.dealid === 'string') { - if (targetMode === 1) { - targetID = slotID + bid.ext.pricelevel; - } else { - targetID = slotID + '_' + bid.ext.dealid; - } - noTargetModeTargetID = slotID + '_' + bid.ext.dealid; - targetPrefix = PRIVATE_MARKET + '_'; - } else { - targetID = slotID + bid.ext.pricelevel; - noTargetModeTargetID = slotID + bid.ext.pricelevel; - targetPrefix = OPEN_MARKET + '_'; - } - if (_IndexRequestData.targetIDToBid[targetID] === undefined) { - _IndexRequestData.targetIDToBid[targetID] = [bid.adm]; - } else { - _IndexRequestData.targetIDToBid[targetID].push(bid.adm); - } - if (_IndexRequestData.targetIDToCreative[noTargetModeTargetID] === undefined) { - _IndexRequestData.targetIDToCreative[noTargetModeTargetID] = [bid.adm]; - } else { - _IndexRequestData.targetIDToCreative[noTargetModeTargetID].push(bid.adm); - } - var impBid = {}; - impBid.impressionID = bid.impid; - if (typeof bid.ext.dealid !== 'undefined') { - impBid.dealID = bid.ext.dealid; - } - impBid.bid = bid.price; - impBid.slotID = slotID; - impBid.priceLevel = bid.ext.pricelevel; - impBid.target = targetPrefix + targetID; - _IndexRequestData.targetIDToResp[targetID] = impBid; - allBids.push(impBid); - } - } - if (typeof callbackFn === 'function') { - if (allBids.length === 0) { - callbackFn(response.id); - } else { - callbackFn(response.id, allBids); - } - } - } - } catch (e) {} - - if (typeof window.cygnus_index_ready_state === 'function') { - window.cygnus_index_ready_state(); - } -} - -window.index_render = function(doc, targetID) { - try { - var ad = _IndexRequestData.targetIDToCreative[targetID].pop(); - if (ad != null) { - doc.write(ad); - } else { - var url = utils.getTopWindowLocation().protocol === 'http:' ? 'http://as.casalemedia.com' : 'https://as-sec.casalemedia.com'; - url += '/headerstats?type=RT&s=' + cygnus_index_args.siteID + '&u=' + encodeURIComponent(location.href) + '&r=' + _IndexRequestData.lastRequestID; - var px_call = new Image(); - px_call.src = url + '&blank=' + targetID; - } - } catch (e) {} -} - -window.headertag_render = function(doc, targetID, slotID) { - var index_slot = slotID; - var index_ary = targetID.split(','); - for (var i = 0; i < index_ary.length; i++) { - var unpack = index_ary[i].split('_'); - if (unpack[0] == index_slot) { - index_render(doc, index_ary[i]); - return; - } - } -} - -window.cygnus_index_args = {}; - -var cygnus_index_adunits = [[728, 90], [120, 600], [300, 250], [160, 600], [336, 280], [234, 60], [300, 600], [300, 50], [320, 50], [970, 250], [300, 1050], [970, 90], [180, 150]]; - -var getIndexDebugMode = function() { - return getParameterByName(CONSTANTS.INDEX_DEBUG_MODE.queryParam).toUpperCase(); -} - -var getParameterByName = function (name) { - var wdw = window; - var childsReferrer = ''; - for (var x = 0; x < CONSTANTS.INDEX_DEBUG_MODE.mode.sandbox.topFrameLimit; x++) { - if (wdw.parent == wdw) { - break; - } - try { - childsReferrer = wdw.document.referrer; - } catch (err) {} - wdw = wdw.parent; - } - var topURL = top === self ? location.href : childsReferrer; - var regexS = '[\\?&]' + name + '=([^&#]*)'; - var regex = new RegExp(regexS); - var results = regex.exec(topURL); - if (results === null) { - return ''; - } - return decodeURIComponent(results[1].replace(/\+/g, ' ')); -}; - -var cygnus_index_start = function () { - window.cygnus_index_args.parseFn = cygnus_index_parse_res; - var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; - var meta = { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"': '\\"', - '\\': '\\\\' - }; - - function escapeCharacter(character) { - var escaped = meta[character]; - if (typeof escaped === 'string') { - return escaped; - } else { - return '\\u' + ('0000' + character.charCodeAt(0).toString(16)).slice(-4); - } - } - - function quote(string) { - escapable.lastIndex = 0; - if (escapable.test(string)) { - return string.replace(escapable, escapeCharacter); - } else { - return string; - } - } - - function OpenRTBRequest(siteID, parseFn, timeoutDelay) { - this.initialized = false; - if (typeof siteID !== 'number' || siteID % 1 !== 0 || siteID < 0) { - throw 'Invalid Site ID'; - } - - timeoutDelay = Number(timeoutDelay); - if (typeof timeoutDelay === 'number' && timeoutDelay % 1 === 0 && timeoutDelay >= 0) { - this.timeoutDelay = timeoutDelay; - } - - this.siteID = siteID; - this.impressions = []; - this._parseFnName = undefined; - - // Get page URL - this.sitePage = undefined; - try { - this.sitePage = utils.getTopWindowUrl(); - } catch (e) {} - // Fallback to old logic if utils.getTopWindowUrl() fails to return site.page - if (typeof this.sitePage === 'undefined' || this.sitePage === '') { - if (top === self) { - this.sitePage = location.href; - } else { - this.sitePage = document.referrer; - } - } - - if (top === self) { - this.topframe = 1; - } else { - this.topframe = 0; - } - - if (typeof parseFn !== 'undefined') { - if (typeof parseFn === 'function') { - this._parseFnName = 'cygnus_index_args.parseFn'; - } else { - throw 'Invalid jsonp target function'; - } - } - - if (typeof _IndexRequestData.requestCounter === 'undefined') { - _IndexRequestData.requestCounter = Math.floor(Math.random() * 256); - } else { - _IndexRequestData.requestCounter = (_IndexRequestData.requestCounter + 1) % 256; - } - - this.requestID = String((new Date().getTime() % 2592000) * 256 + _IndexRequestData.requestCounter + 256); - this.initialized = true; - } - - OpenRTBRequest.prototype.serialize = function () { - var json = '{"id":"' + this.requestID + '","site":{"page":"' + quote(this.sitePage) + '"'; - if (typeof document.referrer === 'string' && document.referrer !== '') { - json += ',"ref":"' + quote(document.referrer) + '"'; - } - - json += '},"imp":['; - for (var i = 0; i < this.impressions.length; i++) { - var impObj = this.impressions[i]; - var ext = []; - json += '{"id":"' + impObj.id + '", "banner":{"w":' + impObj.w + ',"h":' + impObj.h + ',"topframe":' + String(this.topframe) + '}'; - if (typeof impObj.bidfloor === 'number') { - json += ',"bidfloor":' + impObj.bidfloor; - if (typeof impObj.bidfloorcur === 'string') { - json += ',"bidfloorcur":"' + quote(impObj.bidfloorcur) + '"'; - } - } - - if (typeof impObj.slotID === 'string' && (!impObj.slotID.match(/^\s*$/))) { - ext.push('"sid":"' + quote(impObj.slotID) + '"'); - } - - if (typeof impObj.siteID === 'number') { - ext.push('"siteID":' + impObj.siteID); - } - - if (ext.length > 0) { - json += ',"ext": {' + ext.join() + '}'; - } - - if (i + 1 === this.impressions.length) { - json += '}'; - } else { - json += '},'; - } - } - - json += ']}'; - return json; - }; - - OpenRTBRequest.prototype.setPageOverride = function (sitePageOverride) { - if (typeof sitePageOverride === 'string' && (!sitePageOverride.match(/^\s*$/))) { - this.sitePage = sitePageOverride; - return true; - } else { - return false; - } - }; - - OpenRTBRequest.prototype.addImpression = function (width, height, bidFloor, bidFloorCurrency, slotID, siteID) { - var impObj = { - id: String(this.impressions.length + 1) - }; - if (typeof width !== 'number' || width <= 1) { - return null; - } - - if (typeof height !== 'number' || height <= 1) { - return null; - } - - if ((typeof slotID === 'string' || typeof slotID === 'number') && String(slotID).length <= 50) { - impObj.slotID = String(slotID); - } - - impObj.w = width; - impObj.h = height; - if (bidFloor !== undefined && typeof bidFloor !== 'number') { - return null; - } - - if (typeof bidFloor === 'number') { - if (bidFloor < 0) { - return null; - } - - impObj.bidfloor = bidFloor; - if (bidFloorCurrency !== undefined && typeof bidFloorCurrency !== 'string') { - return null; - } - - impObj.bidfloorcur = bidFloorCurrency; - } - - if (typeof siteID !== 'undefined') { - if (typeof siteID === 'number' && siteID % 1 === 0 && siteID >= 0) { - impObj.siteID = siteID; - } else { - return null; - } - } - - this.impressions.push(impObj); - return impObj.id; - }; - - OpenRTBRequest.prototype.buildRequest = function () { - if (this.impressions.length === 0 || this.initialized !== true) { - return; - } - - var jsonURI = encodeURIComponent(this.serialize()); - - var scriptSrc; - if (getIndexDebugMode() == CONSTANTS.INDEX_DEBUG_MODE.mode.sandbox.queryValue.toUpperCase()) { - this.siteID = CONSTANTS.INDEX_DEBUG_MODE.mode.sandbox.siteID; - scriptSrc = utils.getTopWindowLocation().protocol === 'http:' ? 'http://sandbox.ht.indexexchange.com' : 'https://sandbox.ht.indexexchange.com'; - utils.logMessage('IX DEBUG: Sandbox mode activated'); - } else { - scriptSrc = utils.getTopWindowLocation().protocol === 'http:' ? 'http://as.casalemedia.com' : 'https://as-sec.casalemedia.com'; - } - var prebidVersion = encodeURIComponent('$prebid.version$'); - scriptSrc += '/cygnus?v=7&fn=cygnus_index_parse_res&s=' + this.siteID + '&r=' + jsonURI + '&pid=pb' + prebidVersion; - if (typeof this.timeoutDelay === 'number' && this.timeoutDelay % 1 === 0 && this.timeoutDelay >= 0) { - scriptSrc += '&t=' + this.timeoutDelay; - } - - return scriptSrc; - }; - - try { - if (typeof cygnus_index_args === 'undefined' || typeof cygnus_index_args.siteID === 'undefined' || typeof cygnus_index_args.slots === 'undefined') { - return; - } - - var req = new OpenRTBRequest(cygnus_index_args.siteID, cygnus_index_args.parseFn, cygnus_index_args.timeout); - if (cygnus_index_args.url && typeof cygnus_index_args.url === 'string') { - req.setPageOverride(cygnus_index_args.url); - } - - _IndexRequestData.impIDToSlotID[req.requestID] = {}; - _IndexRequestData.reqOptions[req.requestID] = {}; - var slotDef, impID; - - for (var i = 0; i < cygnus_index_args.slots.length; i++) { - slotDef = cygnus_index_args.slots[i]; - - impID = req.addImpression(slotDef.width, slotDef.height, slotDef.bidfloor, slotDef.bidfloorcur, slotDef.id, slotDef.siteID); - if (impID) { - _IndexRequestData.impIDToSlotID[req.requestID][impID] = String(slotDef.id); - } - } - - if (typeof cygnus_index_args.targetMode === 'number') { - _IndexRequestData.reqOptions[req.requestID].targetMode = cygnus_index_args.targetMode; - } - - if (typeof cygnus_index_args.callback === 'function') { - _IndexRequestData.reqOptions[req.requestID].callback = cygnus_index_args.callback; - } - - return req.buildRequest(); - } catch (e) { - utils.logError('Error calling index adapter', ADAPTER_NAME, e); - } -}; - -var IndexExchangeAdapter = function IndexExchangeAdapter() { - let baseAdapter = new Adapter('indexExchange'); - - var slotIdMap = {}; - var requiredParams = [ - /* 0 */ - 'id', - /* 1 */ - 'siteID' - ]; - var firstAdUnitCode = ''; - let bidRequests = {}; - - function passOnBid(adUnitCode) { - var bid = bidfactory.createBid(2); - bid.bidderCode = ADAPTER_CODE; - bidmanager.addBidResponse(adUnitCode, bid); - return bid; - } - - function _callBids(request) { - if (typeof request === 'undefined' || utils.isEmpty(request)) { - return; - } - - var bidArr = request.bids; - - if (typeof window._IndexRequestData === 'undefined') { - window._IndexRequestData = {}; - window._IndexRequestData.impIDToSlotID = {}; - window._IndexRequestData.reqOptions = {}; - } - // clear custom targets at the beginning of every request - _IndexRequestData.targetAggregate = {'open': {}, 'private': {}}; - - // Our standard is to always bid for all known slots. - cygnus_index_args.slots = []; - - var videoImpressions = []; - - // Grab the slot level data for cygnus_index_args - bidArr.forEach(bid => { - if (bid.mediaType === 'video') { - var impression = buildVideoImpressions(bid, bidRequests); - if (typeof impression !== 'undefined') { - videoImpressions.push(impression); - } - } else { - cygnus_index_init(bid); - } - }); - - if (videoImpressions.length > 0) { - sendVideoRequest(request.bidderRequestId, videoImpressions); - } - - if (cygnus_index_args.slots.length > 20) { - utils.logError('Too many unique sizes on slots, will use the first 20.', ADAPTER_NAME); - } - - if (cygnus_index_args.slots.length > 0) { - // bidmanager.setExpectedBidsCount(ADAPTER_CODE, expectedBids); - adloader.loadScript(cygnus_index_start()); - } - - var responded = false; - - // Handle response - window.cygnus_index_ready_state = function () { - if (responded) { - return; - } - responded = true; - - try { - var indexObj = _IndexRequestData.targetIDToBid; - - // Grab all the bids for each slot - for (var adSlotId in slotIdMap) { - var bidObj = slotIdMap[adSlotId]; - var adUnitCode = bidObj.placementCode; - - var bids = []; - - // Grab the bid for current slot - for (var cpmAndSlotId in indexObj) { - var match = /^(T\d_)?(.+)_(\d+)$/.exec(cpmAndSlotId); - // if parse fail, move to next bid - if (!(match)) { - utils.logError('Unable to parse ' + cpmAndSlotId + ', skipping slot', ADAPTER_NAME); - continue; - } - var tier = match[1] || ''; - var slotID = match[2]; - var currentCPM = match[3]; - - var slotObj = getSlotObj(cygnus_index_args, tier + slotID); - // Bid is for the current slot - if (slotID === adSlotId) { - var bid = bidfactory.createBid(1); - bid.cpm = currentCPM / 100; - bid.ad = indexObj[cpmAndSlotId][0]; - bid.bidderCode = ADAPTER_CODE; - bid.width = slotObj.width; - bid.height = slotObj.height; - bid.siteID = slotObj.siteID; - if (typeof _IndexRequestData.targetIDToResp === 'object' && typeof _IndexRequestData.targetIDToResp[cpmAndSlotId] === 'object' && typeof _IndexRequestData.targetIDToResp[cpmAndSlotId].dealID !== 'undefined') { - if (typeof _IndexRequestData.targetAggregate['private'][adUnitCode] === 'undefined') { _IndexRequestData.targetAggregate['private'][adUnitCode] = []; } - bid.dealId = _IndexRequestData.targetIDToResp[cpmAndSlotId].dealID; - _IndexRequestData.targetAggregate['private'][adUnitCode].push(slotID + '_' + _IndexRequestData.targetIDToResp[cpmAndSlotId].dealID); - } else { - if (typeof _IndexRequestData.targetAggregate['open'][adUnitCode] === 'undefined') { _IndexRequestData.targetAggregate['open'][adUnitCode] = []; } - _IndexRequestData.targetAggregate['open'][adUnitCode].push(slotID + '_' + currentCPM); - } - bids.push(bid); - } - } - - if (bids.length > 0) { - // Add all bid responses - for (var i = 0; i < bids.length; i++) { - bidmanager.addBidResponse(adUnitCode, bids[i]); - } - // No bids for expected bid, pass bid - } else { - passOnBid(adUnitCode); - } - } - } catch (e) { - utils.logError('Error calling index adapter', ADAPTER_NAME, e); - logErrorBidResponse(); - } finally { - // ensure that previous targeting mapping is cleared - _IndexRequestData.targetIDToBid = {}; - } - - // slotIdMap is used to determine which slots will be bid on in a given request. - // Therefore it needs to be blanked after the request is handled, else we will submit 'bids' for the wrong ads. - slotIdMap = {}; - }; - } - - function cygnus_index_init(bid) { - if (!utils.hasValidBidRequest(bid.params, requiredParams, ADAPTER_NAME)) { - passOnBid(bid.placementCode); - return; - } - - var sizeID = 0; - - // Expecting nested arrays for sizes - if (!utils.isArray(bid.sizes[0])) { - bid.sizes = [bid.sizes]; - } - - // Create index slots for all bids and sizes - for (var j = 0; j < bid.sizes.length; j++) { - var validSize = false; - for (var k = 0; k < cygnus_index_adunits.length; k++) { - if (bid.sizes[j][0] == cygnus_index_adunits[k][0] && - bid.sizes[j][1] == cygnus_index_adunits[k][1]) { - bid.sizes[j][0] = Number(bid.sizes[j][0]); - bid.sizes[j][1] = Number(bid.sizes[j][1]); - validSize = true; - break; - } - } - - if (!validSize) { - utils.logMessage(ADAPTER_NAME + ' slot excluded from request due to no valid sizes'); - passOnBid(bid.placementCode); - continue; - } - - var usingSizeSpecificSiteID = false; - // Check for size defined in bidder params - if (bid.params.size && utils.isArray(bid.params.size)) { - if (!(bid.sizes[j][0] == bid.params.size[0] && bid.sizes[j][1] == bid.params.size[1])) { - passOnBid(bid.placementCode); - continue; - } - usingSizeSpecificSiteID = true; - } - - if (bid.params.timeout && typeof cygnus_index_args.timeout === 'undefined') { - cygnus_index_args.timeout = bid.params.timeout; - } - - var siteID = Number(bid.params.siteID); - if (typeof siteID !== 'number' || siteID % 1 != 0 || siteID <= 0) { - utils.logMessage(ADAPTER_NAME + ' slot excluded from request due to invalid siteID'); - passOnBid(bid.placementCode); - continue; - } - if (siteID && typeof cygnus_index_args.siteID === 'undefined') { - cygnus_index_args.siteID = siteID; - } - - if (utils.hasValidBidRequest(bid.params, requiredParams, ADAPTER_NAME)) { - firstAdUnitCode = bid.placementCode; - var slotID = bid.params[requiredParams[0]]; - if (typeof slotID !== 'string' && typeof slotID !== 'number') { - utils.logError(ADAPTER_NAME + ' bid contains invalid slot ID from ' + bid.placementCode + '. Discarding slot'); - passOnBid(bid.placementCode); - continue - } - - sizeID++; - var size = { - width: bid.sizes[j][0], - height: bid.sizes[j][1] - }; - - var slotName = usingSizeSpecificSiteID ? String(slotID) : slotID + '_' + sizeID; - slotIdMap[slotName] = bid; - - // Doesn't need the if(primary_request) conditional since we are using the mergeSlotInto function which is safe - cygnus_index_args.slots = mergeSlotInto({ - id: slotName, - width: size.width, - height: size.height, - siteID: siteID || cygnus_index_args.siteID - }, cygnus_index_args.slots); - - if (bid.params.tier2SiteID) { - var tier2SiteID = Number(bid.params.tier2SiteID); - if (typeof tier2SiteID !== 'undefined' && !tier2SiteID) { - continue; - } - - cygnus_index_args.slots = mergeSlotInto({ - id: 'T1_' + slotName, - width: size.width, - height: size.height, - siteID: tier2SiteID - }, cygnus_index_args.slots); - } - - if (bid.params.tier3SiteID) { - var tier3SiteID = Number(bid.params.tier3SiteID); - if (typeof tier3SiteID !== 'undefined' && !tier3SiteID) { - continue; - } - - cygnus_index_args.slots = mergeSlotInto({ - id: 'T2_' + slotName, - width: size.width, - height: size.height, - siteID: tier3SiteID - }, cygnus_index_args.slots); - } - } - } - } - - function sendVideoRequest(requestID, videoImpressions) { - let cygnusRequest = { - 'id': requestID, - 'imp': videoImpressions, - 'site': { - 'page': utils.getTopWindowUrl() - } - }; - - if (!utils.isEmpty(cygnusRequest.imp)) { - let cygnusRequestUrl = createCygnusRequest(cygnusRequest.imp[0].ext.siteID, cygnusRequest); - - adloader.loadScript(cygnusRequestUrl); - } - } - - function buildVideoImpressions(bid) { - if (!validateBid(bid)) { - return; - } - - bid = transformBid(bid); - - // map request id to bid object to retrieve adUnit code in callback - bidRequests[bid.bidId] = {}; - bidRequests[bid.bidId].prebid = bid; - - let cygnusImpression = {}; - cygnusImpression.id = bid.bidId; - - cygnusImpression.ext = {}; - cygnusImpression.ext.siteID = bid.params.video.siteID; - delete bid.params.video.siteID; - - let podType = bid.params.video.startdelay; - if (bid.params.video.startdelay === 0) { - podType = 'preroll'; - } else if (typeof START_DELAY_MAP[bid.params.video.startdelay] === 'undefined') { - podType = 'midroll'; - } - cygnusImpression.ext.sid = [SLOT_ID_PREFIX_MAP[podType], 1, 1, 's'].join('_'); - - cygnusImpression.video = {}; - - if (bid.params.video) { - Object.keys(bid.params.video) - .filter(param => typeof VIDEO_REQUIRED_PARAMS_MAP[param] !== 'undefined' || typeof VIDEO_OPTIONAL_PARAMS_MAP[param] !== 'undefined') - .forEach(param => { - if (param === 'startdelay' && typeof START_DELAY_MAP[bid.params.video[param]] !== 'undefined') { - bid.params.video[param] = START_DELAY_MAP[bid.params.video[param]]; - } - if (param === 'linearity' && typeof LINEARITY_MAP[bid.params.video[param]] !== 'undefined') { - bid.params.video[param] = LINEARITY_MAP[bid.params.video[param]]; - } - cygnusImpression.video[param] = bid.params.video[param]; - }); - } else { - return; - } - - let bidSize = getSizes(bid.sizes).shift(); - if (!bidSize || !bidSize.width || !bidSize.height) { - return; - } - cygnusImpression.video.w = bidSize.width; - cygnusImpression.video.h = bidSize.height; - - bidRequests[bid.bidId].cygnus = cygnusImpression; - - return cygnusImpression; - } - - /* - Function in order to add a slot into the list if it hasn't been created yet, else it returns the same list. - */ - function mergeSlotInto(slot, slotList) { - for (var i = 0; i < slotList.length; i++) { - if (slot.id === slotList[i].id) { - return slotList; - } - } - slotList.push(slot); - return slotList; - } - - function getSlotObj(obj, id) { - var arr = obj.slots; - var returnObj = {}; - utils._each(arr, function (value) { - if (value.id === id) { - returnObj = value; - } - }); - - return returnObj; - } - - function logErrorBidResponse() { - // no bid response - var bid = bidfactory.createBid(2); - bid.bidderCode = ADAPTER_CODE; - - // log error to first add unit - bidmanager.addBidResponse(firstAdUnitCode, bid); - } - - function createCygnusRequest(siteID, cygnusRequest) { - let cygnusUrl = (window.location.protocol === 'https:') ? url.parse(BASE_CYGNUS_VIDEO_URL_SECURE) : url.parse(BASE_CYGNUS_VIDEO_URL_INSECURE); - cygnusUrl.search.s = siteID; - cygnusUrl.search.r = encodeURIComponent(JSON.stringify(cygnusRequest)); - let formattedCygnusUrl = url.format(cygnusUrl); - return formattedCygnusUrl; - } - - /* Notify Prebid of bid responses so bids can get in the auction */ - $$PREBID_GLOBAL$$.handleCygnusResponse = function (response) { - if (!response || !response.seatbid || utils.isEmpty(response.seatbid)) { - utils.logInfo('Cygnus returned no bids'); - - // signal this response is complete - Object.keys(bidRequests) - .forEach(bidId => { - let prebidRequest = bidRequests[bidId].prebid; - let bid = createBidObj(STATUS.NO_BID, prebidRequest); - utils.logInfo(JSON.stringify(bid)); - bidmanager.addBidResponse(prebidRequest.placementCode, bid); - }); - - return; - } - - response.seatbid - .forEach(seat => { - seat.bid.forEach(cygnusBid => { - let validBid = true; - - if (typeof bidRequests[cygnusBid.impid] === 'undefined') { - utils.logInfo('Cygnus returned mismatched id'); - - // signal this response is complete - Object.keys(bidRequests) - .forEach(bidId => { - let prebidRequest = bidRequests[bidId].prebid; - let bid = createBidObj(STATUS.NO_BID, prebidRequest); - bidmanager.addBidResponse(prebidRequest.placementCode, bid); - }); - return; - } - - if (!cygnusBid.ext.vasturl) { - utils.logInfo('Cygnus returned no vast url'); - validBid = false; - } - - if (url.parse(cygnusBid.ext.vasturl).host === window.location.host) { - utils.logInfo('Cygnus returned no vast url'); - validBid = false; - } - - let cpm; - if (typeof cygnusBid.ext.pricelevel === 'string') { - let priceLevel = cygnusBid.ext.pricelevel; - if (priceLevel.charAt(0) === '_') priceLevel = priceLevel.slice(1); - cpm = priceLevel / 100; - if (!utils.isNumber(cpm) || isNaN(cpm)) { - utils.logInfo('Cygnus returned invalid price'); - validBid = false; - } - } else { - validBid = false; - } - - let prebidRequest = bidRequests[cygnusBid.impid].prebid; - let cygnusRequest = bidRequests[cygnusBid.impid].cygnus; - - if (!validBid) { - let bid = createBidObj(STATUS.NO_BID, prebidRequest); - bidmanager.addBidResponse(prebidRequest.placementCode, bid); - return; - } - - let bid = createBidObj(STATUS.GOOD, prebidRequest); - bid.cpm = cpm; - bid.width = cygnusRequest.video.w; - bid.height = cygnusRequest.video.h; - bid.vastUrl = cygnusBid.ext.vasturl; - bid.mediaType = 'video'; - - bidmanager.addBidResponse(prebidRequest.placementCode, bid); - }); - }); - - bidRequests = {}; - }; - - function createBidObj(status, request) { - let bid = bidfactory.createBid(status, request); - bid.code = baseAdapter.getBidderCode(); - bid.bidderCode = baseAdapter.getBidderCode(); - - return bid; - } - - /* Check that a bid has required paramters */ - function validateBid(bid) { - if ( - bid.mediaType === 'video' && - utils.hasValidBidRequest(bid.params.video, Object.keys(VIDEO_REQUIRED_PARAMS_MAP), ADAPTER_NAME) && - isValidSite(bid.params.video.siteID) && - isValidPlayerType(bid.params.video.playerType) && - isValidProtocolArray(bid.params.video.protocols) && - isValidDuration(bid.params.video.maxduration) && bid.params.video.maxduration > 0 - ) { - return bid; - } - } - - function isValidSite(siteID) { - let intSiteID = +siteID; - if (isNaN(intSiteID) || !utils.isNumber(intSiteID) || intSiteID < 0 || utils.isArray(siteID)) { - utils.logError(`Site ID is invalid, must be a number > 0. Got: ${siteID}`); - return false; - } - return true; - } - - function isValidPlayerType(playerType) { - if (typeof playerType === 'undefined' || !utils.isStr(playerType)) { - utils.logError(`Player type is invalid, must be one of: ${Object.keys(SUPPORTED_PLAYER_TYPES_MAP)}`); - return false; - } - playerType = playerType.toUpperCase(); - if (!SUPPORTED_PLAYER_TYPES_MAP[playerType]) { - utils.logError(`Player type is invalid, must be one of: ${Object.keys(SUPPORTED_PLAYER_TYPES_MAP)}`); - return false; - } - return true; - } - - function isValidProtocolArray(protocolArray) { - if (!utils.isArray(protocolArray) || utils.isEmpty(protocolArray)) { - utils.logError(`Protocol array is not an array. Got: ${protocolArray}`); - return false; - } else { - for (var i = 0; i < protocolArray.length; i++) { - let protocol = protocolArray[i]; - if (!SUPPORTED_PROTOCOLS_MAP[protocol]) { - utils.logError(`Protocol array contains an invalid protocol, must be one of: ${SUPPORTED_PROTOCOLS_MAP}. Got: ${protocol}`); - return false; - } - } - } - return true; - } - - function isValidDuration(duration) { - let intDuration = +duration; - if (isNaN(intDuration) || !utils.isNumber(intDuration) || utils.isArray(duration)) { - utils.logError(`Duration is invalid, must be a number. Got: ${duration}`); - return false; - } - return true; - } - - function isValidMimeArray(mimeArray) { - if (!utils.isArray(mimeArray) || utils.isEmpty(mimeArray)) { - utils.logError(`MIMEs array is not an array. Got: ${mimeArray}`); - return false; - } else { - for (var i = 0; i < mimeArray.length; i++) { - let mimeType = mimeArray[i]; - if (!utils.isStr(mimeType) || utils.isEmptyStr(mimeType) || !/^\w+\/[\w-]+$/.test(mimeType)) { - utils.logError(`MIMEs array contains an invalid MIME type. Got: ${mimeType}`); - return false; - } - } - } - return true; - } - - function isValidLinearity(linearity) { - if (!LINEARITY_MAP[linearity]) { - utils.logInfo(`Linearity is invalid, must be one of: ${Object.keys(LINEARITY_MAP)}. Got: ${linearity}`); - return false; - } - return true; - } - - function isValidStartDelay(startdelay) { - if (typeof START_DELAY_MAP[startdelay] === 'undefined') { - let intStartdelay = +startdelay; - if (isNaN(intStartdelay) || !utils.isNumber(intStartdelay) || intStartdelay < -2 || utils.isArray(startdelay)) { - utils.logInfo(`Start delay is invalid, must be a number >= -2. Got: ${startdelay}`); - return false; - } - } - return true; - } - - function isValidApiArray(apiArray, playerType) { - if (!utils.isArray(apiArray) || utils.isEmpty(apiArray)) { - utils.logInfo(`API array is not an array. Got: ${apiArray}`); - return false; - } else { - for (var i = 0; i < apiArray.length; i++) { - let api = +apiArray[i]; - if (isNaN(api) || !SUPPORTED_API_MAP[playerType].includes(api)) { - utils.logInfo(`API array contains an invalid API version. Got: ${api}`); - return false; - } - } - } - return true; - } - - function transformBid(bid) { - bid.params.video.siteID = +bid.params.video.siteID; - bid.params.video.maxduration = +bid.params.video.maxduration; - - bid.params.video.protocols = bid.params.video.protocols.reduce((arr, protocol) => { - return arr.concat(SUPPORTED_PROTOCOLS_MAP[protocol]); - }, []); - - let minduration = bid.params.video.minduration; - if (typeof minduration === 'undefined' || !isValidDuration(minduration)) { - utils.logInfo(`Using default value for 'minduration', default: ${VIDEO_OPTIONAL_PARAMS_MAP.minduration}`); - bid.params.video.minduration = VIDEO_OPTIONAL_PARAMS_MAP.minduration; - } - - let startdelay = bid.params.video.startdelay; - if (typeof startdelay === 'undefined' || !isValidStartDelay(startdelay)) { - utils.logInfo(`Using default value for 'startdelay', default: ${VIDEO_OPTIONAL_PARAMS_MAP.startdelay}`); - bid.params.video.startdelay = VIDEO_OPTIONAL_PARAMS_MAP.startdelay; - } - - let linearity = bid.params.video.linearity; - if (typeof linearity === 'undefined' || !isValidLinearity(linearity)) { - utils.logInfo(`Using default value for 'linearity', default: ${VIDEO_OPTIONAL_PARAMS_MAP.linearity}`); - bid.params.video.linearity = VIDEO_OPTIONAL_PARAMS_MAP.linearity; - } - - let mimes = bid.params.video.mimes; - let playerType = bid.params.video.playerType.toUpperCase(); - if (typeof mimes === 'undefined' || !isValidMimeArray(mimes)) { - utils.logInfo(`Using default value for 'mimes', player type: '${playerType}', default: ${DEFAULT_MIMES_MAP[playerType]}`); - bid.params.video.mimes = DEFAULT_MIMES_MAP[playerType]; - } - - let apiList = bid.params.video.apiList; - if (typeof apiList !== 'undefined' && !isValidApiArray(apiList, playerType)) { - utils.logInfo(`Removing invalid api versions from api list.`); - if (utils.isArray(apiList)) { - bid.params.video.apiList = apiList.filter(api => SUPPORTED_API_MAP[playerType].includes(api)); - } else { - bid.params.video.apiList = []; - } - } - - if (typeof apiList === 'undefined' && bid.params.video.allowVPAID && utils.isA(bid.params.video.allowVPAID, 'Boolean')) { - bid.params.video.mimes = bid.params.video.mimes.concat(DEFAULT_VPAID_MIMES_MAP[playerType]); - bid.params.video.apiList = SUPPORTED_API_MAP[playerType]; - } - - if (utils.isEmpty(bid.params.video.apiList)) { - utils.logInfo(`API list is empty, VPAID ads will not be requested.`); - delete bid.params.video.apiList; - } - - delete bid.params.video.playerType; - delete bid.params.video.allowVPAID; - - return bid; - } - - /* Turn bid request sizes into ut-compatible format */ - function getSizes(requestSizes) { - let sizes = []; - let sizeObj = {}; - - if (utils.isArray(requestSizes) && requestSizes.length === 2 && !utils.isArray(requestSizes[0])) { - if (!utils.isNumber(requestSizes[0]) || !utils.isNumber(requestSizes[1])) { - return sizes; - } - sizeObj.width = requestSizes[0]; - sizeObj.height = requestSizes[1]; - sizes.push(sizeObj); - } else if (typeof requestSizes === 'object') { - for (let i = 0; i < requestSizes.length; i++) { - let size = requestSizes[i]; - sizeObj = {}; - sizeObj.width = parseInt(size[0], 10); - sizeObj.height = parseInt(size[1], 10); - sizes.push(sizeObj); - } - } - - return sizes; - } - - return Object.assign(this, { - callBids: _callBids - }); -}; - -adaptermanager.registerBidAdapter(new IndexExchangeAdapter(), 'indexExchange', { - supportedMediaTypes: ['video'] -}); - -module.exports = IndexExchangeAdapter; diff --git a/modules/inneractiveBidAdapter.js b/modules/inneractiveBidAdapter.js deleted file mode 100644 index c3b6c0a9027..00000000000 --- a/modules/inneractiveBidAdapter.js +++ /dev/null @@ -1,459 +0,0 @@ -import * as utils from 'src/utils'; -import Adapter from 'src/adapter'; -import {ajax} from 'src/ajax'; -import bidManager from 'src/bidmanager'; -import bidFactory from 'src/bidfactory'; -import {STATUS} from 'src/constants'; -import {formatQS} from 'src/url'; -import adaptermanager from 'src/adaptermanager'; -import { config } from 'src/config'; - -/** - * @type {{IA_JS: string, ADAPTER_NAME: string, V: string, RECTANGLE_SIZE: {W: number, H: number}, SPOT_TYPES: {INTERSTITIAL: string, RECTANGLE: string, FLOATING: string, BANNER: string}, DISPLAY_AD: number, ENDPOINT_URL: string, EVENTS_ENDPOINT_URL: string, RESPONSE_HEADERS_NAME: {PRICING_VALUE: string, AD_H: string, AD_W: string}}} - */ -const CONSTANTS = { - ADAPTER_NAME: 'inneractive', - V: 'IA-JS-HB-PBJS-1.0', - RECTANGLE_SIZE: {W: 300, H: 250}, - - SPOT_TYPES: { - INTERSTITIAL: 'interstitial', - RECTANGLE: 'rectangle', - FLOATING: 'floating', - BANNER: 'banner' - }, - - DISPLAY_AD: 20, - ENDPOINT_URL: '//ad-tag.inner-active.mobi/simpleM2M/requestJsonAd', - EVENTS_ENDPOINT_URL: '//vast-events.inner-active.mobi/Event', - RESPONSE_HEADERS_NAME: { - PRICING_VALUE: 'X-IA-Pricing-Value', - AD_H: 'X-IA-Ad-Height', - AD_W: 'X-IA-Ad-Width' - } -}; - -let iaRef; -try { - iaRef = window.top.document.referrer; -} catch (e) { - iaRef = window.document.referrer; -} - -/** - * gloable util functions - * @type {{defaultsQsParams: {v: (string|string), page: string, mw: boolean, hb: string}, stringToCamel: (function(*)), objectToCamel: (function(*=))}} - */ -const Helpers = { - defaultsQsParams: {v: CONSTANTS.V, page: encodeURIComponent(utils.getTopWindowUrl()), mw: true, hb: 'prebidjs'}, - /** - * Change string format from underscore to camelcase (e.g., APP_ID to appId) - * @param str: string - * @returns string - */ - stringToCamel(str) { - if (str.indexOf('_') === -1) { - const first = str.charAt(0); - if (first !== first.toLowerCase()) { - str = str.toLowerCase(); - } - return str; - } - - str = str.toLowerCase(); - return str.replace(/(\_[a-z])/g, $1 => $1.toUpperCase().replace('_', '')); - }, - - /** - * Change all object keys string format from underscore to camelcase (e.g., {'APP_ID' : ...} to {'appId' : ...}) - * @param params: object - * @returns object - */ - objectToCamel(params) { - Object.keys(params).forEach(key => { - const keyCamelCase = this.stringToCamel(key); - if (keyCamelCase !== key) { - params[keyCamelCase] = params[key]; - delete params[key]; - } - }); - return params; - } -}; - -/** - * Tracking pixels for events - * @type {{fire: (function(*=))}} - */ -const Tracker = { - /** - * Creates a tracking pixel - * @param urls: Array - */ - fire(urls) { - urls.forEach(url => url && ((new Image(1, 1)).src = encodeURI(url))); - } -}; - -/** - * Analytics - * @type {{errorEventName: string, pageProtocol: string, getPageProtocol: (function(): string), getEventUrl: (function(*, *=)), reportEvent: (function(string, Object)), defaults: {v: (string|string), page: string, mw: boolean, hb: string}, eventQueryStringParams: (function(Object): string), createTrackingPixel: (function(string))}} - */ -const Reporter = { - /** - * @private - */ - errorEventName: 'HBPreBidError', - pageProtocol: '', - - /** - * Gets the page protocol based on the document.location.protocol - * The returned string is either http:// or https:// - * @returns {string} - */ - getPageProtocol() { - if (!this.pageProtocol) { - this.pageProtocol = (utils.getTopWindowLocation().protocol === 'http:' ? 'http:' : 'https:'); - } - return this.pageProtocol; - }, - - getEventUrl(evtName, extraDetails) { - let eventsEndpoint = CONSTANTS.EVENTS_ENDPOINT_URL + '?table=' + ((evtName === this.errorEventName) ? 'mbwError' : 'mbwEvent'); - let queryStringParams = this.eventQueryStringParams(extraDetails); - const appId = extraDetails && extraDetails.appId; - let queryStringParamsWithAID = `${queryStringParams}&aid=${appId}_${evtName}_other&evtName=${evtName}`; - return eventsEndpoint + '&' + queryStringParamsWithAID; - }, - - /** - * Reports an event to IA's servers. - * @param {string} evtName - event name as string. - * @param {object} extraDetails - e.g., a JS exception JSON object. - * @param shouldSendOnlyToNewEndpoint - */ - reportEvent(evtName, extraDetails) { - const url = this.getEventUrl(evtName, extraDetails); - this.createTrackingPixel(url); - }, - defaults: Helpers.defaultsQsParams, - - /** - * Ia Event Reporting Query String Parameters, not including App Id. - * @param {object} extraDetails - e.g., a JS exception JSON object. - * @return {string} IA event contcatenated queryString parameters. - */ - eventQueryStringParams(extraDetails) { - const toQS = Object.assign({}, this.defaults, {realAppId: extraDetails && extraDetails.appId, timestamp: Date.now()}); - return formatQS(toQS); - }, - - /** - * Creates a tracking pixel by prepending the page's protocol to the URL sent as the param. - * @param {string} urlWithoutProtocol - the URL to send the tracking pixel to, without the protocol as a prefix. - */ - createTrackingPixel(urlWithoutProtocol) { - Tracker.fire([this.getPageProtocol() + urlWithoutProtocol]); - } -}; - -/** - * Url generator - generates a request URL - * @type {{defaultsParams: *, serverParamNameBySettingParamName: {referrer: string, keywords: string, appId: string, portal: string, age: string, gender: string, isSecured: (boolean|null)}, toServerParams: (function(*)), unwantedValues: *[], getUrlParams: (function(*=))}} - */ -const Url = { - defaultsParams: Object.assign({}, Helpers.defaultsQsParams, {f: CONSTANTS.DISPLAY_AD, fs: false, ref: iaRef}), - serverParamNameBySettingParamName: { - referrer: 'ref', - keywords: 'k', - appId: 'aid', - portal: 'po', - age: 'a', - gender: 'g', - }, - unwantedValues: ['', null, undefined], - - /** - * Maps publisher params to server params - * @param params: object {k:v} - * @returns object {k:v} - */ - toServerParams(params) { - const serverParams = {}; - for (const paramName in params) { - if (params.hasOwnProperty(paramName) && this.serverParamNameBySettingParamName.hasOwnProperty(paramName)) { - serverParams[this.serverParamNameBySettingParamName[paramName]] = params[paramName]; - } else { - serverParams[paramName] = params[paramName]; - } - } - - serverParams.isSecured = Reporter.getPageProtocol() === 'https:' || null; - return serverParams; - }, - - /** - * Prepare querty string to ad server - * @param params: object {k:v} - * @returns : object {k:v} - */ - getUrlParams(params) { - const serverParams = this.toServerParams(params); - const toQueryString = Object.assign({}, this.defaultsParams, serverParams); - for (const paramName in toQueryString) { - if (toQueryString.hasOwnProperty(paramName) && this.unwantedValues.indexOf(toQueryString[paramName]) !== -1) { - delete toQueryString[paramName]; - } - } - toQueryString.fs = params.spotType === CONSTANTS.SPOT_TYPES.INTERSTITIAL; - - if (params.spotType === CONSTANTS.SPOT_TYPES.RECTANGLE) { - toQueryString.rw = CONSTANTS.RECTANGLE_SIZE.W; - toQueryString.rh = CONSTANTS.RECTANGLE_SIZE.H; - } - - if (typeof $$PREBID_GLOBAL$$ !== 'undefined') { - toQueryString.bco = $$PREBID_GLOBAL$$.cbTimeout || config.getConfig('bidderTimeout'); - } - - toQueryString.timestamp = Date.now(); - delete toQueryString.qa; - return toQueryString; - } -}; - -/** - * Http helper to extract metadata - * @type {{headers: *[], getBidHeaders: (function(*))}} - */ -const Http = { - headers: [ - CONSTANTS.RESPONSE_HEADERS_NAME.PRICING_VALUE, - CONSTANTS.RESPONSE_HEADERS_NAME.AD_H, - CONSTANTS.RESPONSE_HEADERS_NAME.AD_W - ], - - /** - * Extract headers data - * @param xhr: XMLHttpRequest - * @returns {} - */ - getBidHeaders(xhr) { - const headersData = {}; - this.headers.forEach(headerName => headersData[headerName] = xhr.getResponseHeader(headerName)); - return headersData; - } -}; - -/** - * InnerActiveAdapter for requesting bids - * @class - */ -class InnerActiveAdapter { - constructor() { - this.iaAdapter = new Adapter(CONSTANTS.ADAPTER_NAME); - this.setBidderCode = this.iaAdapter.setBidderCode.bind(this); - - this.bidByBidId = {}; - } - - /** - * validate if bid request is valid - * @param adSettings: object - * @returns {boolean} - * @private - */ - _isValidRequest(adSettings) { - if (adSettings && adSettings.appId && adSettings.spotType) { - return true; - } - utils.logError('bid requires appId'); - return false; - } - - /** - * Store the bids in a Map object (k: bidId, v: bid)to check later if won - * @param bid - * @returns bid object - * @private - */ - _storeBidRequestDetails(bid) { - this.bidByBidId[bid.bidId] = bid; - return bid; - } - - /** - * @param bidStatus: int ("STATUS": {"GOOD": 1,"NO_BID": 2}) - * @param bidResponse: object - * @returns {type[]} - * @private - */ - _getBidDetails(bidStatus, bidResponse, bidId) { - let bid = bidFactory.createBid(bidStatus, bidResponse); - bid.code = CONSTANTS.ADAPTER_NAME; - bid.bidderCode = bid.code; - if (bidStatus === STATUS.GOOD) { - bid = Object.assign(bid, bidResponse); - this._setBidCpm(bid, bidId); - } - return bid; - } - - _setBidCpm(bid, bidId) { - const storedBid = this.bidByBidId[bidId]; - if (storedBid) { - bid.cpm = (storedBid.params && storedBid.params.qa && storedBid.params.qa.cpm) || bid.cpm; - bid.cpm = (bid.cpm !== null && !isNaN(bid.cpm)) ? parseFloat(bid.cpm) : 0.0; - } - } - - /** - * Validate if response is valid - * @param responseAsJson : object - * @param headersData: {} - * @returns {boolean} - * @private - */ - _isValidBidResponse(responseAsJson, headersData) { - return (responseAsJson && responseAsJson.ad && responseAsJson.ad.html && headersData && headersData[CONSTANTS.RESPONSE_HEADERS_NAME.PRICING_VALUE] > 0); - } - - /** - * When response is received - * @param response: string(json format) - * @param xhr: XMLHttpRequest - * @param bidId: string - * @private - */ - _onResponse(response, xhr, bidId) { - const bid = this.bidByBidId[bidId]; - const [w, h] = bid.sizes[0]; - const size = {w, h}; - let responseAsJson; - const headersData = Http.getBidHeaders(xhr); - try { - responseAsJson = JSON.parse(response); - } catch (error) { - utils.logError(error); - } - - if (!this._isValidBidResponse(responseAsJson, headersData)) { - let errorMessage = `response failed for ${CONSTANTS.ADAPTER_NAME} adapter`; - utils.logError(errorMessage); - const passback = responseAsJson && responseAsJson.config && responseAsJson.config.passback; - if (passback) { - Tracker.fire([passback]); - } - Reporter.reportEvent('HBPreBidNoAd', bid.params); - return bidManager.addBidResponse(bid.placementCode, this._getBidDetails(STATUS.NO_BID)); - } - const bidResponse = { - cpm: headersData[CONSTANTS.RESPONSE_HEADERS_NAME.PRICING_VALUE] * 1000, - width: parseFloat(headersData[CONSTANTS.RESPONSE_HEADERS_NAME.AD_W]) || size.w, - ad: this._getAd(responseAsJson.ad.html, responseAsJson.config.tracking, bid.params), - height: parseFloat(headersData[CONSTANTS.RESPONSE_HEADERS_NAME.AD_H]) || size.h - }; - const auctionBid = this._getBidDetails(STATUS.GOOD, bidResponse, bidId); - bid.adId = auctionBid.adId; - this.bidByBidId[bidId] = bid; - bidManager.addBidResponse(bid.placementCode, auctionBid); - } - - /** - * Returns the ad HTML template - * @param adHtml: string {ad server creative} - * @param tracking: object {impressions, clicks} - * @param bidParams: object - * @returns {string}: create template - * @private - */ - _getAd(adHtml, tracking, bidParams) { - let impressionsHtml = ''; - if (tracking && Array.isArray(tracking.impressions)) { - let impressions = tracking.impressions; - impressions.push(Reporter.getEventUrl('HBPreBidImpression', bidParams, false)); - impressions.forEach(impression => impression && (impressionsHtml += utils.createTrackPixelHtml(impression))); - } - adHtml = impressionsHtml + adHtml.replace(/ - - - - -
${adHtml}
- - - `; - return adTemplate; - } - /** - * Adjust bid params to ia-ad-server params - * @param bid: object - * @private - */ - _toIaBidParams(bid) { - const bidParamsWithCustomParams = Object.assign({}, bid.params, bid.params.customParams); - delete bidParamsWithCustomParams.customParams; - bid.params = Helpers.objectToCamel(bidParamsWithCustomParams); - } - - /** - * Prebid executes for stating an auction - * @param bidRequest: object - */ - callBids(bidRequest) { - const bids = bidRequest.bids || []; - bids.forEach(bid => this._toIaBidParams(bid)); - bids - .filter(bid => this._isValidRequest(bid.params)) - .map(bid => this._storeBidRequestDetails(bid)) - .forEach(bid => ajax(this._getEndpointUrl(bid.params), (response, xhr) => this._onResponse(response, xhr, bid.bidId), Url.getUrlParams(bid.params), {method: 'GET'})); - } - - _getEndpointUrl(params) { - return (params && params.qa && params.qa.url) || Reporter.getPageProtocol() + CONSTANTS.ENDPOINT_URL; - } - - _getStoredBids() { - const storedBids = []; - for (const bidId in this.bidByBidId) { - if (this.bidByBidId.hasOwnProperty(bidId)) { - storedBids.push(this.bidByBidId[bidId]); - } - } - return storedBids; - } - - /** - * Return internal object - testing - * @returns {{Reporter: {errorEventName: string, pageProtocol: string, getPageProtocol: (function(): string), getEventUrl: (function(*, *=)), reportEvent: (function(string, Object)), defaults: {v: (string|string), page: string, mw: boolean, hb: string}, eventQueryStringParams: (function(Object): string), createTrackingPixel: (function(string))}}} - * @private - */ - static _getUtils() { - return {Reporter}; - } -} - -adaptermanager.registerBidAdapter(new InnerActiveAdapter(), 'inneractive'); - -module.exports = InnerActiveAdapter; diff --git a/modules/innityBidAdapter.js b/modules/innityBidAdapter.js deleted file mode 100644 index 79afe7ffe17..00000000000 --- a/modules/innityBidAdapter.js +++ /dev/null @@ -1,65 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var utils = require('src/utils.js'); -var CONSTANTS = require('src/constants.json'); -var adaptermanager = require('src/adaptermanager'); - -var InnityAdapter = function InnityAdapter() { - function _callBids(params) { - var bidURL; - const bids = params.bids || []; - const requestURL = window.location.protocol + '//as.innity.com/synd/?cb=' + new Date().getTime() + '&ver=2&hb=1&output=js&'; - for (var i = 0; i < bids.length; i++) { - const requestParams = {}; - const bid = bids[i]; - requestParams.pub = bid.params.pub; - requestParams.zone = bid.params.zone; - // Page URL - requestParams.url = utils.getTopWindowUrl(); - // Sizes - const parseSized = utils.parseSizesInput(bid.sizes); - const arrSize = parseSized[0].split('x'); - requestParams.width = arrSize[0]; - requestParams.height = arrSize[1]; - // Callback function - requestParams.callback = '$$PREBID_GLOBAL$$._doInnityCallback'; - // Callback ID - requestParams.callback_uid = bid.bidId; - // Load Bidder URL - bidURL = requestURL + utils.parseQueryStringParameters(requestParams); - utils.logMessage('Innity.prebid, Bid ID: ' + bid.bidId + ', Pub ID: ' + bid.params.pub + ', Zone ID: ' + bid.params.zone + ', URL: ' + bidURL); - adloader.loadScript(bidURL); - } - } - - $$PREBID_GLOBAL$$._doInnityCallback = function(response) { - var bidObject; - var bidRequest; - var callbackID; - var libURL = window.location.protocol + '//cdn.innity.net/frame_util.js'; - callbackID = response.callback_uid; - bidRequest = utils.getBidRequest(callbackID); - if (response.cpm > 0) { - bidObject = bidfactory.createBid(CONSTANTS.STATUS.GOOD, bidRequest); - bidObject.bidderCode = 'innity'; - bidObject.cpm = parseFloat(response.cpm) / 100; - bidObject.ad = '' + response.tag; - bidObject.width = response.width; - bidObject.height = response.height; - } else { - bidObject = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, bidRequest); - bidObject.bidderCode = 'innity'; - utils.logMessage('No Bid response from Innity request: ' + callbackID); - } - bidmanager.addBidResponse(bidRequest.placementCode, bidObject); - }; - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new InnityAdapter(), 'innity'); - -module.exports = InnityAdapter; diff --git a/modules/kruxlinkBidAdapter.js b/modules/kruxlinkBidAdapter.js deleted file mode 100644 index e3e6569ec1c..00000000000 --- a/modules/kruxlinkBidAdapter.js +++ /dev/null @@ -1,90 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var adaptermanager = require('src/adaptermanager'); - -function _qs(key, value) { - return encodeURIComponent(key) + '=' + encodeURIComponent(value); -} - -function _makeBidResponse(placementCode, bid) { - var bidResponse = bidfactory.createBid(bid !== undefined ? 1 : 2); - bidResponse.bidderCode = 'kruxlink'; - if (bid !== undefined) { - bidResponse.cpm = bid.price; - bidResponse.ad = bid.adm; - bidResponse.width = bid.w; - bidResponse.height = bid.h; - } - bidmanager.addBidResponse(placementCode, bidResponse); -} - -function _makeCallback(id, placements) { - var callback = '_kruxlink_' + id; - $$PREBID_GLOBAL$$[callback] = function(response) { - // Clean up our callback - delete $$PREBID_GLOBAL$$[callback]; - - // Add in the bid respones - if (response.seatbid !== undefined) { - for (var i = 0; i < response.seatbid.length; i++) { - var seatbid = response.seatbid[i]; - if (seatbid.bid !== undefined) { - for (var j = 0; j < seatbid.bid.length; j++) { - var bid = seatbid.bid[j]; - if (bid.impid !== undefined) { - _makeBidResponse(placements[bid.impid], bid); - delete placements[bid.impid]; - } - } - } - } - } - - // Add any no-bids remaining - for (var impid in placements) { - if (placements.hasOwnProperty(impid)) { - _makeBidResponse(placements[impid]); - } - } - }; - - return '$$PREBID_GLOBAL$$.' + callback; -} - -function _callBids(params) { - var impids = []; - var placements = {}; - - var bids = params.bids || []; - for (var i = 0; i < bids.length; i++) { - var bidRequest = bids[i]; - var bidRequestParams = bidRequest.params || {}; - var impid = bidRequestParams.impid; - placements[impid] = bidRequest.placementCode; - - impids.push(impid); - } - - var callback = _makeCallback(params.bidderRequestId, placements); - var qs = [ - _qs('id', params.bidderRequestId), - _qs('u', window.location.href), - _qs('impid', impids.join(',')), - _qs('calltype', 'pbd'), - _qs('callback', callback) - ]; - var url = 'https://link.krxd.net/hb?' + qs.join('&'); - - adloader.loadScript(url); -} - -function KruxAdapter() { - return { - callBids: _callBids - }; -} - -adaptermanager.registerBidAdapter(new KruxAdapter(), 'kruxlink'); - -module.exports = KruxAdapter; diff --git a/modules/lifestreetBidAdapter.js b/modules/lifestreetBidAdapter.js deleted file mode 100644 index aa65ed1fd71..00000000000 --- a/modules/lifestreetBidAdapter.js +++ /dev/null @@ -1,166 +0,0 @@ -const bidfactory = require('src/bidfactory.js'); -const bidmanager = require('src/bidmanager'); -const utils = require('src/utils.js'); -const adloader = require('src/adloader'); -const adaptermanager = require('src/adaptermanager'); - -const LifestreetAdapter = function LifestreetAdapter() { - const BIDDER_CODE = 'lifestreet'; - const ADAPTER_VERSION = 'prebidJS-1.0'; - const SLOTS_LOAD_MAP = {}; - const PREBID_REQUEST_MESSAGE = 'LSMPrebid Request'; - const PREBID_RESPONSE_MESSAGE = 'LSMPrebid Response'; - - function _callBids(params) { - utils._each(params.bids, bid => { - const jstagUrl = bid.params.jstag_url; - const slot = bid.params.slot; - const adkey = bid.params.adkey; - const adSize = bid.params.ad_size; - let timeout = 700; - if (bid.params.timeout) { - timeout = bid.params.timeout; - } - let shouldRequest = false; - if (jstagUrl && jstagUrl.length > 0 && slot && slot.length > 0 && - adkey && adkey.length > 0 && adSize && adSize.length > 0) { - let adSizeArray = adSize.split('x'); - for (let i = 0; i < adSizeArray.length; ++i) { - adSizeArray[i] = +adSizeArray[i]; - } - if (bid.sizes && (bid.sizes instanceof Array) && bid.sizes.length > 0 && adSizeArray.length > 1) { - bid.sizes = !(bid.sizes[0] instanceof Array) ? [ bid.sizes ] : bid.sizes; - for (let i = 0; i < bid.sizes.length; ++i) { - let size = bid.sizes[i]; - if (size.length > 1) { - if (size[0] === adSizeArray[0] && size[1] === adSizeArray[1]) { - shouldRequest = true; - break; - } - } - } - } else { - shouldRequest = true; - } - } - if (shouldRequest) { - _callJSTag(bid, jstagUrl, timeout); - } else { - _addSlotBidResponse(bid, 0, null, 0, 0); - } - }); - } - - function _callJSTag(bid, jstagUrl, timeout) { - adloader.loadScript(jstagUrl, () => { - /* global LSM_Slot */ - if (LSM_Slot && typeof LSM_Slot === 'function') { - let slotTagParams = { - _preload: 'wait', - _hb_request: ADAPTER_VERSION, - _timeout: timeout, - _onload: (slot, action, cpm, width, height) => { - if (slot.state() !== 'error') { - let slotName = slot.getSlotObjectName(); - $$PREBID_GLOBAL$$[slotName] = slot; - if (slotName && !SLOTS_LOAD_MAP[slotName]) { - SLOTS_LOAD_MAP[slotName] = true; - let ad = _constructLSMAd(jstagUrl, slotName); - _addSlotBidResponse(bid, cpm, ad, width, height); - } else { - slot.show(); - } - } else { - _addSlotBidResponse(bid, 0, null, 0, 0); - } - } - }; - for (let property in bid.params) { - if (property === 'jstag_url' || property === 'timeout') { - continue; - } - if (bid.params.hasOwnProperty(property)) { - slotTagParams[property] = bid.params[property]; - } - } - LSM_Slot(slotTagParams); - window.addEventListener('message', (ev) => { - let key = ev.message ? 'message' : 'data'; - let object = {}; - try { - object = JSON.parse(ev[key]); - } catch (e) { - return; - } - if (object.message && object.message === PREBID_REQUEST_MESSAGE && object.slotName && - window.$$PREBID_GLOBAL$$[object.slotName]) { - ev.source.postMessage(JSON.stringify({ - message: PREBID_RESPONSE_MESSAGE, - slotObject: window.$$PREBID_GLOBAL$$[object.slotName] - }), '*'); - window.$$PREBID_GLOBAL$$[object.slotName].destroy(); - window.$$PREBID_GLOBAL$$[object.slotName] = null; - } - }, false); - } else { - _addSlotBidResponse(bid, 0, null, 0, 0); - } - }); - } - - function _addSlotBidResponse(bid, cpm, ad, width, height) { - let hasResponse = cpm && ad && ad.length > 0; - let bidObject = bidfactory.createBid(hasResponse ? 1 : 2, bid); - bidObject.bidderCode = BIDDER_CODE; - if (hasResponse) { - bidObject.cpm = cpm; - bidObject.ad = ad; - bidObject.width = width; - bidObject.height = height; - } - bidmanager.addBidResponse(bid.placementCode, bidObject); - } - - function _constructLSMAd(jsTagUrl, slotName) { - if (jsTagUrl && slotName) { - return `
- - `; - } - return null; - } - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new LifestreetAdapter(), 'lifestreet'); - -module.exports = LifestreetAdapter; diff --git a/modules/mantisBidAdapter.js b/modules/mantisBidAdapter.js deleted file mode 100644 index 4dfb62f395b..00000000000 --- a/modules/mantisBidAdapter.js +++ /dev/null @@ -1,228 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader'); -var constants = require('src/constants.json'); -var adaptermanager = require('src/adaptermanager'); - -function MantisAdapter () { - function inIframe() { - try { - return window.self !== window.top && !window.mantis_link; - } catch (e) { - return true; - } - } - - function isDesktop(ignoreTouch) { - var scope = function (win) { - var width = win.innerWidth || win.document.documentElement.clientWidth || win.document.body.clientWidth; - var supportsTouch = !ignoreTouch && ('ontouchstart' in window || navigator.msMaxTouchPoints); - - return !supportsTouch && (!width || width >= (window.mantis_breakpoint || 768)); - }; - - if (inIframe()) { - try { - return scope(window.top); - } catch (ex) { - } - } - - return scope(window); - } - - function isSendable(val) { - if (val === null || val === undefined) { - return false; - } - - if (typeof val === 'string') { - return !(!val || /^\s*$/.test(val)); - } - - if (typeof val === 'number') { - return !isNaN(val); - } - - return true; - } - - function isObject(value) { - return Object.prototype.toString.call(value) === '[object Object]'; - } - - function isAmp() { - return typeof window.context === 'object' && (window.context.tagName === 'AMP-AD' || window.context.tagName === 'AMP-EMBED'); - } - - function isSecure() { - return document.location.protocol === 'https:'; - } - - function isArray(value) { - return Object.prototype.toString.call(value) === '[object Array]'; - } - - function jsonp(callback) { - if (!window.mantis_jsonp) { - window.mantis_jsonp = []; - } - - window.mantis_jsonp.push(callback); - - return 'mantis_jsonp[' + (window.mantis_jsonp.length - 1) + ']'; - } - - function jsonToQuery(data, chain, form) { - if (!data) { - return null; - } - - var parts = form || []; - - for (var key in data) { - var queryKey = key; - - if (chain) { - queryKey = chain + '[' + key + ']'; - } - - var val = data[key]; - - if (isArray(val)) { - for (var index = 0; index < val.length; index++) { - var akey = queryKey + '[' + index + ']'; - var aval = val[index]; - - if (isObject(aval)) { - jsonToQuery(aval, akey, parts); - } else if (isSendable(aval)) { - parts.push(akey + '=' + encodeURIComponent(aval)); - } - } - } else if (isObject(val)) { - jsonToQuery(val, queryKey, parts); - } else if (isSendable(val)) { - parts.push(queryKey + '=' + encodeURIComponent(val)); - } - } - - return parts.join('&'); - } - - function buildMantisUrl(path, data, domain) { - var params = { - referrer: document.referrer, - tz: new Date().getTimezoneOffset(), - buster: new Date().getTime(), - secure: isSecure() - }; - - if (!inIframe() || isAmp()) { - params.mobile = !isAmp() && isDesktop(true) ? 'false' : 'true'; - } - - if (window.mantis_uuid) { - params.uuid = window.mantis_uuid; - } else if (window.localStorage) { - var localUuid = window.localStorage.getItem('mantis:uuid'); - - if (localUuid) { - params.uuid = localUuid; - } - } - - if (!inIframe()) { - try { - params.title = window.top.document.title; - params.referrer = window.top.document.referrer; - params.url = window.top.document.location.href; - } catch (ex) { - - } - } else { - params.iframe = true; - } - - if (isAmp()) { - if (!params.url && window.context.canonicalUrl) { - params.url = window.context.canonicalUrl; - } - - if (!params.url && window.context.location) { - params.url = window.context.location.href; - } - - if (!params.referrer && window.context.referrer) { - params.referrer = window.context.referrer; - } - } - - Object.keys(data || {}).forEach(function (key) { - params[key] = data[key]; - }); - - var query = jsonToQuery(params); - - return (window.mantis_domain === undefined ? domain || 'https://mantodea.mantisadnetwork.com' : window.mantis_domain) + path + '?' + query; - } - - var Prebid = function (bidfactory, bidmanager, adloader, constants) { - return { - callBids: function (params) { - var property = null; - - params.bids.some(function (bid) { - if (bid.params.property) { - property = bid.params.property; - - return true; - } - }); - - var url = { - jsonp: jsonp(function (resp) { - params.bids.forEach(function (bid) { - var ad = resp.ads[bid.bidId]; - - var bidObject; - - if (ad) { - bidObject = bidfactory.createBid(constants.STATUS.GOOD); - bidObject.bidderCode = 'mantis'; - bidObject.cpm = ad.cpm; - bidObject.ad = ad.html; - bidObject.width = ad.width; - bidObject.height = ad.height; - } else { - bidObject = bidfactory.createBid(constants.STATUS.NO_BID); - bidObject.bidderCode = 'mantis'; - } - - bidmanager.addBidResponse(bid.placementCode, bidObject); - }); - }), - property: property, - bids: params.bids.map(function (bid) { - return { - bidId: bid.bidId, - config: bid.params, - sizes: bid.sizes.map(function (size) { - return {width: size[0], height: size[1]}; - }) - }; - }), - version: 1 - }; - - adloader.loadScript(buildMantisUrl('/website/prebid', url)); - } - }; - }; - - return new Prebid(bidfactory, bidmanager, adloader, constants); -} - -adaptermanager.registerBidAdapter(new MantisAdapter(), 'mantis'); - -module.exports = MantisAdapter; diff --git a/modules/marsmediaBidAdapter.js b/modules/marsmediaBidAdapter.js deleted file mode 100644 index e6ad12dd345..00000000000 --- a/modules/marsmediaBidAdapter.js +++ /dev/null @@ -1,160 +0,0 @@ -import Adapter from 'src/adapter'; -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import { ajax } from 'src/ajax'; -import { STATUS } from 'src/constants'; -import * as utils from 'src/utils'; -import adaptermanager from 'src/adaptermanager'; - -const MARS_BIDDER_CODE = 'marsmedia'; -const MARS_BIDDER_URL = '//bid306.rtbsrv.com:9306/bidder/?bid=3mhdom'; - -var MarsmediaBidAdapter = function MarsmediaBidAdapter() { - function _callBids(bidderRequest) { - var bids = bidderRequest.bids || []; - - bids.forEach(bid => { - try { - ajax( - MARS_BIDDER_URL, - { - success: handleBidResponse, - error: handleBidError - }, - buildCallParams(bid, bidderRequest), - {} - ); - } catch (err) { - utils.logError('Error sending marsmedia request for publisher id: ' + bid.params.publisherID, null, err); - handleBidError(); - } - - function handleBidResponse(res) { - try { - utils.logMessage('Register bid for publisher ID: ' + bid.params.publisherID); - addBid(res, bid); - } catch (err) { - utils.logError('Error processing response for publisher ID: ' + bid.params.publisherID, null, err); - handleBidError(); - } - } - - function addBid(res, bid) { - var obj; - try { - obj = JSON.parse(res); - } catch (err) { - throw 'Faild to parse bid response'; - } - - if (Object.keys(obj).length === 0 || Object.keys(bid).length === 0) { - throw 'Empty Bid'; - } - - var ad = obj.seatbid[0].bid[0]; - var bid_params = bidfactory.createBid(STATUS.GOOD, bid); - var sizes = bid.sizes[0]; - bid_params.un_id = obj.id; - bid_params.bidderCode = bid.bidder; - bid_params.cpm = Number(ad.price); - bid_params.price = Number(ad.price); - bid_params.width = sizes[0]; - bid_params.height = sizes[1]; - bid_params.ad = ad.adm; - bid_params.cid = ad.cid; - bid_params.seat = obj.seatbid[0].seat; - - bidmanager.addBidResponse(bid.placementCode, bid_params); - } - - function handleBidError() { - var bidObj = bidfactory.createBid(STATUS.NO_BID, bid); - bidObj.bidderCode = bid.bidder; - bidmanager.addBidResponse(bid.bidid, bidObj); - } - }); - } - - function buildCallParams(bidRequest) { - if (typeof bidRequest.params === 'undefined') { - throw 'No params'; - } - - if (typeof bidRequest.sizes === 'undefined' || bidRequest.sizes.length === 0) { - throw 'No sizes'; - } - - if (typeof bidRequest.params.floor === 'undefined') { - throw 'No floor'; - } else if (isNaN(Number(bidRequest.params.floor))) { - throw 'Floor must be numeric value'; - } - - var sizes = bidRequest.sizes[0]; - var floor = (typeof bidRequest.params.floor !== 'undefined' && bidRequest.params.floor === '') ? 0 : bidRequest.params.floor; - var protocol = (window.location.protocol === 'https') ? 1 : 0; - var publisher_id = (typeof bidRequest.params.publisherID !== 'undefined') ? bidRequest.params.publisherID : ''; - var params = {}; - params.id = utils.generateUUID(); - - params.cur = ['USD']; - - params.imp = [{ - id: params.id, - banner: { - w: sizes[0], - h: sizes[1], - secure: protocol - }, - bidfloor: floor - }]; - - params.device = { - ua: navigator.userAgent - }; - - params.user = { - id: publisher_id - }; - - params.app = { - id: params.id, - domain: document.domain, - publisher: { - id: publisher_id - } - }; - - params.site = { - 'id': publisher_id, - 'domain': window.location.hostname, - 'page': document.URL, - 'ref': document.referrer, - 'publisher': { - 'id': publisher_id, - 'domain': window.location.hostname - } - }; - - params.publisher = { - 'id': publisher_id, - 'domain': window.location.hostname - }; - - return JSON.stringify(params); - } - - return Object.assign(new Adapter(MARS_BIDDER_CODE), { - callBids: _callBids, - createNew: MarsmediaBidAdapter.createNew, - buildCallParams: buildCallParams - }); -}; - -MarsmediaBidAdapter.createNew = function() { - return new MarsmediaBidAdapter(); -}; - -adaptermanager.registerBidAdapter(new MarsmediaBidAdapter(), MARS_BIDDER_CODE); - -module.exports = MarsmediaBidAdapter; diff --git a/modules/memeglobalBidAdapter.js b/modules/memeglobalBidAdapter.js deleted file mode 100644 index c47c8ed7381..00000000000 --- a/modules/memeglobalBidAdapter.js +++ /dev/null @@ -1,124 +0,0 @@ -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'); - -var bidderName = 'memeglobal'; -/** - * Adapter for requesting bids from Meme Global Media Group - * OpenRTB compatible - */ -var MemeGlobalAdapter = function MemeGlobalAdapter() { - var bidder = 'stinger.memeglobal.com/api/v1/services/prebid'; - - function _callBids(params) { - var bids = params.bids; - - if (!bids) return; - - for (var i = 0; i < bids.length; i++) { - _requestBid(bids[i]); - } - } - - function _requestBid(bidReq) { - // build bid request object - var domain = window.location.host; - var page = window.location.host + window.location.pathname + location.search + location.hash; - - var tagId = utils.getBidIdParameter('tagid', bidReq.params); - var bidFloor = Number(utils.getBidIdParameter('bidfloor', bidReq.params)); - var adW = 0; - var adH = 0; - - var bidSizes = Array.isArray(bidReq.params.sizes) ? bidReq.params.sizes : bidReq.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]; - } - - // build bid request with impressions - var bidRequest = { - id: utils.getUniqueIdentifierStr(), - imp: [{ - id: bidReq.bidId, - banner: { - w: adW, - h: adH - }, - tagid: bidReq.placementCode, - bidfloor: bidFloor - }], - site: { - domain: domain, - page: page, - publisher: { - id: tagId - } - } - }; - - var scriptUrl = '//' + bidder + '?callback=window.$$PREBID_GLOBAL$$.mgres' + - '&src=' + CONSTANTS.REPO_AND_VERSION + - '&br=' + encodeURIComponent(JSON.stringify(bidRequest)); - adloader.loadScript(scriptUrl); - } - - function getBidSetForBidder() { - return $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === bidderName); - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.mgres = function (bidResp) { - // valid object? - if ((!bidResp || !bidResp.id) || - (!bidResp.seatbid || bidResp.seatbid.length === 0 || !bidResp.seatbid[0].bid || bidResp.seatbid[0].bid.length === 0)) { - return; - } - - bidResp.seatbid[0].bid.forEach(function (bidderBid) { - var responseCPM; - var placementCode = ''; - - var bidSet = getBidSetForBidder(); - var bidRequested = bidSet.bids.find(b => b.bidId === bidderBid.impid); - if (bidRequested) { - var bidResponse = bidfactory.createBid(1); - placementCode = bidRequested.placementCode; - bidRequested.status = CONSTANTS.STATUS.GOOD; - responseCPM = parseFloat(bidderBid.price); - if (responseCPM === 0) { - var bid = bidfactory.createBid(2); - bid.bidderCode = bidderName; - bidmanager.addBidResponse(placementCode, bid); - return; - } - bidResponse.placementCode = placementCode; - bidResponse.size = bidRequested.sizes; - var responseAd = bidderBid.adm; - var responseNurl = ''; - bidResponse.creative_id = bidderBid.id; - bidResponse.bidderCode = bidderName; - bidResponse.cpm = responseCPM; - bidResponse.ad = decodeURIComponent(responseAd + responseNurl); - bidResponse.width = parseInt(bidderBid.w); - bidResponse.height = parseInt(bidderBid.h); - bidmanager.addBidResponse(placementCode, bidResponse); - } - }); - }; - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new MemeGlobalAdapter(), 'memeglobal'); - -module.exports = MemeGlobalAdapter; diff --git a/modules/nanointeractiveBidAdapter.js b/modules/nanointeractiveBidAdapter.js index 9781e36edb6..c4cce6646d3 100644 --- a/modules/nanointeractiveBidAdapter.js +++ b/modules/nanointeractiveBidAdapter.js @@ -55,7 +55,7 @@ function createSingleBidRequest(bid) { [NQ]: [createNqParam(bid), createCategoryParam(bid)], sizes: bid.sizes.map(value => value[0] + 'x' + value[1]), bidId: bid.bidId, - cors: location.origin + cors: utils.getOrigin() }; } diff --git a/modules/nginadBidAdapter.js b/modules/nginadBidAdapter.js deleted file mode 100644 index 32560120d64..00000000000 --- a/modules/nginadBidAdapter.js +++ /dev/null @@ -1,186 +0,0 @@ -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'); - -var defaultPlacementForBadBid = null; - -/** - * Adapter for requesting bids from NginAd - */ -var NginAdAdapter = function NginAdAdapter() { - var rtbServerDomain = 'placeholder.for.nginad.server.com'; - - function _callBids(params) { - var nginadBids = params.bids || []; - - // De-dupe by tagid then issue single bid request for all bids - _requestBids(_getUniqueTagids(nginadBids)); - } - - // filter bids to de-dupe them? - function _getUniqueTagids(bids) { - var key; - var map = {}; - var PubZoneIds = []; - - for (key in bids) { - map[utils.getBidIdParameter('pzoneid', bids[key].params)] = bids[key]; - } - - for (key in map) { - if (map.hasOwnProperty(key)) { - PubZoneIds.push(map[key]); - } - } - - return PubZoneIds; - } - - function getWidthAndHeight(bid) { - var adW = null; - var adH = null; - - var sizeArrayLength = bid.sizes.length; - if (sizeArrayLength === 2 && typeof bid.sizes[0] === 'number' && typeof bid.sizes[1] === 'number') { - adW = bid.sizes[0]; - adH = bid.sizes[1]; - } else { - adW = bid.sizes[0][0]; - adH = bid.sizes[0][1]; - } - - return [adW, adH]; - } - - function _requestBids(bidReqs) { - // build bid request object - var domain = window.location.host; - var page = window.location.pathname + location.search + location.hash; - - var nginadImps = []; - - // assign the first adUnit (placement) for bad bids; - defaultPlacementForBadBid = bidReqs[0].placementCode; - - // build impression array for nginad - utils._each(bidReqs, function(bid) { - var tagId = utils.getBidIdParameter('pzoneid', bid.params); - var bidFloor = utils.getBidIdParameter('bidfloor', bid.params); - - var whArr = getWidthAndHeight(bid); - - var imp = { - id: bid.bidId, - banner: { - w: whArr[0], - h: whArr[1] - }, - tagid: tagId, - bidfloor: bidFloor - }; - - nginadImps.push(imp); - // bidmanager.pbCallbackMap[imp.id] = bid; - - rtbServerDomain = bid.params.nginadDomain; - }); - - // build bid request with impressions - var nginadBidReq = { - id: utils.getUniqueIdentifierStr(), - imp: nginadImps, - site: { - domain: domain, - page: page - } - }; - - var scriptUrl = window.location.protocol + '//' + rtbServerDomain + '/bid/rtb?callback=window.$$PREBID_GLOBAL$$.nginadResponse' + - '&br=' + encodeURIComponent(JSON.stringify(nginadBidReq)); - - adloader.loadScript(scriptUrl); - } - - function handleErrorResponse(bidReqs, defaultPlacementForBadBid) { - // no response data - if (defaultPlacementForBadBid === null) { - // no id with which to create an dummy bid - return; - } - - var bid = bidfactory.createBid(2); - bid.bidderCode = 'nginad'; - bidmanager.addBidResponse(defaultPlacementForBadBid, bid); - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.nginadResponse = function(nginadResponseObj) { - var bid = {}; - var key; - - // valid object? - if (!nginadResponseObj || !nginadResponseObj.id) { - return handleErrorResponse(nginadResponseObj, defaultPlacementForBadBid); - } - - if (!nginadResponseObj.seatbid || nginadResponseObj.seatbid.length === 0 || !nginadResponseObj.seatbid[0].bid || nginadResponseObj.seatbid[0].bid.length === 0) { - return handleErrorResponse(nginadResponseObj, defaultPlacementForBadBid); - } - - for (key in nginadResponseObj.seatbid[0].bid) { - var nginadBid = nginadResponseObj.seatbid[0].bid[key]; - - var responseCPM; - var placementCode = ''; - var id = nginadBid.impid; - - // try to fetch the bid request we sent NginAd - var bidObj = $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === 'nginad').bids - .find(bid => bid.bidId === id); - if (!bidObj) { - return handleErrorResponse(nginadBid, defaultPlacementForBadBid); - } - - placementCode = bidObj.placementCode; - bidObj.status = CONSTANTS.STATUS.GOOD; - - // place ad response on bidmanager._adResponsesByBidderId - responseCPM = parseFloat(nginadBid.price); - - if (responseCPM === 0) { - handleErrorResponse(nginadBid, id); - } - - nginadBid.placementCode = placementCode; - nginadBid.size = bidObj.sizes; - var responseAd = nginadBid.adm; - - // store bid response - // bid status is good (indicating 1) - bid = bidfactory.createBid(1); - bid.creative_id = nginadBid.Id; - bid.bidderCode = 'nginad'; - bid.cpm = responseCPM; - - // The bid is a mock bid, the true bidding process happens after the publisher tag is called - bid.ad = decodeURIComponent(responseAd); - - var whArr = getWidthAndHeight(bidObj); - bid.width = whArr[0]; - bid.height = whArr[1]; - - bidmanager.addBidResponse(placementCode, bid); - } - }; // nginadResponse - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new NginAdAdapter(), 'nginad'); - -module.exports = NginAdAdapter; diff --git a/modules/orbitsoftBidAdapter.js b/modules/orbitsoftBidAdapter.js deleted file mode 100644 index e01f82a7097..00000000000 --- a/modules/orbitsoftBidAdapter.js +++ /dev/null @@ -1,228 +0,0 @@ -import { getBidRequest } from 'src/utils'; - -let CONSTANTS = require('src/constants'); -let bidmanager = require('src/bidmanager'); -let bidfactory = require('src/bidfactory'); -let adloader = require('src/adloader'); -let utils = require('src/utils'); -let adaptermanager = require('src/adaptermanager'); -let Adapter = require('src/adapter').default; - -let ORBITSOFT_BIDDERCODE = 'orbitsoft'; -let styleParamsToFieldsMap = { - 'title.family': 'f1', // headerFont - 'title.size': 'fs1', // headerFontSize - 'title.weight': 'w1', // headerWeight - 'title.style': 's1', // headerStyle - 'title.color': 'c3', // headerColor - 'description.family': 'f2', // descriptionFont - 'description.size': 'fs2', // descriptionFontSize - 'description.weight': 'w2', // descriptionWeight - 'description.style': 's2', // descriptionStyle - 'description.color': 'c4', // descriptionColor - 'url.family': 'f3', // urlFont - 'url.size': 'fs3', // urlFontSize - 'url.weight': 'w3', // urlWeight - 'url.style': 's3', // urlStyle - 'url.color': 'c5', // urlColor - 'colors.background': 'c2', // borderColor - 'colors.border': 'c1', // borderColor - 'colors.link': 'c6', // lnkColor -}; - -let OrbitsoftAdapter = function OrbitsoftAdapter() { - let baseAdapter = new Adapter(ORBITSOFT_BIDDERCODE); - - baseAdapter.callBids = function(params) { - let bids = params.bids || []; - - for (let i = 0; i < bids.length; i++) { - let bidRequest = bids[i]; - let callbackId = bidRequest.bidId; - let jptCall = buildJPTCall(bidRequest, callbackId); - - if (jptCall) { - adloader.loadScript(jptCall); - } else { - // indicate that there is no bid for this placement - let bid = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, bidRequest); - bid.bidderCode = params.bidderCode; - bidmanager.addBidResponse(bidRequest.placementCode, bid); - } - } - } - - function buildJPTCall(bid, callbackId) { - // Determine tag params - let placementId = utils.getBidIdParameter('placementId', bid.params); - - let referrer = utils.getBidIdParameter('ref', bid.params); - let location = utils.getBidIdParameter('loc', bid.params); - let jptCall = utils.getBidIdParameter('requestUrl', bid.params); - if (jptCall.length === 0) { - // No param requestUrl - // @if NODE_ENV='debug' - utils.logMessage('No param requestUrl'); - // @endif - return null; - } else { - jptCall += '?'; - } - - jptCall = utils.tryAppendQueryString(jptCall, 'callback', '$$PREBID_GLOBAL$$.handleOASCB'); - jptCall = utils.tryAppendQueryString(jptCall, 'callback_uid', callbackId); - jptCall = utils.tryAppendQueryString(jptCall, 'scid', placementId); - - // Sizes takes a bit more logic - let sizeQueryString; - let parsedSizes = utils.parseSizesInput(bid.sizes); - - // Combine string into proper query string - let parsedSizesLength = parsedSizes.length; - if (parsedSizesLength > 0) { - // First value should be "size" - sizeQueryString = 'size=' + parsedSizes[0]; - jptCall += sizeQueryString + '&'; - } - - // Append custom attributes: - let paramsCopy = Object.assign({}, bid.params); - - // Delete attributes already used - delete paramsCopy.placementId; - delete paramsCopy.referrer; - delete paramsCopy.style; - delete paramsCopy.customParams; - - // Get the reminder - jptCall += utils.parseQueryStringParameters(paramsCopy); - - // Append location & referrer - if (location === '') { - location = utils.getTopWindowUrl(); - } - if (referrer === '') { - referrer = window.top.document.referrer; - } - jptCall = utils.tryAppendQueryString(jptCall, 'loc', location); - jptCall = utils.tryAppendQueryString(jptCall, 'ref', referrer); - - // Remove the trailing "&" - jptCall = removeTrailingAmp(jptCall); - - // @if NODE_ENV='debug' - utils.logMessage('jpt request built: ' + jptCall); - // @endif - - // Append a timer here to track latency - bid.startTime = new Date().getTime(); - - return jptCall; - } - - // Remove the trailing "&" - function removeTrailingAmp(url) { - if (url.lastIndexOf('&') === url.length - 1) { - url = url.substring(0, url.length - 1); - } - return url; - } - - // Expose the callback to the global object - $$PREBID_GLOBAL$$.handleOASCB = function (jptResponseObj) { - let bidCode; - - if (jptResponseObj && jptResponseObj.callback_uid) { - let responseCPM; - let id = jptResponseObj.callback_uid; - let placementCode = ''; - let bidObj = getBidRequest(id); - if (bidObj) { - bidCode = bidObj.bidder; - - placementCode = bidObj.placementCode; - - // Set the status - bidObj.status = CONSTANTS.STATUS.GOOD; - } - - // @if NODE_ENV='debug' - utils.logMessage('JSONP callback function called for ad ID: ' + id); - // @endif - - let bid = []; - if (jptResponseObj.cpm && jptResponseObj.cpm !== 0) { - // Store bid response - responseCPM = jptResponseObj.cpm; - // Bid status is good (indicating 1) - bid = bidfactory.createBid(CONSTANTS.STATUS.GOOD, bidObj); - bid.bidderCode = bidCode; - bid.cpm = responseCPM; - bid.adUrl = jptResponseObj.content_url; - bid.width = jptResponseObj.width; - bid.height = jptResponseObj.height; - - // Styles params - let styles = utils.getBidIdParameter('style', bidObj.params); - let stylesParams = {}; - for (let currentValue in styles) { - if (styles.hasOwnProperty(currentValue)) { - let currentStyle = styles[currentValue]; - for (let field in currentStyle) { - if (currentStyle.hasOwnProperty(field)) { - let styleField = styleParamsToFieldsMap[currentValue + '.' + field]; - if (styleField !== undefined) { - stylesParams[styleField] = currentStyle[field]; - } - } - } - } - } - bid.adUrl += '&' + utils.parseQueryStringParameters(stylesParams); - - // Custom params - let customParams = utils.getBidIdParameter('customParams', bidObj.params); - let customParamsArray = {}; - for (let customField in customParams) { - if (customParams.hasOwnProperty(customField)) { - customParamsArray['c.' + customField] = customParams[customField]; - } - } - let customParamsLink = utils.parseQueryStringParameters(customParamsArray); - if (customParamsLink) { - // Don't append a "&" here, we have already done it in parseQueryStringParameters - bid.adUrl += customParamsLink; - } - - // Remove the trailing "&" - bid.adUrl = removeTrailingAmp(bid.adUrl); - - bidmanager.addBidResponse(placementCode, bid); - } else { - // No response data - // @if NODE_ENV='debug' - utils.logMessage('No prebid response from Orbitsoft for placement code ' + placementCode); - // @endif - // indicate that there is no bid for this placement - bid = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, bidObj); - bid.bidderCode = bidCode; - bidmanager.addBidResponse(placementCode, bid); - } - } else { - // No response data - // @if NODE_ENV='debug' - utils.logMessage('No prebid response for placement'); - // @endif - } - }; - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - buildJPTCall: buildJPTCall - }); -}; - -adaptermanager.registerBidAdapter(new OrbitsoftAdapter(), ORBITSOFT_BIDDERCODE); - -module.exports = OrbitsoftAdapter; diff --git a/modules/piximediaBidAdapter.js b/modules/piximediaBidAdapter.js deleted file mode 100644 index 48d2c9ee37b..00000000000 --- a/modules/piximediaBidAdapter.js +++ /dev/null @@ -1,155 +0,0 @@ -var CONSTANTS = require('src/constants.json'); -var utils = require('src/utils.js'); -var bidmanager = require('src/bidmanager.js'); -var bidfactory = require('src/bidfactory.js'); -var adloader = require('src/adloader.js'); -var Adapter = require('src/adapter.js').default; -var adaptermanager = require('src/adaptermanager'); - -var PiximediaAdapter = function PiximediaAdapter() { - var PREBID_URL = '//static.adserver.pm/prebid'; - var baseAdapter = new Adapter('piximedia'); - var bidStash = {}; - - var tryAppendPixiQueryString = function(url, name, value) { - return url + '/' + encodeURIComponent(name) + '=' + value; - }; - - baseAdapter.callBids = function callBidsPiximedia(params) { - utils._each(params.bids, function(bid) { - // valid bids must include a siteId and an placementId - if (bid.placementCode && bid.sizes && bid.params && bid.params.siteId && bid.params.placementId) { - var sizes = bid.params.hasOwnProperty('sizes') ? bid.params.sizes : bid.sizes; - sizes = utils.parseSizesInput(sizes); - - var cbid = utils.getUniqueIdentifierStr(); - - // we allow overriding the URL in the params - var url = bid.params.prebidUrl || PREBID_URL; - - // params are passed to the Piximedia endpoint, including custom params - for (var key in bid.params) { - /* istanbul ignore else */ - if (bid.params.hasOwnProperty(key)) { - var value = bid.params[key]; - switch (key) { - case 'siteId': - url = tryAppendPixiQueryString(url, 'site_id', encodeURIComponent(value)); - break; - - case 'placementId': - url = tryAppendPixiQueryString(url, 'placement_id', encodeURIComponent(value)); - break; - - case 'dealId': - url = tryAppendPixiQueryString(url, 'l_id', encodeURIComponent(value)); - break; - - case 'sizes': - case 'prebidUrl': - break; - - default: - if (typeof value === 'function') { - url = tryAppendPixiQueryString(url, key, encodeURIComponent((value(baseAdapter, params, bid) || '').toString())); - } else { - url = tryAppendPixiQueryString(url, key, encodeURIComponent((value || '').toString())); - } - break; - } - } - } - - url = tryAppendPixiQueryString(url, 'jsonp', '$$PREBID_GLOBAL$$.handlePiximediaCallback'); - url = tryAppendPixiQueryString(url, 'sizes', encodeURIComponent(sizes.join(','))); - url = tryAppendPixiQueryString(url, 'cbid', encodeURIComponent(cbid)); - url = tryAppendPixiQueryString(url, 'rand', String(Math.floor(Math.random() * 1000000000))); - - bidStash[cbid] = { - 'bidObj': bid, - 'url': url, - 'start': new Date().getTime() - }; - utils.logMessage('[Piximedia] Dispatching header Piximedia to URL ' + url); - adloader.loadScript(url); - } - }); - }; - - /* - * Piximedia's bidResponse should look like: - * - * { - * 'foundbypm': true, // a Boolean, indicating if an ad was found - * 'currency': 'EUR', // the currency, as a String - * 'cpm': 1.99, // the win price as a Number, in currency - * 'dealId': null, // or string value of winning deal ID - * 'width': 300, // width in pixels of winning ad - * 'height': 250, // height in pixels of winning ad - * 'html': 'tag_here' // HTML tag to load if we are picked - * } - * - */ - $$PREBID_GLOBAL$$.handlePiximediaCallback = function(bidResponse) { - if (bidResponse && bidResponse.hasOwnProperty('foundbypm')) { - var stash = bidStash[bidResponse.cbid]; // retrieve our stashed data, by using the cbid - var bid; - - if (stash) { - var bidObj = stash.bidObj; - var timelapsed = new Date().getTime(); - timelapsed = timelapsed - stash.start; - - if (bidResponse.foundbypm && bidResponse.width && bidResponse.height && bidResponse.html && bidResponse.cpm && bidResponse.currency) { - /* we have a valid ad to display */ - bid = bidfactory.createBid(CONSTANTS.STATUS.GOOD); - bid.bidderCode = bidObj.bidder; - bid.width = bidResponse.width; - bid.height = bidResponse.height; - bid.ad = bidResponse.html; - bid.cpm = bidResponse.cpm; - bid.currency = bidResponse.currency; - - if (bidResponse.dealId) { - bid.dealId = bidResponse.dealId; - } else { - bid.dealId = null; - } - - bidmanager.addBidResponse(bidObj.placementCode, bid); - - utils.logMessage('[Piximedia] Registered bidresponse from URL ' + stash.url + - ' (time: ' + String(timelapsed) + ')'); - utils.logMessage('[Piximedia] ======> BID placementCode: ' + bidObj.placementCode + - ' CPM: ' + String(bid.cpm) + ' ' + bid.currency + - ' Format: ' + String(bid.width) + 'x' + String(bid.height)); - } else { - /* we have no ads to display */ - bid = bidfactory.createBid(CONSTANTS.STATUS.NO_BID); - bid.bidderCode = bidObj.bidder; - bidmanager.addBidResponse(bidObj.placementCode, bid); - - utils.logMessage('[Piximedia] Registered BLANK bidresponse from URL ' + stash.url + - ' (time: ' + String(timelapsed) + ')'); - utils.logMessage('[Piximedia] ======> NOBID placementCode: ' + bidObj.placementCode); - } - - // We should no longer need this stashed object, so drop reference: - bidStash[bidResponse.cbid] = null; - } else { - utils.logMessage("[Piximedia] Couldn't find stash for cbid=" + bidResponse.cbid); - } - } - }; - - // return an object with PiximediaAdapter methods - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - getBidderCode: baseAdapter.getBidderCode - }); -}; - -adaptermanager.registerBidAdapter(new PiximediaAdapter(), 'piximedia'); - -module.exports = PiximediaAdapter; diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 7dc3b9b6d6d..0540d325c79 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -1,6 +1,5 @@ import Adapter from 'src/adapter'; import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; import * as utils from 'src/utils'; import { ajax } from 'src/ajax'; import { STATUS, S2S } from 'src/constants'; @@ -8,12 +7,106 @@ import { cookieSet } from 'src/cookie.js'; import adaptermanager from 'src/adaptermanager'; import { config } from 'src/config'; import { VIDEO } from 'src/mediaTypes'; +import { isValid } from 'src/adapters/bidderFactory'; +import includes from 'core-js/library/fn/array/includes'; const getConfig = config.getConfig; const TYPE = S2S.SRC; -const cookieSetUrl = 'https://acdn.adnxs.com/cookieset/cs.js'; let _synced = false; +const DEFAULT_S2S_TTL = 60; +const DEFAULT_S2S_CURRENCY = 'USD'; +const DEFAULT_S2S_NETREVENUE = true; + +let _s2sConfig; +config.setDefaults({ + 's2sConfig': { + enabled: false, + timeout: 1000, + maxBids: 1, + adapter: 'prebidServer' + } +}); + +/** + * Set config for server to server header bidding + * @typedef {Object} options - required + * @property {boolean} enabled enables S2S bidding + * @property {string[]} bidders bidders to request S2S + * @property {string} endpoint endpoint to contact + * === optional params below === + * @property {number} [timeout] timeout for S2S bidders - should be lower than `pbjs.requestBids({timeout})` + * @property {boolean} [cacheMarkup] whether to cache the adm result + * @property {string} [adapter] adapter code to use for S2S + * @property {string} [syncEndpoint] endpoint URL for syncing cookies + * @property {string} [cookieSetUrl] url for cookie set library, if passed then cookieSet is enabled + */ +function setS2sConfig(options) { + let keys = Object.keys(options); + + if (['accountId', 'bidders', 'endpoint'].filter(key => { + if (!includes(keys, key)) { + utils.logError(key + ' missing in server to server config'); + return true; + } + return false; + }).length > 0) { + return; + } + + _s2sConfig = options; + if (options.syncEndpoint) { + queueSync(options.bidders); + } +} +getConfig('s2sConfig', ({s2sConfig}) => setS2sConfig(s2sConfig)); + +/** + * @param {Array} bidderCodes list of bidders to request user syncs for. + */ +function queueSync(bidderCodes) { + if (_synced) { + return; + } + _synced = true; + const payload = JSON.stringify({ + uuid: utils.generateUUID(), + bidders: bidderCodes + }); + ajax(_s2sConfig.syncEndpoint, (response) => { + try { + response = JSON.parse(response); + response.bidder_status.forEach(bidder => doBidderSync(bidder.usersync.type, bidder.usersync.url, bidder.bidder)); + } catch (e) { + utils.logError(e); + } + }, + payload, { + contentType: 'text/plain', + withCredentials: true + }); +} + +/** + * Run a cookie sync for the given type, url, and bidder + * + * @param {string} type the type of sync, "image", "redirect", "iframe" + * @param {string} url the url to sync + * @param {string} bidder name of bidder doing sync for + */ +function doBidderSync(type, url, bidder) { + if (!url) { + utils.logError(`No sync url for bidder "${bidder}": ${url}`); + } else if (type === 'image' || type === 'redirect') { + utils.logMessage(`Invoking image pixel user sync for bidder: "${bidder}"`); + utils.triggerPixel(url); + } else if (type == 'iframe') { + utils.logMessage(`Invoking iframe user sync for bidder: "${bidder}"`); + utils.insertUserSyncIframe(url); + } else { + utils.logError(`User sync type "${type}" not supported for bidder: "${bidder}"`); + } +} /** * Try to convert a value to a type. @@ -73,18 +166,11 @@ const paramTypes = { }, }; -let _cookiesQueued = false; - /** * Bidder adapter for Prebid Server */ -function PrebidServer() { +export function PrebidServer() { let baseAdapter = new Adapter('prebidServer'); - let config; - - baseAdapter.setConfig = function(s2sconfig) { - config = s2sconfig; - }; function convertTypes(adUnits) { adUnits.forEach(adUnit => { @@ -92,11 +178,7 @@ function PrebidServer() { const types = paramTypes[bid.bidder] || []; Object.keys(types).forEach(key => { if (bid.params[key]) { - const converted = types[key](bid.params[key]); - if (converted !== bid.params[key]) { - utils.logMessage(`Mismatched type for Prebid Server : ${bid.bidder} : ${key}. Required Type:${types[key]}`); - } - bid.params[key] = converted; + bid.params[key] = types[key](bid.params[key]); // don't send invalid values if (isNaN(bid.params[key])) { @@ -104,33 +186,14 @@ 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; }); }); } /* Prebid executes this function when the page asks to send out bid requests */ - baseAdapter.callBids = function(bidRequest) { + baseAdapter.callBids = function(s2sBidRequest, bidRequests, addBidResponse, done, ajax) { const isDebug = !!getConfig('debug'); - const adUnits = utils.deepClone(bidRequest.ad_units); + const adUnits = utils.deepClone(s2sBidRequest.ad_units); adUnits.forEach(adUnit => { let videoMediaType = utils.deepAccess(adUnit, 'mediaTypes.video'); if (videoMediaType) { @@ -140,14 +203,15 @@ function PrebidServer() { // default is assumed to be 'banner' so if there is a video type we assume video only until PBS can support multi format auction. adUnit.media_types = [VIDEO]; } - }) + }); convertTypes(adUnits); let requestJson = { - account_id: config.accountId, - tid: bidRequest.tid, - max_bids: config.maxBids, - timeout_millis: config.timeout, - secure: config.secure, + account_id: _s2sConfig.accountId, + tid: s2sBidRequest.tid, + max_bids: _s2sConfig.maxBids, + timeout_millis: _s2sConfig.timeout, + secure: _s2sConfig.secure, + cache_markup: _s2sConfig.cacheMarkup, url: utils.getTopWindowUrl(), prebid_version: '$prebid.version$', ad_units: adUnits.filter(hasSizes), @@ -157,10 +221,10 @@ function PrebidServer() { // in case config.bidders contains invalid bidders, we only process those we sent requests for. const requestedBidders = requestJson.ad_units.map(adUnit => adUnit.bids.map(bid => bid.bidder).filter(utils.uniques)).reduce(utils.flatten).filter(utils.uniques); function processResponse(response) { - handleResponse(response, requestedBidders); + handleResponse(response, requestedBidders, bidRequests, addBidResponse, done); } const payload = JSON.stringify(requestJson); - ajax(config.endpoint, processResponse, payload, { + ajax(_s2sConfig.endpoint, processResponse, payload, { contentType: 'text/plain', withCredentials: true }); @@ -171,29 +235,8 @@ function PrebidServer() { return unit.sizes && unit.sizes.length; } - /** - * Run a cookie sync for the given type, url, and bidder - * - * @param {string} type the type of sync, "image", "redirect", "iframe" - * @param {string} url the url to sync - * @param {string} bidder name of bidder doing sync for - */ - function doBidderSync(type, url, bidder) { - if (!url) { - utils.logError(`No sync url for bidder "${bidder}": ${url}`); - } else if (type === 'image' || type === 'redirect') { - utils.logMessage(`Invoking image pixel user sync for bidder: "${bidder}"`); - utils.triggerPixel(url); - } else if (type == 'iframe') { - utils.logMessage(`Invoking iframe user sync for bidder: "${bidder}"`); - utils.insertUserSyncIframe(url); - } else { - utils.logError(`User sync type "${type}" not supported for bidder: "${bidder}"`); - } - } - /* Notify Prebid of bid responses so bids can get in the auction */ - function handleResponse(response, requestedBidders) { + function handleResponse(response, requestedBidders, bidRequests, addBidResponse, done) { let result; try { result = JSON.parse(response); @@ -201,7 +244,7 @@ function PrebidServer() { if (result.status === 'OK' || result.status === 'no_cookie') { if (result.bidder_status) { result.bidder_status.forEach(bidder => { - if (bidder.no_cookie && !_cookiesQueued) { + if (bidder.no_cookie) { doBidderSync(bidder.usersync.type, bidder.usersync.url, bidder.bidder); } }); @@ -217,7 +260,7 @@ function PrebidServer() { if (result.bids) { result.bids.forEach(bidObj => { - let bidRequest = utils.getBidRequest(bidObj.bid_id); + let bidRequest = utils.getBidRequest(bidObj.bid_id, bidRequests); let cpm = bidObj.price; let status; if (cpm !== 0) { @@ -231,6 +274,12 @@ function PrebidServer() { bidObject.creative_id = bidObj.creative_id; bidObject.bidderCode = bidObj.bidder; bidObject.cpm = cpm; + if (bidObj.cache_id) { + bidObject.cache_id = bidObj.cache_id; + } + if (bidObj.cache_url) { + bidObject.cache_url = bidObj.cache_url; + } // From ORTB see section 4.2.3: adm Optional means of conveying ad markup in case the bid wins; supersedes the win notice if markup is included in both. if (bidObj.media_type === VIDEO) { bidObject.mediaType = VIDEO; @@ -257,68 +306,36 @@ function PrebidServer() { if (bidObj.deal_id) { bidObject.dealId = bidObj.deal_id; } + bidObject.requestId = bidObj.bid_id; + bidObject.creativeId = bidObj.creative_id; + + // TODO: Remove when prebid-server returns ttl, currency and netRevenue + bidObject.ttl = (bidObj.ttl) ? bidObj.ttl : DEFAULT_S2S_TTL; + bidObject.currency = (bidObj.currency) ? bidObj.currency : DEFAULT_S2S_CURRENCY; + bidObject.netRevenue = (bidObj.netRevenue) ? bidObj.netRevenue : DEFAULT_S2S_NETREVENUE; - bidmanager.addBidResponse(bidObj.code, bidObject); + if (isValid(bidObj.code, bidObject, bidRequests)) { + addBidResponse(bidObj.code, bidObject); + } }); } - - const receivedBidIds = result.bids ? result.bids.map(bidObj => bidObj.bid_id) : []; - - // issue a no-bid response for every bid request that can not be matched with received bids - requestedBidders.forEach(bidder => { - utils - .getBidderRequestAllAdUnits(bidder) - .bids.filter(bidRequest => !receivedBidIds.includes(bidRequest.bidId)) - .forEach(bidRequest => { - let bidObject = bidfactory.createBid(STATUS.NO_BID, bidRequest); - bidObject.source = TYPE; - bidObject.adUnitCode = bidRequest.placementCode; - bidObject.bidderCode = bidRequest.bidder; - bidmanager.addBidResponse(bidObject.adUnitCode, bidObject); - }); - }); } - if (result.status === 'no_cookie' && config.cookieSet) { + if (result.status === 'no_cookie' && typeof _s2sConfig.cookieSetUrl === 'string') { // cookie sync - cookieSet(cookieSetUrl); + cookieSet(_s2sConfig.cookieSetUrl); } } catch (error) { utils.logError(error); } - if (!result || (result.status && result.status.includes('Error'))) { + if (!result || (result.status && includes(result.status, 'Error'))) { utils.logError('error parsing response: ', result.status); } + + done(); } - /** - * @param {} {bidders} list of bidders to request user syncs for. - */ - baseAdapter.queueSync = function({bidderCodes}) { - if (_synced) { - return; - } - _synced = true; - const payload = JSON.stringify({ - uuid: utils.generateUUID(), - bidders: bidderCodes - }); - ajax(config.syncEndpoint, (response) => { - try { - response = JSON.parse(response); - response.bidder_status.forEach(bidder => doBidderSync(bidder.usersync.type, bidder.usersync.url, bidder.bidder)); - } catch (e) { - utils.logError(e); - } - }, - payload, { - contentType: 'text/plain', - withCredentials: true - }); - }; return Object.assign(this, { - queueSync: baseAdapter.queueSync, - setConfig: baseAdapter.setConfig, callBids: baseAdapter.callBids, setBidderCode: baseAdapter.setBidderCode, type: TYPE @@ -326,5 +343,3 @@ function PrebidServer() { } adaptermanager.registerBidAdapter(new PrebidServer(), 'prebidServer'); - -module.exports = PrebidServer; diff --git a/modules/pubgearsBidAdapter.js b/modules/pubgearsBidAdapter.js deleted file mode 100644 index fd6ccee453a..00000000000 --- a/modules/pubgearsBidAdapter.js +++ /dev/null @@ -1,150 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var consts = require('src/constants.json'); -var utils = require('src/utils.js'); -var adaptermanager = require('src/adaptermanager'); -var d = document; -var SCRIPT = 'script'; -var PARAMS = 'params'; -var SIZES = 'sizes'; -var SIZE = 'size'; -var CPM = 'cpm'; -var AD = 'ad'; -var WIDTH = 'width'; -var HEIGHT = 'height'; -var PUB_ZONE = 'pub_zone'; -var GROSS_PRICE = 'gross_price'; -var RESOURCE = 'resource'; -var DETAIL = 'detail'; -var BIDDER_CODE_RESPONSE_KEY = 'bidderCode'; -var BIDDER_CODE = 'pubgears'; -var SCRIPT_ID = 'pg-header-tag'; -var ATTRIBUTE_PREFIX = 'data-bsm-'; -var SLOT_LIST_ATTRIBUTE = 'slot-list'; -var PUBLISHER_ATTRIBUTE = 'pub'; -var FLAG_ATTRIBUTE = 'flag'; -var PLACEMENT_CODE = 'placementCode'; -var BID_ID = 'bidId'; -var PUBLISHER_PARAM = 'publisherName'; -var PUB_ZONE_PARAM = 'pubZone'; -var BID_RECEIVED_EVENT_NAME = 'onBidResponse'; -var SLOT_READY_EVENT_NAME = 'onResourceComplete'; -var CREATIVE_TEMPLATE = decodeURIComponent("%3Cscript%3E%0A(function(define)%7B%0Adefine(function(a)%7B%0A%09var%20id%3D%20%22pg-ad-%22%20%2B%20Math.floor(Math.random()%20*%201e10)%2C%20d%3D%20document%0A%09d.write(\'%3Cdiv%20id%3D%22\'%2Bid%2B\'%22%3E%3C%2Fdiv%3E\')%0A%09a.push(%7B%0A%09%09pub%3A%20\'%25%25PUBLISHER_NAME%25%25\'%2C%0A%09%09pub_zone%3A%20\'%25%25PUB_ZONE%25%25\'%2C%0A%09%09sizes%3A%20%5B\'%25%25SIZE%25%25\'%5D%2C%0A%09%09flag%3A%20true%2C%0A%09%09container%3A%20d.getElementById(id)%2C%0A%09%7D)%3B%0A%7D)%7D)(function(f)%7Bvar%20key%3D\'uber_imps\'%2Ca%3Dthis%5Bkey%5D%3Dthis%5Bkey%5D%7C%7C%5B%5D%3Bf(a)%3B%7D)%3B%0A%3C%2Fscript%3E%0A%3Cscript%20src%3D%22%2F%2Fc.pubgears.com%2Ftags%2Fb%22%3E%3C%2Fscript%3E%0A"); -var TAG_URL = '//c.pubgears.com/tags/h'; -var publisher = ''; - -adaptermanager.registerBidAdapter(new PubGearsAdapter(), BIDDER_CODE); - -module.exports = PubGearsAdapter; - -function PubGearsAdapter() { - var proxy = null; - var pendingSlots = {}; - var initialized = false; - - this.callBids = callBids; - - function callBids(params) { - var bids = params[consts.JSON_MAPPING.PL_BIDS]; - var slots = bids.map(getSlotFromBidParam); - if (slots.length <= 0) { return; } - publisher = bids[0][PARAMS][PUBLISHER_PARAM]; - - bids.forEach(function(bid) { - var name = getSlotFromBidParam(bid); - pendingSlots[ name ] = bid; - }); - - proxy = proxy || getScript(SCRIPT_ID) || makeScript(slots, publisher, SCRIPT_ID, TAG_URL); - if (!initialized) { registerEventListeners(proxy); } - initialized = true; - } - function loadScript(script) { - var anchor = (function(scripts) { - return scripts[ scripts.length - 1 ]; - })(d.getElementsByTagName(SCRIPT)); - - return anchor.parentNode.insertBefore(script, anchor); - } - function getSlotFromBidParam(bid) { - var size = getSize(bid); - var params = bid[PARAMS]; - var slotName = params[PUB_ZONE_PARAM]; - return [ slotName, size ].join('@'); - } - function getSlotFromResource(resource) { - var size = resource[SIZE]; - var key = [ resource[PUB_ZONE], size ].join('@'); - return key; - } - function getSize(bid) { - var sizes = bid[SIZES]; - var size = Array.isArray(sizes[0]) ? sizes[0] : sizes; - return size.join('x'); - } - function makeScript(slots, publisher, id, url) { - var script = d.createElement(SCRIPT); - script.src = url; - script.id = id; - script.setAttribute(ATTRIBUTE_PREFIX + SLOT_LIST_ATTRIBUTE, slots.join(' ')); - script.setAttribute(ATTRIBUTE_PREFIX + FLAG_ATTRIBUTE, 'true'); - script.setAttribute(ATTRIBUTE_PREFIX + PUBLISHER_ATTRIBUTE, publisher); - - return loadScript(script); - } - function getScript(id) { - return d.getElementById(id); - } - function registerEventListeners(script) { - script.addEventListener(BID_RECEIVED_EVENT_NAME, onBid, true); - script.addEventListener(SLOT_READY_EVENT_NAME, onComplete, true); - } - function onBid(event) { - var data = event[DETAIL]; - var slotKey = getSlotFromResource(data[RESOURCE]); - var bidRequest = pendingSlots[slotKey]; - var adUnitCode = bidRequest[PLACEMENT_CODE]; - var bid = null; - - if (bidRequest) { - bid = buildResponse(data, bidRequest); - bidmanager.addBidResponse(adUnitCode, bid); - utils.logMessage('adding bid respoonse to "' + adUnitCode + '" for bid request "' + bidRequest[BID_ID] + '"'); - } else { - utils.logError('Cannot get placement id for slot "' + slotKey + '"'); - } - } - function buildResponse(eventData, bidRequest) { - var resource = eventData[RESOURCE]; - var dims = resource[SIZE].split('x'); - var price = Number(eventData[GROSS_PRICE]); - var status = isNaN(price) || price <= 0 ? 2 : 1; - - var response = bidfactory.createBid(status, bidRequest); - response[BIDDER_CODE_RESPONSE_KEY] = BIDDER_CODE; - - if (status !== 1) { return response; } - - response[AD] = getCreative(resource); - - response[CPM] = price / 1e3; - response[WIDTH] = dims[0]; - response[HEIGHT] = dims[1]; - return response; - } - function getCreative(resource) { - var token = '%%'; - var creative = CREATIVE_TEMPLATE; - var replacementValues = { - publisher_name: publisher, - pub_zone: resource[PUB_ZONE], - size: resource[SIZE] - }; - return utils.replaceTokenInString(creative, replacementValues, token); - } - function onComplete(event) { - var data = event[DETAIL]; - var slotKey = getSlotFromResource(data[RESOURCE]); - delete pendingSlots[slotKey]; - } -} diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js deleted file mode 100644 index 8176052f9e2..00000000000 --- a/modules/pubmaticBidAdapter.js +++ /dev/null @@ -1,233 +0,0 @@ -var utils = require('src/utils.js'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adaptermanager = require('src/adaptermanager'); -const constants = require('src/constants.json'); - -/** - * Adapter for requesting bids from Pubmatic. - * - * @returns {{callBids: _callBids}} - * @constructor - */ -const PubmaticAdapter = function PubmaticAdapter() { - let bids; - let usersync = false; - let _secure = 0; - let _protocol = (window.location.protocol === 'https:' ? (_secure = 1, 'https') : 'http') + '://'; - let iframe; - - let dealChannelValues = { - 1: 'PMP', - 5: 'PREF', - 6: 'PMPG' - }; - - let customPars = { - 'kadgender': 'gender', - 'age': 'kadage', - 'dctr': 'dctr', // Custom Targeting - 'wiid': 'wiid', // Wrapper Impression ID - 'profId': 'profId', // Legacy: Profile ID - 'verId': 'verId', // Legacy: version ID - 'pmzoneid': { // Zone ID - n: 'pmZoneId', - m: function(zoneId) { - if (utils.isStr(zoneId)) { - return zoneId.split(',').slice(0, 50).join(); - } else { - return undefined; - } - } - } - }; - - function _initConf() { - var conf = {}; - var currTime = new Date(); - - conf.SAVersion = '1100'; - conf.wp = 'PreBid'; - conf.js = 1; - conf.wv = constants.REPO_AND_VERSION; - _secure && (conf.sec = 1); - conf.screenResolution = screen.width + 'x' + screen.height; - conf.ranreq = Math.random(); - conf.inIframe = window != top ? '1' : '0'; - - // istanbul ignore else - if (window.navigator.cookieEnabled === false) { - conf.fpcd = '1'; - } - - try { - conf.pageURL = window.top.location.href; - conf.refurl = window.top.document.referrer; - } catch (e) { - conf.pageURL = window.location.href; - conf.refurl = window.document.referrer; - } - - conf.kltstamp = currTime.getFullYear() + - '-' + (currTime.getMonth() + 1) + - '-' + currTime.getDate() + - ' ' + currTime.getHours() + - ':' + currTime.getMinutes() + - ':' + currTime.getSeconds(); - conf.timezone = currTime.getTimezoneOffset() / 60 * -1; - - return conf; - } - - function _handleCustomParams(params, conf) { - // istanbul ignore else - if (!conf.kadpageurl) { - conf.kadpageurl = conf.pageURL; - } - - var key, value, entry; - for (key in customPars) { - // istanbul ignore else - if (customPars.hasOwnProperty(key)) { - value = params[key]; - // istanbul ignore else - if (value) { - entry = customPars[key]; - - if (typeof entry === 'object') { - value = entry.m(value, conf); - key = entry.n; - } else { - key = customPars[key]; - } - - if (utils.isStr(value)) { - conf[key] = value; - } else { - utils.logWarn('PubMatic: Ignoring param key: ' + customPars[key] + ', expects string-value, found ' + typeof value); - } - } - } - } - return conf; - } - - function _cleanSlot(slotName) { - // istanbul ignore else - if (utils.isStr(slotName)) { - return slotName.replace(/^\s+/g, '').replace(/\s+$/g, ''); - } - return ''; - } - - function _legacyExecution(conf, slots) { - var url = _generateLegacyCall(conf, slots); - iframe = utils.createInvisibleIframe(); - var elToAppend = document.getElementsByTagName('head')[0]; - elToAppend.insertBefore(iframe, elToAppend.firstChild); - var iframeDoc = utils.getIframeDocument(iframe); - var content = utils.createContentToExecuteExtScriptInFriendlyFrame(url); - content = content.replace(``, ``); - iframeDoc.write(content); - iframeDoc.close(); - } - - function _generateLegacyCall(conf, slots) { - var request_url = 'gads.pubmatic.com/AdServer/AdCallAggregator'; - return _protocol + request_url + '?' + utils.parseQueryStringParameters(conf) + 'adslots=' + encodeURIComponent('[' + slots.join(',') + ']'); - } - - function _initUserSync(pubId) { - // istanbul ignore else - if (!usersync) { - var iframe = utils.createInvisibleIframe(); - iframe.src = _protocol + 'ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p=' + pubId; - utils.insertElement(iframe, document); - usersync = true; - } - } - - function _callBids(params) { - var conf = _initConf(); - var slots = []; - - conf.pubId = 0; - bids = params.bids || []; - - for (var i = 0; i < bids.length; i++) { - var bid = bids[i]; - conf.pubId = conf.pubId || bid.params.publisherId; - conf = _handleCustomParams(bid.params, conf); - bid.params.adSlot = _cleanSlot(bid.params.adSlot); - bid.params.adSlot.length && slots.push(bid.params.adSlot); - } - - // istanbul ignore else - if (conf.pubId && slots.length > 0) { - _legacyExecution(conf, slots); - } - - _initUserSync(conf.pubId); - } - - $$PREBID_GLOBAL$$.handlePubmaticCallback = function(bidDetailsMap, progKeyValueMap) { - var i; - var adUnit; - var adUnitInfo; - var bid; - var bidResponseMap = bidDetailsMap; - var bidInfoMap = progKeyValueMap; - - if (!bidResponseMap || !bidInfoMap) { - return; - } - - for (i = 0; i < bids.length; i++) { - var adResponse; - bid = bids[i].params; - adUnit = bidResponseMap[bid.adSlot] || {}; - // adUnitInfo example: bidstatus=0;bid=0.0000;bidid=39620189@320x50;wdeal= - // if using DFP GPT, the params string comes in the format: - // "bidstatus;1;bid;5.0000;bidid;hb_test@468x60;wdeal;" - // the code below detects and handles this. - // istanbul ignore else - if (bidInfoMap[bid.adSlot] && bidInfoMap[bid.adSlot].indexOf('=') === -1) { - bidInfoMap[bid.adSlot] = bidInfoMap[bid.adSlot].replace(/([a-z]+);(.[^;]*)/ig, '$1=$2'); - } - - adUnitInfo = (bidInfoMap[bid.adSlot] || '').split(';').reduce(function(result, pair) { - var parts = pair.split('='); - result[parts[0]] = parts[1]; - return result; - }, {}); - - if (adUnitInfo.bidstatus === '1') { - adResponse = bidfactory.createBid(1); - adResponse.bidderCode = 'pubmatic'; - adResponse.adSlot = bid.adSlot; - adResponse.cpm = Number(adUnitInfo.bid); - adResponse.ad = unescape(adUnit.creative_tag); - adResponse.ad += utils.createTrackPixelIframeHtml(decodeURIComponent(adUnit.tracking_url)); - adResponse.width = adUnit.width; - adResponse.height = adUnit.height; - adResponse.dealId = adUnitInfo.wdeal; - adResponse.dealChannel = dealChannelValues[adUnit.deal_channel] || null; - - bidmanager.addBidResponse(bids[i].placementCode, adResponse); - } else { - // Indicate an ad was not returned - adResponse = bidfactory.createBid(2); - adResponse.bidderCode = 'pubmatic'; - bidmanager.addBidResponse(bids[i].placementCode, adResponse); - } - } - }; - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new PubmaticAdapter(), 'pubmatic'); - -module.exports = PubmaticAdapter; diff --git a/modules/pubwiseAnalyticsAdapter.js b/modules/pubwiseAnalyticsAdapter.js index 96ccb26f513..69227cd154a 100644 --- a/modules/pubwiseAnalyticsAdapter.js +++ b/modules/pubwiseAnalyticsAdapter.js @@ -23,7 +23,8 @@ const utils = require('src/utils'); const analyticsType = 'endpoint'; const analyticsName = 'PubWise Analytics: '; let defaultUrl = 'https://api.pubwise.io/api/v4/event/default/'; -let pubwiseVersion = '2.2'; +let pubwiseVersion = '3.0'; +let pubwiseSchema = 'AVOCET'; let configOptions = {site: '', endpoint: 'https://api.pubwise.io/api/v4/event/default/', debug: ''}; let pwAnalyticsEnabled = false; let utmKeys = {utm_source: '', utm_medium: '', utm_campaign: '', utm_term: '', utm_content: ''}; @@ -49,8 +50,7 @@ function enrichWithUTM(dataBag) { let newUtm = false; try { for (let prop in utmKeys) { - let urlValue = utils.getParameterByName(prop); - utmKeys[prop] = urlValue; + utmKeys[prop] = utils.getParameterByName(prop); if (utmKeys[prop] != '') { newUtm = true; dataBag[prop] = utmKeys[prop]; @@ -84,6 +84,7 @@ function sendEvent(eventType, data) { eventType: eventType, args: data, target_site: configOptions.site, + pubwiseSchema: pubwiseSchema, debug: configOptions.debug ? 1 : 0, }; diff --git a/modules/pulsepointBidAdapter.js b/modules/pulsepointBidAdapter.js index 82c8df9a9c1..2c1f6f9174d 100644 --- a/modules/pulsepointBidAdapter.js +++ b/modules/pulsepointBidAdapter.js @@ -1,85 +1,332 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var utils = require('src/utils.js'); -var adaptermanager = require('src/adaptermanager'); - -var PulsePointAdapter = function PulsePointAdapter() { - var getJsStaticUrl = window.location.protocol + '//tag-st.contextweb.com/getjs.static.js'; - var bidUrl = window.location.protocol + '//bid.contextweb.com/header/tag'; - - function _callBids(params) { - if (typeof window.pp === 'undefined') { - adloader.loadScript(getJsStaticUrl, function () { bid(params); }, true); - } else { - bid(params); - } - } +/* eslint dot-notation:0, quote-props:0 */ +import {logError, getTopWindowLocation} from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; + +const NATIVE_DEFAULTS = { + TITLE_LEN: 100, + DESCR_LEN: 200, + SPONSORED_BY_LEN: 50, + IMG_MIN: 150, + ICON_MIN: 50, +}; + +const DEFAULT_BID_TTL = 20; +const DEFAULT_CURRENCY = 'USD'; +const DEFAULT_NET_REVENUE = true; + +/** + * PulsePoint Bid Adapter. + * Contact: ExchangeTeam@pulsepoint.com + * + * Aliases - pulseLite and pulsepointLite are supported for backwards compatibility. + * Formats - Display/Native/Outstream formats supported. + * + */ +export const spec = { - function bid(params) { - var bids = params.bids; - for (var i = 0; i < bids.length; i++) { - var bidRequest = bids[i]; - requestBid(bidRequest); + code: 'pulsepoint', + + aliases: ['pulseLite', 'pulsepointLite'], + + supportedMediaTypes: ['native'], + + isBidRequestValid: bid => ( + !!(bid && bid.params && bid.params.cp && bid.params.ct) + ), + + buildRequests: bidRequests => { + const request = { + id: bidRequests[0].bidderRequestId, + imp: bidRequests.map(slot => impression(slot)), + site: site(bidRequests), + app: app(bidRequests), + device: device(), + }; + return { + method: 'POST', + url: '//bid.contextweb.com/header/ortb', + data: JSON.stringify(request), + }; + }, + + interpretResponse: (response, request) => ( + bidResponseAvailable(request, response) + ), + + getUserSyncs: syncOptions => { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: '//bh.contextweb.com/visitormatch' + }]; + } else if (syncOptions.pixelEnabled) { + return [{ + type: 'image', + url: '//bh.contextweb.com/visitormatch/prebid' + }]; } } - function requestBid(bidRequest) { - try { - var ppBidRequest = new window.pp.Ad(bidRequestOptions(bidRequest)); - ppBidRequest.display(); - } catch (e) { - // register passback on any exceptions while attempting to fetch response. - utils.logError('pulsepoint.requestBid', 'ERROR', e); - bidResponseAvailable(bidRequest); +}; + +/** + * Callback for bids, after the call to PulsePoint completes. + */ +function bidResponseAvailable(bidRequest, bidResponse) { + const idToImpMap = {}; + const idToBidMap = {}; + bidResponse = bidResponse.body + // extract the request bids and the response bids, keyed by impr-id + const ortbRequest = parse(bidRequest.data); + ortbRequest.imp.forEach(imp => { + idToImpMap[imp.id] = imp; + }); + if (bidResponse) { + bidResponse.seatbid.forEach(seatBid => seatBid.bid.forEach(bid => { + idToBidMap[bid.impid] = bid; + })); + } + 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, + ttl: DEFAULT_BID_TTL, + netRevenue: DEFAULT_NET_REVENUE, + currency: DEFAULT_CURRENCY + }; + if (idToImpMap[id]['native']) { + bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); + bid.mediaType = 'native'; + } else { + bid.ad = idToBidMap[id].adm; + 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. + */ +function impression(slot) { + return { + id: slot.bidId, + banner: banner(slot), + 'native': nativeImpression(slot), + tagid: slot.params.ct.toString(), + }; +} + +/** + * Produces an OpenRTB Banner object for the slot given. + */ +function banner(slot) { + const size = adSize(slot); + return slot.nativeParams ? null : { + w: size[0], + h: size[1], + }; +} - function bidRequestOptions(bidRequest) { - var callback = bidResponseCallback(bidRequest); - var options = { - cn: 1, - ca: window.pp.requestActions.BID, - cu: bidUrl, - adUnitId: bidRequest.placementCode, - callback: callback +/** + * Produces an OpenRTB Native object for the slot given. + */ +function nativeImpression(slot) { + if (slot.nativeParams) { + const assets = []; + addAsset(assets, titleAsset(assets.length + 1, slot.nativeParams.title, NATIVE_DEFAULTS.TITLE_LEN)); + addAsset(assets, dataAsset(assets.length + 1, slot.nativeParams.body, 2, NATIVE_DEFAULTS.DESCR_LEN)); + addAsset(assets, dataAsset(assets.length + 1, slot.nativeParams.sponsoredBy, 1, NATIVE_DEFAULTS.SPONSORED_BY_LEN)); + addAsset(assets, imageAsset(assets.length + 1, slot.nativeParams.icon, 1, NATIVE_DEFAULTS.ICON_MIN, NATIVE_DEFAULTS.ICON_MIN)); + addAsset(assets, imageAsset(assets.length + 1, slot.nativeParams.image, 3, NATIVE_DEFAULTS.IMG_MIN, NATIVE_DEFAULTS.IMG_MIN)); + return { + request: JSON.stringify({ assets }), + ver: '1.1', }; - for (var param in bidRequest.params) { - if (bidRequest.params.hasOwnProperty(param)) { - options[param] = bidRequest.params[param]; - } - } - return options; } + return null; +} - function bidResponseCallback(bid) { - return function (bidResponse) { - bidResponseAvailable(bid, bidResponse); +/** + * Helper method to add an asset to the assets list. + */ +function addAsset(assets, asset) { + if (asset) { + assets.push(asset); + } +} + +/** + * Produces a Native Title asset for the configuration given. + */ +function titleAsset(id, params, defaultLen) { + if (params) { + return { + id, + required: params.required ? 1 : 0, + title: { + len: params.len || defaultLen, + }, }; } + return null; +} + +/** + * Produces a Native Image asset for the configuration given. + */ +function imageAsset(id, params, type, defaultMinWidth, defaultMinHeight) { + return params ? { + id, + required: params.required ? 1 : 0, + img: { + type, + wmin: params.wmin || defaultMinWidth, + hmin: params.hmin || defaultMinHeight, + } + } : null; +} + +/** + * Produces a Native Data asset for the configuration given. + */ +function dataAsset(id, params, type, defaultLen) { + return params ? { + id, + required: params.required ? 1 : 0, + data: { + type, + len: params.len || defaultLen, + } + } : null; +} + +/** + * Produces an OpenRTB site object. + */ +function site(bidderRequest) { + const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.cp : '0'; + const appParams = bidderRequest[0].params.app; + if (!appParams) { + return { + publisher: { + id: pubId.toString(), + }, + ref: referrer(), + page: getTopWindowLocation().href, + } + } + return null; +} - function bidResponseAvailable(bidRequest, bidResponse) { - if (bidResponse) { - var adSize = bidRequest.params.cf.toUpperCase().split('X'); - var bid = bidfactory.createBid(1, bidRequest); - bid.bidderCode = bidRequest.bidder; - bid.cpm = bidResponse.bidCpm; - bid.ad = bidResponse.html; - bid.width = adSize[0]; - bid.height = adSize[1]; - bidmanager.addBidResponse(bidRequest.placementCode, bid); - } else { - var passback = bidfactory.createBid(2, bidRequest); - passback.bidderCode = bidRequest.bidder; - bidmanager.addBidResponse(bidRequest.placementCode, passback); +/** + * Produces an OpenRTB App object. + */ +function app(bidderRequest) { + const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.cp : '0'; + const appParams = bidderRequest[0].params.app; + if (appParams) { + return { + publisher: { + id: pubId.toString(), + }, + bundle: appParams.bundle, + storeurl: appParams.storeUrl, + domain: appParams.domain, } } + return null; +} +/** + * Attempts to capture the referrer url. + */ +function referrer() { + try { + return window.top.document.referrer; + } catch (e) { + return document.referrer; + } +} + +/** + * Produces an OpenRTB Device object. + */ +function device() { return { - callBids: _callBids + ua: navigator.userAgent, + language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), }; -}; +} + +/** + * Safely parses the input given. Returns null on + * parsing failure. + */ +function parse(rawResponse) { + try { + if (rawResponse) { + return JSON.parse(rawResponse); + } + } catch (ex) { + logError('pulsepointLite.safeParse', 'ERROR', ex); + } + return null; +} -adaptermanager.registerBidAdapter(new PulsePointAdapter(), 'pulsepoint'); +/** + * Determines the AdSize for the slot. + */ +function adSize(slot) { + if (slot.params.cf) { + const size = slot.params.cf.toUpperCase().split('X'); + const width = parseInt(slot.params.cw || size[0], 10); + const height = parseInt(slot.params.ch || size[1], 10); + return [width, height]; + } + return [1, 1]; +} + +/** + * Parses the native response from the Bid given. + */ +function nativeResponse(imp, bid) { + if (imp['native']) { + const nativeAd = parse(bid.adm); + const keys = {}; + if (nativeAd && nativeAd['native'] && nativeAd['native'].assets) { + nativeAd['native'].assets.forEach(asset => { + keys.title = asset.title ? asset.title.text : keys.title; + keys.body = asset.data && asset.data.type === 2 ? asset.data.value : keys.body; + keys.sponsoredBy = asset.data && asset.data.type === 1 ? asset.data.value : keys.sponsoredBy; + keys.image = asset.img && asset.img.type === 3 ? asset.img.url : keys.image; + keys.icon = asset.img && asset.img.type === 1 ? asset.img.url : keys.icon; + }); + if (nativeAd['native'].link) { + keys.clickUrl = encodeURIComponent(nativeAd['native'].link.url); + } + keys.impressionTrackers = nativeAd['native'].imptrackers; + return keys; + } + } + return null; +} -module.exports = PulsePointAdapter; +registerBidder(spec); diff --git a/modules/pulsepointLiteBidAdapter.md b/modules/pulsepointBidAdapter.md similarity index 77% rename from modules/pulsepointLiteBidAdapter.md rename to modules/pulsepointBidAdapter.md index 23c96758ca0..1b119f0499f 100644 --- a/modules/pulsepointLiteBidAdapter.md +++ b/modules/pulsepointBidAdapter.md @@ -1,6 +1,6 @@ # Overview -**Module Name**: PulsePoint Lite Bidder Adapter +**Module Name**: PulsePoint Bidder Adapter **Module Type**: Bidder Adapter **Maintainer**: ExchangeTeam@pulsepoint.com @@ -8,7 +8,8 @@ Connects to PulsePoint demand source to fetch bids. Banner, Outstream and Native formats are supported. -Please use ```pulseLite``` as the bidder code. +Please use ```pulsepoint``` as the bidder code. +```pulseLite``` and ```pulsepointLite``` aliases also supported as well. # Test Parameters ``` @@ -16,7 +17,7 @@ Please use ```pulseLite``` as the bidder code. code: 'banner-ad-div', sizes: [[300, 250]], bids: [{ - bidder: 'pulsepointLite', + bidder: 'pulsepoint', params: { cf: '300X250', cp: 512379, @@ -33,7 +34,7 @@ Please use ```pulseLite``` as the bidder code. sponsoredBy: { len: 20 } }, bids: [{ - bidder: 'pulseLite', + bidder: 'pulsepoint', params: { cp: 512379, ct: 505642 diff --git a/modules/pulsepointLiteBidAdapter.js b/modules/pulsepointLiteBidAdapter.js deleted file mode 100644 index d851245402c..00000000000 --- a/modules/pulsepointLiteBidAdapter.js +++ /dev/null @@ -1,330 +0,0 @@ -/* eslint dot-notation:0, quote-props:0 */ -import {logError, getTopWindowLocation} from 'src/utils'; -import { registerBidder } from 'src/adapters/bidderFactory'; - -const NATIVE_DEFAULTS = { - TITLE_LEN: 100, - DESCR_LEN: 200, - SPONSORED_BY_LEN: 50, - IMG_MIN: 150, - 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 - * dependencies and relies on a single OpenRTB request to the PulsePoint - * bidder instead of separate requests per slot. - */ -export const spec = { - - code: 'pulseLite', - - aliases: ['pulsepointLite'], - - supportedMediaTypes: ['native'], - - isBidRequestValid: bid => ( - !!(bid && bid.params && bid.params.cp && bid.params.ct) - ), - - buildRequests: bidRequests => { - const request = { - id: bidRequests[0].bidderRequestId, - imp: bidRequests.map(slot => impression(slot)), - site: site(bidRequests), - app: app(bidRequests), - device: device(), - }; - return { - method: 'POST', - url: '//bid.contextweb.com/header/ortb', - data: JSON.stringify(request), - }; - }, - - interpretResponse: (response, request) => ( - bidResponseAvailable(request, response) - ), - - getUserSyncs: syncOptions => { - if (syncOptions.iframeEnabled) { - return [{ - type: 'iframe', - url: '//bh.contextweb.com/visitormatch' - }]; - } else if (syncOptions.pixelEnabled) { - return [{ - type: 'image', - url: '//bh.contextweb.com/visitormatch/prebid' - }]; - } - } - -}; - -/** - * Callback for bids, after the call to PulsePoint completes. - */ -function bidResponseAvailable(bidRequest, bidResponse) { - const idToImpMap = {}; - const idToBidMap = {}; - bidResponse = bidResponse.body - // extract the request bids and the response bids, keyed by impr-id - const ortbRequest = parse(bidRequest.data); - ortbRequest.imp.forEach(imp => { - idToImpMap[imp.id] = imp; - }); - if (bidResponse) { - bidResponse.seatbid.forEach(seatBid => seatBid.bid.forEach(bid => { - idToBidMap[bid.impid] = bid; - })); - } - 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, - ttl: DEFAULT_BID_TTL, - netRevenue: DEFAULT_NET_REVENUE, - currency: DEFAULT_CURRENCY - }; - if (idToImpMap[id]['native']) { - bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); - bid.mediaType = 'native'; - } else { - bid.ad = idToBidMap[id].adm; - 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. - */ -function impression(slot) { - return { - id: slot.bidId, - banner: banner(slot), - 'native': nativeImpression(slot), - tagid: slot.params.ct.toString(), - }; -} - -/** - * Produces an OpenRTB Banner object for the slot given. - */ -function banner(slot) { - const size = adSize(slot); - return slot.nativeParams ? null : { - w: size[0], - h: size[1], - }; -} - -/** - * Produces an OpenRTB Native object for the slot given. - */ -function nativeImpression(slot) { - if (slot.nativeParams) { - const assets = []; - addAsset(assets, titleAsset(assets.length + 1, slot.nativeParams.title, NATIVE_DEFAULTS.TITLE_LEN)); - addAsset(assets, dataAsset(assets.length + 1, slot.nativeParams.body, 2, NATIVE_DEFAULTS.DESCR_LEN)); - addAsset(assets, dataAsset(assets.length + 1, slot.nativeParams.sponsoredBy, 1, NATIVE_DEFAULTS.SPONSORED_BY_LEN)); - addAsset(assets, imageAsset(assets.length + 1, slot.nativeParams.icon, 1, NATIVE_DEFAULTS.ICON_MIN, NATIVE_DEFAULTS.ICON_MIN)); - addAsset(assets, imageAsset(assets.length + 1, slot.nativeParams.image, 3, NATIVE_DEFAULTS.IMG_MIN, NATIVE_DEFAULTS.IMG_MIN)); - return { - request: JSON.stringify({ assets }), - ver: '1.1', - }; - } - return null; -} - -/** - * Helper method to add an asset to the assets list. - */ -function addAsset(assets, asset) { - if (asset) { - assets.push(asset); - } -} - -/** - * Produces a Native Title asset for the configuration given. - */ -function titleAsset(id, params, defaultLen) { - if (params) { - return { - id, - required: params.required ? 1 : 0, - title: { - len: params.len || defaultLen, - }, - }; - } - return null; -} - -/** - * Produces a Native Image asset for the configuration given. - */ -function imageAsset(id, params, type, defaultMinWidth, defaultMinHeight) { - return params ? { - id, - required: params.required ? 1 : 0, - img: { - type, - wmin: params.wmin || defaultMinWidth, - hmin: params.hmin || defaultMinHeight, - } - } : null; -} - -/** - * Produces a Native Data asset for the configuration given. - */ -function dataAsset(id, params, type, defaultLen) { - return params ? { - id, - required: params.required ? 1 : 0, - data: { - type, - len: params.len || defaultLen, - } - } : null; -} - -/** - * Produces an OpenRTB site object. - */ -function site(bidderRequest) { - const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.cp : '0'; - const appParams = bidderRequest[0].params.app; - if (!appParams) { - return { - publisher: { - id: pubId.toString(), - }, - ref: referrer(), - page: getTopWindowLocation().href, - } - } - return null; -} - -/** - * Produces an OpenRTB App object. - */ -function app(bidderRequest) { - const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.cp : '0'; - const appParams = bidderRequest[0].params.app; - if (appParams) { - return { - publisher: { - id: pubId.toString(), - }, - bundle: appParams.bundle, - storeurl: appParams.storeUrl, - domain: appParams.domain, - } - } - return null; -} - -/** - * Attempts to capture the referrer url. - */ -function referrer() { - try { - return window.top.document.referrer; - } catch (e) { - return document.referrer; - } -} - -/** - * Produces an OpenRTB Device object. - */ -function device() { - return { - ua: navigator.userAgent, - language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), - }; -} - -/** - * Safely parses the input given. Returns null on - * parsing failure. - */ -function parse(rawResponse) { - try { - if (rawResponse) { - return JSON.parse(rawResponse); - } - } catch (ex) { - logError('pulsepointLite.safeParse', 'ERROR', ex); - } - return null; -} - -/** - * Determines the AdSize for the slot. - */ -function adSize(slot) { - if (slot.params.cf) { - const size = slot.params.cf.toUpperCase().split('X'); - const width = parseInt(slot.params.cw || size[0], 10); - const height = parseInt(slot.params.ch || size[1], 10); - return [width, height]; - } - return [1, 1]; -} - -/** - * Parses the native response from the Bid given. - */ -function nativeResponse(imp, bid) { - if (imp['native']) { - const nativeAd = parse(bid.adm); - const keys = {}; - if (nativeAd && nativeAd['native'] && nativeAd['native'].assets) { - nativeAd['native'].assets.forEach(asset => { - keys.title = asset.title ? asset.title.text : keys.title; - keys.body = asset.data && asset.data.type === 2 ? asset.data.value : keys.body; - keys.sponsoredBy = asset.data && asset.data.type === 1 ? asset.data.value : keys.sponsoredBy; - keys.image = asset.img && asset.img.type === 3 ? asset.img.url : keys.image; - keys.icon = asset.img && asset.img.type === 1 ? asset.img.url : keys.icon; - }); - if (nativeAd['native'].link) { - keys.clickUrl = encodeURIComponent(nativeAd['native'].link.url); - } - keys.impressionTrackers = nativeAd['native'].imptrackers; - return keys; - } - } - return null; -} - -registerBidder(spec); diff --git a/modules/realvuBidAdapter.js b/modules/realvuBidAdapter.js deleted file mode 100644 index dfed3d64370..00000000000 --- a/modules/realvuBidAdapter.js +++ /dev/null @@ -1,238 +0,0 @@ -import { getBidRequest } from 'src/utils'; -import adaptermanager from 'src/adaptermanager'; - -const CONSTANTS = require('src/constants'); -const utils = require('src/utils.js'); -const adloader = require('src/adloader.js'); -const bidmanager = require('src/bidmanager.js'); -const bidfactory = require('src/bidfactory.js'); -const Adapter = require('src/adapter.js').default; - -var RealVuAdapter = function RealVuAdapter() { - var baseAdapter = new Adapter('realvu'); - baseAdapter.callBids = function (params) { - var pbids = params.bids; - var boost_back = function() { - var top1 = window; - try { - var wnd = window; - while ((top1 != top) && (typeof (wnd.document) != 'undefined')) { - top1 = wnd; - wnd = wnd.parent; - } - } catch (e) { }; - for (var i = 0; i < pbids.length; i++) { - var bid_rq = pbids[i]; - var sizes = utils.parseSizesInput(bid_rq.sizes); - top1.realvu_boost.addUnitById({ - partner_id: bid_rq.params.partnerId, - unit_id: bid_rq.placementCode, - callback: baseAdapter.boostCall, - pbjs_bid: bid_rq, - size: sizes[0], - mode: 'kvp' - }); - } - }; - adloader.loadScript('//ac.realvu.net/realvu_boost.js', boost_back, 1); - }; - - baseAdapter.boostCall = function(rez) { - var bid_request = rez.pin.pbjs_bid; - var callbackId = bid_request.bidId; - if (rez.realvu === 'yes') { - var adap = new RvAppNexusAdapter(); - adloader.loadScript(adap.buildJPTCall(bid_request, callbackId)); - } else { // not in view - respond with no bid. - var adResponse = bidfactory.createBid(2); - adResponse.bidderCode = 'realvu'; - bidmanager.addBidResponse(bid_request.placementCode, adResponse); - } - }; - - // +copy/pasted appnexusBidAdapter, "handleAnCB" replaced with "handleRvAnCB" - var RvAppNexusAdapter = function RvAppNexusAdapter() { - var usersync = false; - - this.buildJPTCall = function (bid, callbackId) { - // determine tag params - var placementId = utils.getBidIdParameter('placementId', bid.params); - - // memberId will be deprecated, use member instead - var memberId = utils.getBidIdParameter('memberId', bid.params); - var member = utils.getBidIdParameter('member', bid.params); - var inventoryCode = utils.getBidIdParameter('invCode', bid.params); - var query = utils.getBidIdParameter('query', bid.params); - var referrer = utils.getBidIdParameter('referrer', bid.params); - 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_uid', callbackId); - jptCall = utils.tryAppendQueryString(jptCall, 'psa', '0'); - jptCall = utils.tryAppendQueryString(jptCall, 'id', placementId); - if (member) { - jptCall = utils.tryAppendQueryString(jptCall, 'member', member); - } else if (memberId) { - jptCall = utils.tryAppendQueryString(jptCall, 'member', memberId); - utils.logMessage('appnexus.callBids: "memberId" will be deprecated soon. Please use "member" instead'); - } - - jptCall = utils.tryAppendQueryString(jptCall, 'code', inventoryCode); - jptCall = utils.tryAppendQueryString(jptCall, 'traffic_source_code', (utils.getBidIdParameter('trafficSourceCode', bid.params))); - - // sizes takes a bit more logic - var sizeQueryString = ''; - var parsedSizes = utils.parseSizesInput(bid.sizes); - - // combine string into proper querystring for impbus - var parsedSizesLength = parsedSizes.length; - if (parsedSizesLength > 0) { - // first value should be "size" - sizeQueryString = 'size=' + parsedSizes[0]; - if (parsedSizesLength > 1) { - // any subsequent values should be "promo_sizes" - sizeQueryString += '&promo_sizes='; - for (var j = 1; j < parsedSizesLength; j++) { - sizeQueryString += parsedSizes[j] += ','; - } - - // remove trailing comma - if (sizeQueryString && sizeQueryString.charAt(sizeQueryString.length - 1) === ',') { - sizeQueryString = sizeQueryString.slice(0, sizeQueryString.length - 1); - } - } - } - - if (sizeQueryString) { - jptCall += sizeQueryString + '&'; - } - - // this will be deprecated soon - var targetingParams = utils.parseQueryStringParameters(query); - - if (targetingParams) { - // don't append a & here, we have already done it in parseQueryStringParameters - jptCall += targetingParams; - } - - // append custom attributes: - var paramsCopy = Object.assign({}, bid.params); - - // delete attributes already used - delete paramsCopy.placementId; - delete paramsCopy.memberId; - delete paramsCopy.invCode; - delete paramsCopy.query; - delete paramsCopy.referrer; - delete paramsCopy.alt_referrer; - delete paramsCopy.member; - - // get the reminder - var queryParams = utils.parseQueryStringParameters(paramsCopy); - - // append - if (queryParams) { - jptCall += queryParams; - } - - // append referrer - if (referrer === '') { - referrer = utils.getTopWindowUrl(); - } - - jptCall = utils.tryAppendQueryString(jptCall, 'referrer', referrer); - jptCall = utils.tryAppendQueryString(jptCall, 'alt_referrer', altReferrer); - - // remove the trailing "&" - if (jptCall.lastIndexOf('&') === jptCall.length - 1) { - jptCall = jptCall.substring(0, jptCall.length - 1); - } - - // @if NODE_ENV='debug' - utils.logMessage('jpt request built: ' + jptCall); - // @endif - - // append a timer here to track latency - bid.startTime = new Date().getTime(); - - return jptCall; - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.handleRvAnCB = function (jptResponseObj) { - var bidCode; - - if (jptResponseObj && jptResponseObj.callback_uid) { - var responseCPM; - var id = jptResponseObj.callback_uid; - var placementCode = ''; - var bidObj = getBidRequest(id); - if (bidObj) { - bidCode = bidObj.bidder; - - placementCode = bidObj.placementCode; - - // set the status - bidObj.status = CONSTANTS.STATUS.GOOD; - } - - // @if NODE_ENV='debug' - utils.logMessage('JSONP callback function called for ad ID: ' + id); - - // @endif - var bid = []; - if (jptResponseObj.result && jptResponseObj.result.cpm && jptResponseObj.result.cpm !== 0) { - responseCPM = parseInt(jptResponseObj.result.cpm, 10); - - // CPM response from /jpt is dollar/cent multiplied by 10000 - // in order to avoid using floats - // switch CPM to "dollar/cent" - responseCPM = responseCPM / 10000; - - // store bid response - // bid status is good (indicating 1) - var adId = jptResponseObj.result.creative_id; - bid = bidfactory.createBid(1, bidObj); - bid.creative_id = adId; - bid.bidderCode = bidCode; - bid.cpm = responseCPM; - bid.adUrl = jptResponseObj.result.ad; - bid.width = jptResponseObj.result.width; - bid.height = jptResponseObj.result.height; - bid.dealId = jptResponseObj.result.deal_id; - - bidmanager.addBidResponse(placementCode, bid); - } else { - // no bid - bid = bidfactory.createBid(2, bidObj); - bid.bidderCode = bidCode; - bidmanager.addBidResponse(placementCode, bid); - } - - if (!usersync) { - var iframe = utils.createInvisibleIframe(); - iframe.src = '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html'; - try { - document.body.appendChild(iframe); - } catch (error) { - utils.logError(error); - } - usersync = true; - } - } else { - utils.logMessage('No prebid response for placement %%PLACEMENT%%'); - } - }; - }; - // -copy/pasted appnexusBidAdapter - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - boostCall: baseAdapter.boostCall - }); -}; - -adaptermanager.registerBidAdapter(new RealVuAdapter(), 'realvu'); - -module.exports = RealVuAdapter; diff --git a/modules/roxotAnalyticsAdapter.js b/modules/roxotAnalyticsAdapter.js index 0a274660699..65771ad245d 100644 --- a/modules/roxotAnalyticsAdapter.js +++ b/modules/roxotAnalyticsAdapter.js @@ -1,6 +1,7 @@ import adapter from 'src/AnalyticsAdapter'; import CONSTANTS from 'src/constants.json'; import adaptermanager from 'src/adaptermanager'; +import includes from 'core-js/library/fn/array/includes'; const utils = require('src/utils'); @@ -106,7 +107,7 @@ function checkAdUnitConfig() { function buildBidWon(eventType, args) { bidWon.options = initOptions; if (checkAdUnitConfig()) { - if (initOptions.adUnits.includes(args.adUnitCode)) { + if (includes(initOptions.adUnits, args.adUnitCode)) { bidWon.events = [{ args: args, eventType: eventType }]; } } else { @@ -121,7 +122,7 @@ function buildEventStack() { function filterBidsByAdUnit(bids) { var filteredBids = []; bids.forEach(function (bid) { - if (initOptions.adUnits.includes(bid.placementCode)) { + if (includes(initOptions.adUnits, bid.placementCode)) { filteredBids.push(bid); } }); @@ -131,7 +132,7 @@ function filterBidsByAdUnit(bids) { function isValidEvent(eventType, adUnitCode) { if (checkAdUnitConfig()) { let validationEvents = [bidAdjustmentConst, bidResponseConst, bidWonConst]; - if (!initOptions.adUnits.includes(adUnitCode) && validationEvents.includes(eventType)) { + if (!includes(initOptions.adUnits, adUnitCode) && includes(validationEvents, eventType)) { return false; } } diff --git a/modules/roxotBidAdapter.js b/modules/roxotBidAdapter.js deleted file mode 100644 index a2b9b6ca6dc..00000000000 --- a/modules/roxotBidAdapter.js +++ /dev/null @@ -1,116 +0,0 @@ -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'); - -var RoxotAdapter = function RoxotAdapter() { - var roxotUrl = 'r.rxthdr.com'; - - $$PREBID_GLOBAL$$.roxotResponseHandler = roxotResponseHandler; - - return { - callBids: _callBids - }; - - function _callBids(bidReqs) { - utils.logInfo('callBids roxot adapter invoking'); - - var domain = window.location.host; - var page = window.location.pathname + location.search + location.hash; - - var roxotBidReqs = { - id: utils.getUniqueIdentifierStr(), - bids: bidReqs, - site: { - domain: domain, - page: page - } - }; - - var scriptUrl = '//' + roxotUrl + '?callback=$$PREBID_GLOBAL$$.roxotResponseHandler' + - '&src=' + CONSTANTS.REPO_AND_VERSION + - '&br=' + encodeURIComponent(JSON.stringify(roxotBidReqs)); - - adloader.loadScript(scriptUrl); - } - - function roxotResponseHandler(roxotResponseObject) { - utils.logInfo('roxotResponseHandler invoking'); - var placements = []; - - if (isResponseInvalid()) { - return fillPlacementEmptyBid(); - } - - roxotResponseObject.bids.forEach(pushRoxotBid); - var allBidResponse = fillPlacementEmptyBid(placements); - utils.logInfo('roxotResponse handler finish'); - - return allBidResponse; - - function isResponseInvalid() { - return !roxotResponseObject || !roxotResponseObject.bids || !Array.isArray(roxotResponseObject.bids) || roxotResponseObject.bids.length <= 0; - } - - function pushRoxotBid(roxotBid) { - var placementCode = ''; - - var bidReq = $$PREBID_GLOBAL$$ - ._bidsRequested.find(bidSet => bidSet.bidderCode === 'roxot') - .bids.find(bid => bid.bidId === roxotBid.bidId); - - if (!bidReq) { - return pushErrorBid(placementCode); - } - - bidReq.status = CONSTANTS.STATUS.GOOD; - - placementCode = bidReq.placementCode; - placements.push(placementCode); - - var cpm = roxotBid.cpm; - var responseNurl = ''; - - if (!cpm) { - return pushErrorBid(placementCode); - } - - var bid = bidfactory.createBid(1, bidReq); - - bid.creative_id = roxotBid.id; - bid.bidderCode = 'roxot'; - bid.cpm = cpm; - bid.ad = decodeURIComponent(roxotBid.adm + responseNurl); - bid.width = parseInt(roxotBid.w); - bid.height = parseInt(roxotBid.h); - - bidmanager.addBidResponse(placementCode, bid); - } - - function fillPlacementEmptyBid(places) { - $$PREBID_GLOBAL$$ - ._bidsRequested.find(bidSet => bidSet.bidderCode === 'roxot') - .bids.forEach(fillIfNotFilled); - - function fillIfNotFilled(bid) { - if (utils.contains(places, bid.placementCode)) { - return null; - } - - pushErrorBid(bid); - } - } - - function pushErrorBid(bidRequest) { - var bid = bidfactory.createBid(2, bidRequest); - bid.bidderCode = 'roxot'; - bidmanager.addBidResponse(bidRequest.placementCode, bid); - } - } -}; - -adaptermanager.registerBidAdapter(new RoxotAdapter(), 'roxot'); - -module.exports = RoxotAdapter; diff --git a/modules/rubiconBidAdapter.js b/modules/rubiconBidAdapter.js index 5c7a3dbd05c..48fe18677e0 100644 --- a/modules/rubiconBidAdapter.js +++ b/modules/rubiconBidAdapter.js @@ -118,6 +118,7 @@ export const spec = { resolution: _getScreenResolution(), account_id: params.accountId, integration: INTEGRATION, + 'x_source.tid': bidRequest.transactionId, timeout: bidderRequest.timeout - (Date.now() - bidderRequest.auctionStart + TIMEOUT_BUFFER), stash_creatives: true, ae_pass_through_parameters: params.video.aeParams, @@ -192,7 +193,7 @@ export const spec = { 'rp_floor', floor, 'rp_secure', isSecure() ? '1' : '0', 'tk_flint', INTEGRATION, - 'tid', bidRequest.transactionId, + 'x_source.tid', bidRequest.transactionId, 'p_screen_res', _getScreenResolution(), 'kw', keywords, 'tk_user_key', userId diff --git a/modules/rubiconBidAdapter.md b/modules/rubiconBidAdapter.md new file mode 100644 index 00000000000..b1871882a9a --- /dev/null +++ b/modules/rubiconBidAdapter.md @@ -0,0 +1,48 @@ +# Overview + +``` +Module Name: Rubicon Project Bid Adapter +Module Type: Bidder Adapter +Maintainer: header-bidding@rubiconproject.com +``` + +# Description + +Connect to Rubicon Project's exchange for bids. + +The Rubicon Project adapter requires setup and approval from the +Rubicon Project team. Please reach out to your account team or +globalsupport@rubiconproject.com for more information. + +# Test Parameters +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300, 250]], + bids: [ + { + bidder: "rubicon", + params: { + accountId: 1001, + siteId: 113932, + zoneId: 535510 + } + } + ] + },{ + code: 'test-div', + sizes: [[300, 50]], + bids: [ + { + bidder: "rubicon", + params: { + accountId: 1001, + siteId: 113932, + zoneId: 535510 + } + } + ] + } + ]; +``` diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js deleted file mode 100644 index d815f69c752..00000000000 --- a/modules/smartadserverBidAdapter.js +++ /dev/null @@ -1,60 +0,0 @@ -var utils = require('src/utils.js'); -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var url = require('src/url.js'); -var adaptermanager = require('src/adaptermanager'); - -var SmartAdServer = function SmartAdServer() { - var generateCallback = function(bid) { - var callbackId = 'sas_' + utils.getUniqueIdentifierStr(); - $$PREBID_GLOBAL$$[callbackId] = function(adUnit) { - var bidObject; - if (adUnit) { - utils.logMessage(`[SmartAdServer] bid response for placementCode ${bid.placementCode}`); - bidObject = bidfactory.createBid(1); - bidObject.bidderCode = 'smartadserver'; - bidObject.cpm = adUnit.cpm; - bidObject.currency = adUnit.currency; - bidObject.ad = adUnit.ad; - bidObject.width = adUnit.width; - bidObject.height = adUnit.height; - bidObject.dealId = adUnit.dealId; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } else { - utils.logMessage(`[SmartAdServer] no bid response for placementCode ${bid.placementCode}`); - bidObject = bidfactory.createBid(2); - bidObject.bidderCode = 'smartadserver'; - bidmanager.addBidResponse(bid.placementCode, bidObject); - } - }; - return callbackId; - }; - - return { - callBids: function(params) { - for (var i = 0; i < params.bids.length; i++) { - var bid = params.bids[i]; - var adCall = url.parse(bid.params.domain); - adCall.pathname = '/prebid'; - adCall.search = { - 'pbjscbk': '$$PREBID_GLOBAL$$.' + generateCallback(bid), - 'siteid': bid.params.siteId, - 'pgid': bid.params.pageId, - 'fmtid': bid.params.formatId, - 'ccy': bid.params.currency || 'USD', - 'bidfloor': bid.params.bidfloor || 0.0, - 'tgt': encodeURIComponent(bid.params.target || ''), - 'tag': bid.placementCode, - 'sizes': bid.sizes.map(size => size[0] + 'x' + size[1]).join(','), - 'async': 1 - }; - adloader.loadScript(url.format(adCall)); - } - } - }; -}; - -adaptermanager.registerBidAdapter(new SmartAdServer(), 'smartadserver'); - -module.exports = SmartAdServer; diff --git a/modules/smartyadsBidAdapter.js b/modules/smartyadsBidAdapter.js deleted file mode 100644 index 89f93f393c7..00000000000 --- a/modules/smartyadsBidAdapter.js +++ /dev/null @@ -1,180 +0,0 @@ -import Adapter from 'src/adapter'; -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import * as utils from 'src/utils'; -import {ajax} from 'src/ajax'; -import {STATUS} from 'src/constants'; -import adaptermanager from 'src/adaptermanager'; - -const SMARTYADS_BIDDER_CODE = 'smartyads'; - -var sizeMap = { - 1: '468x60', - 2: '728x90', - 8: '120x600', - 9: '160x600', - 10: '300x600', - 15: '300x250', - 16: '336x280', - 19: '300x100', - 43: '320x50', - 44: '300x50', - 48: '300x300', - 54: '300x1050', - 55: '970x90', - 57: '970x250', - 58: '1000x90', - 59: '320x80', - 61: '1000x1000', - 65: '640x480', - 67: '320x480', - 68: '1800x1000', - 72: '320x320', - 73: '320x160', - 83: '480x300', - 94: '970x310', - 96: '970x210', - 101: '480x320', - 102: '768x1024', - 113: '1000x300', - 117: '320x100', - 125: '800x250', - 126: '200x600' -}; - -utils._each(sizeMap, (item, key) => sizeMap[item] = key); - -function SmartyadsAdapter() { - function _callBids(bidderRequest) { - var bids = bidderRequest.bids || []; - - bids.forEach((bid) => { - try { - ajax(buildOptimizedCall(bid), bidCallback, undefined, { withCredentials: true }); - } catch (err) { - utils.logError('Error sending smartyads request for placement code ' + bid.placementCode, null, err); - } - - function bidCallback(responseText) { - try { - utils.logMessage('XHR callback function called for ad ID: ' + bid.bidId); - handleRpCB(responseText, bid); - } catch (err) { - if (typeof err === 'string') { - utils.logWarn(`${err} when processing smartyads response for placement code ${bid.placementCode}`); - } else { - utils.logError('Error processing smartyads response for placement code ' + bid.placementCode, null, err); - } - - // indicate that there is no bid for this placement - let badBid = bidfactory.createBid(STATUS.NO_BID, bid); - badBid.bidderCode = bid.bidder; - badBid.error = err; - bidmanager.addBidResponse(bid.placementCode, badBid); - } - } - }); - } - - function buildOptimizedCall(bid) { - bid.startTime = new Date().getTime(); - - // use smartyads sizes if provided, otherwise adUnit.sizes - var parsedSizes = SmartyadsAdapter.masSizeOrdering( - Array.isArray(bid.params.sizes) ? bid.params.sizes.map(size => (sizeMap[size] || '').split('x')) : bid.sizes - ); - - if (parsedSizes.length < 1) { - throw 'no valid sizes'; - } - - var secure; - if (window.location.protocol !== 'http:') { - secure = 1; - } else { - secure = 0; - } - - const host = window.location.host; - const page = window.location.pathname; - const language = navigator.language; - const deviceWidth = window.screen.width; - const deviceHeight = window.screen.height; - - var queryString = [ - 'banner_id', bid.params.banner_id, - 'size_ad', parsedSizes[0], - 'alt_size_ad', parsedSizes.slice(1).join(',') || undefined, - 'host', host, - 'page', page, - 'language', language, - 'deviceWidth', deviceWidth, - 'deviceHeight', deviceHeight, - 'secure', secure, - 'bidId', bid.bidId, - 'checkOn', 'rf' - ]; - - return queryString.reduce( - (memo, curr, index) => - index % 2 === 0 && queryString[index + 1] !== undefined - ? memo + curr + '=' + encodeURIComponent(queryString[index + 1]) + '&' - : memo, - '//ssp-nj.webtradehub.com/?' - ).slice(0, -1); - } - - function handleRpCB(responseText, bidRequest) { - let ad = JSON.parse(responseText); // can throw - - var bid = bidfactory.createBid(STATUS.GOOD, bidRequest); - bid.creative_id = ad.ad_id; - bid.bidderCode = bidRequest.bidder; - bid.cpm = ad.cpm || 0; - bid.ad = ad.adm; - bid.width = ad.width; - bid.height = ad.height; - bid.dealId = ad.deal; - - bidmanager.addBidResponse(bidRequest.placementCode, bid); - } - - return Object.assign(new Adapter(SMARTYADS_BIDDER_CODE), { // SMARTYADS_BIDDER_CODE smartyads - callBids: _callBids - }); -} - -SmartyadsAdapter.masSizeOrdering = function (sizes) { - const MAS_SIZE_PRIORITY = [15, 2, 9]; - - return utils.parseSizesInput(sizes) - // map sizes while excluding non-matches - .reduce((result, size) => { - let mappedSize = parseInt(sizeMap[size], 10); - if (mappedSize) { - result.push(mappedSize); - } - return result; - }, []) - .sort((first, second) => { - // sort by MAS_SIZE_PRIORITY priority order - const firstPriority = MAS_SIZE_PRIORITY.indexOf(first); - const secondPriority = MAS_SIZE_PRIORITY.indexOf(second); - - if (firstPriority > -1 || secondPriority > -1) { - if (firstPriority === -1) { - return 1; - } - if (secondPriority === -1) { - return -1; - } - return firstPriority - secondPriority; - } - - return first - second; - }); -}; - -adaptermanager.registerBidAdapter(new SmartyadsAdapter(), 'smartyads'); - -module.exports = SmartyadsAdapter; diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js deleted file mode 100644 index 689de8635c9..00000000000 --- a/modules/sonobiBidAdapter.js +++ /dev/null @@ -1,118 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var utils = require('src/utils'); -var adaptermanager = require('src/adaptermanager'); - -var SonobiAdapter = function SonobiAdapter() { - var keymakerAssoc = {}; // Remember placement codes for callback mapping - var bidReqAssoc = {}; // Remember bids for bid complete reporting - - function _phone_in(request) { - var trinity = 'https://apex.go.sonobi.com/trinity.js?key_maker='; - var adSlots = request.bids || []; - var bidderRequestId = request.bidderRequestId; - var ref = '&ref=' + encodeURI(utils.getTopWindowLocation().host); - adloader.loadScript(trinity + JSON.stringify(_keymaker(adSlots)) + '&cv=' + _operator(bidderRequestId) + ref); - } - - function _keymaker(adSlots) { - var keyring = {}; - utils._each(adSlots, function(bidRequest) { - if (bidRequest.params) { - // Optional - var floor = (bidRequest.params.floor) ? bidRequest.params.floor : null; - // Mandatory - var slotIdentifier = (bidRequest.params.ad_unit) ? bidRequest.params.ad_unit : (bidRequest.params.placement_id) ? bidRequest.params.placement_id : null; - var sizes = (bidRequest.params.sizes) ? bidRequest.params.sizes : bidRequest.sizes || null; - sizes = utils.parseSizesInput(sizes).toString(); - - if (utils.isEmpty(sizes)) { - utils.logError('Sonobi adapter expects sizes for ' + bidRequest.placementCode); - } - - var bidId = bidRequest.bidId; - - var args = (sizes) ? ((floor) ? (sizes + '|f=' + floor) : (sizes)) : (floor) ? ('f=' + floor) : ''; - if (/^[\/]?[\d]+[[\/].+[\/]?]?$/.test(slotIdentifier)) { - slotIdentifier = slotIdentifier.charAt(0) === '/' ? slotIdentifier : '/' + slotIdentifier; - keyring[slotIdentifier + '|' + bidId] = args; - keymakerAssoc[slotIdentifier + '|' + bidId] = bidRequest.placementCode; - bidReqAssoc[bidRequest.placementCode] = bidRequest; - } else if (/^[0-9a-fA-F]{20}$/.test(slotIdentifier) && slotIdentifier.length === 20) { - keyring[bidId] = slotIdentifier + '|' + args; - keymakerAssoc[bidId] = bidRequest.placementCode; - bidReqAssoc[bidRequest.placementCode] = bidRequest; - } else { - keymakerAssoc[bidId] = bidRequest.placementCode; - bidReqAssoc[bidRequest.placementCode] = bidRequest; - _failure(bidRequest.placementCode); - utils.logError('The ad unit code or Sonobi Placement id for slot ' + bidRequest.placementCode + ' is invalid'); - } - } - }); - return keyring; - } - - function _operator(bidderRequestId) { - var cb_name = 'sbi_' + bidderRequestId; - window[cb_name] = _trinity; - return cb_name; - } - - function _trinity(response) { - var slots = response.slots || {}; - var sbi_dc = response.sbi_dc || ''; - utils._each(slots, function(bid, slot_id) { - var placementCode = keymakerAssoc[slot_id]; - if (bid.sbi_aid && bid.sbi_mouse && bid.sbi_size) { - _success(placementCode, sbi_dc, bid); - } else { - _failure(placementCode); - } - delete keymakerAssoc[slot_id]; - }); - } - - function _seraph(placementCode) { - var theOne = bidReqAssoc[placementCode]; - delete bidReqAssoc[placementCode]; - return theOne; - } - - function _success(placementCode, sbi_dc, bid) { - var goodBid = bidfactory.createBid(1, _seraph(placementCode)); - if (bid.sbi_dozer) { - goodBid.dealId = bid.sbi_dozer; - } - goodBid.bidderCode = 'sonobi'; - goodBid.ad = _creative(sbi_dc, bid.sbi_aid); - goodBid.cpm = Number(bid.sbi_mouse); - goodBid.width = Number(bid.sbi_size.split('x')[0]) || 1; - goodBid.height = Number(bid.sbi_size.split('x')[1]) || 1; - bidmanager.addBidResponse(placementCode, goodBid); - } - - function _failure(placementCode) { - var failBid = bidfactory.createBid(2, _seraph(placementCode)); - failBid.bidderCode = 'sonobi'; - bidmanager.addBidResponse(placementCode, failBid); - } - - function _creative(sbi_dc, sbi_aid) { - var src = 'https://' + sbi_dc + 'apex.go.sonobi.com/sbi.js?aid=' + sbi_aid + '&as=null'; - return ''; - } - - return { - callBids: _phone_in, - formRequest: _keymaker, - parseResponse: _trinity, - success: _success, - failure: _failure - }; -}; - -adaptermanager.registerBidAdapter(new SonobiAdapter(), 'sonobi'); - -module.exports = SonobiAdapter; diff --git a/modules/spotxBidAdapter.js b/modules/spotxBidAdapter.js deleted file mode 100644 index 2e2831a028a..00000000000 --- a/modules/spotxBidAdapter.js +++ /dev/null @@ -1,143 +0,0 @@ -import Adapter from 'src/adapter'; -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import adLoader from 'src/adloader'; -import * as utils from 'src/utils'; -import { STATUS } from 'src/constants'; -import adaptermanager from 'src/adaptermanager'; - -function Spotx() { - let baseAdapter = new Adapter('Spotx'); - let bidReq; - let KVP_Object; - - const _defaultBidderSettings = { - alwaysUseBid: true, - adserverTargeting: [ - { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.spotx_ad_key; - } - } - ] - }; - - bidmanager.registerDefaultBidderSetting('spotx', _defaultBidderSettings); - - baseAdapter.callBids = function(bidRequest) { - if (!bidRequest || !bidRequest.bids || bidRequest.bids.length === 0) { - return; - } - bidReq = bidRequest.bids[0] || []; - - if (!validateParams(bidReq)) { - console.log('Bid Request does not contain valid parameters.'); - return; - } - - loadDSDK(); - }; - - // Load the SpotX Direct AdOS SDK onto the page - function loadDSDK() { - var channelId = bidReq.params.video.channel_id; - adLoader.loadScript('//js.spotx.tv/directsdk/v1/' + channelId + '.js', initDSDK, true); - } - - // We have a Direct AdOS SDK! Set options and initialize it! - function initDSDK() { - var options = bidReq.params.video; - - // If we are passed a id string set the slot and video slot to the element using that id. - if (typeof options.slot === 'string') { - options.slot = document.getElementById(bidReq.params.video.slot); - } - if (typeof options.video_slot === 'string') { - options.video_slot = document.getElementById(bidReq.params.video.video_slot); - } - - var directAdOS = new SpotX.DirectAdOS(options); - - directAdOS.getAdServerKVPs().then(function(adServerKVPs) { - // Got an ad back. Build a successful response. - var resp = { - bids: [] - }; - var bid = {}; - - bid.cmpID = bidReq.params.video.channel_id; - bid.cpm = adServerKVPs.spotx_bid; - bid.url = adServerKVPs.spotx_ad_key; - bid.cur = 'USD'; - bid.bidderCode = 'spotx'; - var sizes = utils.isArray(bidReq.sizes[0]) ? bidReq.sizes[0] : bidReq.sizes; - bid.height = sizes[1]; - bid.width = sizes[0]; - resp.bids.push(bid); - KVP_Object = adServerKVPs; - handleResponse(resp); - }, function() { - // No ad... - handleResponse() - }); - } - - function createBid(status) { - var bid = bidfactory.createBid(status, utils.getBidRequest(bidReq.bidId)); - - // Stuff we have no matter what - bid.bidderCode = bidReq.bidder; - bid.placementCode = bidReq.placementCode; - bid.requestId = bidReq.requestId; - bid.code = bidReq.bidder; - - // Stuff we only get with a successful response - if (status === STATUS.GOOD && KVP_Object) { - let url = '//search.spotxchange.com/ad/vast.html?key=' + KVP_Object.spotx_ad_key; - bid.mediaType = 'video'; - - bid.cpm = KVP_Object.spotx_bid; - bid.vastUrl = url; - bid.spotx_ad_key = KVP_Object.spotx_ad_key; - - var sizes = utils.isArray(bidReq.sizes[0]) ? bidReq.sizes[0] : bidReq.sizes; - bid.height = sizes[1]; - bid.width = sizes[0]; - } - - return bid; - } - - /* Notify Prebid of bid responses so bids can get in the auction */ - function handleResponse(response) { - if (!response || !response.bids || !response.bids.length) { - bidmanager.addBidResponse(bidReq.placementCode, createBid(STATUS.NO_BID)); - } else { - bidmanager.addBidResponse(bidReq.placementCode, createBid(STATUS.GOOD, response.bids[0])); - } - } - - function validateParams(request) { - if (typeof request.params !== 'object' && typeof request.params.video !== 'object') { - return false; - } - - // Check that all of our required parameters are defined. - if (bidReq.params.video.channel_id === undefined || bidReq.params.video.slot === undefined || bidReq.params.video.video_slot === undefined) { - return false; - } - return true; - } - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode - }); -} - -adaptermanager.registerBidAdapter(new Spotx(), 'spotx', { - supportedMediaTypes: ['video'] -}); - -module.exports = Spotx; diff --git a/modules/springserveBidAdapter.js b/modules/springserveBidAdapter.js deleted file mode 100644 index d54702a230f..00000000000 --- a/modules/springserveBidAdapter.js +++ /dev/null @@ -1,116 +0,0 @@ -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader'); -var adaptermanager = require('src/adaptermanager'); - -var SpringServeAdapter; -SpringServeAdapter = function SpringServeAdapter() { - function buildSpringServeCall(bid) { - var spCall = window.location.protocol + '//bidder.springserve.com/display/hbid?'; - - // get width and height from bid attribute - var size = bid.sizes[0]; - var width = size[0]; - var height = size[1]; - - spCall += '&w='; - spCall += width; - spCall += '&h='; - spCall += height; - - var params = bid.params; - - // maps param attributes to request parameters - var requestAttrMap = { - sp: 'supplyPartnerId', - imp_id: 'impId' - }; - - for (var property in requestAttrMap) { - if (requestAttrMap.hasOwnProperty && params.hasOwnProperty(requestAttrMap[property])) { - spCall += '&'; - spCall += property; - spCall += '='; - - // get property from params and include it in request - spCall += params[requestAttrMap[property]]; - } - } - - var domain = window.location.hostname; - - // override domain when testing - if (params.hasOwnProperty('test') && params.test === true) { - spCall += '&debug=true'; - domain = 'test.com'; - } - - spCall += '&domain='; - spCall += domain; - spCall += '&callback=$$PREBID_GLOBAL$$.handleSpringServeCB'; - - return spCall; - } - - function _callBids(params) { - var bids = params.bids || []; - for (var i = 0; i < bids.length; i++) { - var bid = bids[i]; - // bidmanager.pbCallbackMap[bid.params.impId] = params; - adloader.loadScript(buildSpringServeCall(bid)); - } - } - - $$PREBID_GLOBAL$$.handleSpringServeCB = function (responseObj) { - if (responseObj && responseObj.seatbid && responseObj.seatbid.length > 0 && - responseObj.seatbid[0].bid[0] !== undefined) { - // look up the request attributs stored in the bidmanager - var responseBid = responseObj.seatbid[0].bid[0]; - // var requestObj = bidmanager.getPlacementIdByCBIdentifer(responseBid.impid); - var requestBids = $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === 'springserve'); - if (requestBids && requestBids.bids.length > 0) { - requestBids = requestBids.bids.filter(bid => bid.params && bid.params.impId === responseBid.impid); - } else { - requestBids = []; - } - var bid = bidfactory.createBid(1); - var placementCode; - - // assign properties from the original request to the bid object - for (var i = 0; i < requestBids.length; i++) { - var bidRequest = requestBids[i]; - if (bidRequest.bidder === 'springserve') { - placementCode = bidRequest.placementCode; - var size = bidRequest.sizes[0]; - bid.width = size[0]; - bid.height = size[1]; - } - } - - if (requestBids[0]) { bid.bidderCode = requestBids[0].bidder; } - - if (responseBid.hasOwnProperty('price') && responseBid.hasOwnProperty('adm')) { - // assign properties from the response to the bid object - bid.cpm = responseBid.price; - bid.ad = responseBid.adm; - } else { - // make object for invalid bid response - bid = bidfactory.createBid(2); - bid.bidderCode = 'springserve'; - } - - bidmanager.addBidResponse(placementCode, bid); - } - }; - - // Export the callBids function, so that prebid.js can execute this function - // when the page asks to send out bid requests. - return { - callBids: _callBids, - buildSpringServeCall: buildSpringServeCall - }; -}; - -adaptermanager.registerBidAdapter(new SpringServeAdapter(), 'springserve'); - -module.exports = SpringServeAdapter; diff --git a/modules/stickyadstvBidAdapter.js b/modules/stickyadstvBidAdapter.js deleted file mode 100644 index c22e696e74e..00000000000 --- a/modules/stickyadstvBidAdapter.js +++ /dev/null @@ -1,269 +0,0 @@ -var Adapter = require('src/adapter.js').default; -var bidfactory = require('src/bidfactory.js'); -var bidmanager = require('src/bidmanager.js'); -var adloader = require('src/adloader.js'); -var utils = require('src/utils.js'); -var adaptermanager = require('src/adaptermanager'); - -var StickyAdsTVAdapter = function StickyAdsTVAdapter() { - var STICKYADS_BIDDERCODE = 'stickyadstv'; - var MUSTANG_URL = '//cdn.stickyadstv.com/mustang/mustang.min.js'; - var OUTSTREAM_URL = '//cdn.stickyadstv.com/prime-time/[COMP-ID].min.js'; - - var topMostWindow = getTopMostWindow(); - topMostWindow.stickyadstv_cache = {}; - - function _callBids(params) { - var bids = params.bids || []; - for (var i = 0; i < bids.length; i++) { - var bid = bids[i]; - // Send out bid request for each bid given its tag IDs and query strings - - if (bid.placementCode && bid.params.zoneId) { - sendBidRequest(bid); - } else { - utils.logWarn('StickyAdsTV: Missing mandatory field(s).'); - } - } - } - - function sendBidRequest(bid) { - var placementCode = bid.placementCode; - - var integrationType = bid.params.format ? bid.params.format : 'inbanner'; - var urltoLoad = MUSTANG_URL; - - if (integrationType !== 'inbanner') { - // integration types are equals to component ids - urltoLoad = OUTSTREAM_URL.replace('[COMP-ID]', integrationType); - } - - var bidRegistered = false; - adloader.loadScript(urltoLoad, function() { - getBid(bid, function(bidObject) { - if (!bidRegistered) { - bidRegistered = true; - bidmanager.addBidResponse(placementCode, bidObject); - } - }); - }, true); - } - - function getBid(bid, callback) { - var zoneId = bid.params.zoneId || bid.params.zone; // accept both - var size = getBiggerSize(bid.sizes); - - // some of our formats doesn't have tools API exposed - var toolsAPI = window.com.stickyadstv.tools; - if (toolsAPI && toolsAPI.ASLoader) { - topMostWindow.stickyadstv_asLoader = new toolsAPI.ASLoader(zoneId, getComponentId(bid.params.format)); - } - - var vastLoader = new window.com.stickyadstv.vast.VastLoader(); - bid.vast = topMostWindow.stickyadstv_cache[bid.placementCode] = vastLoader.getVast(); - - var vastCallback = { - onSuccess: bind(function() { - // 'this' is the bid request here - var bidRequest = this; - - var adHtml = formatAdHTML(bidRequest, size); - var price = extractPrice(bidRequest.vast); - - callback(formatBidObject(bidRequest, true, price, adHtml, size[0], size[1])); - }, bid), - onError: bind(function() { - var bidRequest = this; - callback(formatBidObject(bidRequest, false)); - }, bid) - }; - - var config = { - zoneId: zoneId, - playerSize: size[0] + 'x' + size[1], - vastUrlParams: bid.params.vastUrlParams, - componentId: getComponentId(bid.params.format) - }; - - var api = window.com.stickyadstv[getAPIName(bid.params.format)]; - if (api && typeof api.getPlayerSize === 'function') { - // in screenroll and similar cases we don't use the original div size. - config.playerSize = api.getPlayerSize(); - } - - vastLoader.load(config, vastCallback); - } - - function getComponentId(inputFormat) { - var component = 'mustang'; // default component id - - if (inputFormat && inputFormat !== 'inbanner') { - // format identifiers are equals to their component ids. - component = inputFormat; - } - - return component; - } - - function getAPIName(componentId) { - componentId = componentId || ''; - - // remove dash in componentId to get API name - return componentId.replace('-', ''); - } - - function getBiggerSize(array) { - var result = [1, 1]; - for (var i = 0; i < array.length; i++) { - if (array[i][0] * array[i][1] > result[0] * result[1]) { - result = array[i]; - } - } - return result; - } - - var formatInBannerHTML = function(bid, size) { - var placementCode = bid.placementCode; - - var divHtml = '
'; - - var script = "'; - - return divHtml + script; - }; - - var formatOutstreamHTML = function(bid) { - var placementCode = bid.placementCode; - - var config = bid.params; - - // default placement if no placement is set - if (!config.hasOwnProperty('domId') && !config.hasOwnProperty('auto') && !config.hasOwnProperty('p') && !config.hasOwnProperty('article')) { - config.domId = placementCode; - } - - var script = "'; - - return script; - }; - - function formatAdHTML(bid, size) { - var integrationType = bid.params.format; - - var html = ''; - if (integrationType && integrationType !== 'inbanner') { - html = formatOutstreamHTML(bid); - } else { - html = formatInBannerHTML(bid, size); - } - - return html; - } - - function extractPrice(vast) { - var priceData = vast.getPricing(); - - if (!priceData) { - console.warn("freewheel-ssp: Bid pricing Can't be retreived. You may need to enable pricing on you're zone. Please get in touch with your Freewheel contact."); - } - - return priceData; - } - - function formatBidObject(bidRequest, valid, priceData, html, width, height) { - var bidObject; - if (valid && priceData) { - // valid bid response - bidObject = bidfactory.createBid(1, bidRequest); - bidObject.bidderCode = bidRequest.bidder; - bidObject.cpm = priceData.price; - bidObject.currencyCode = priceData.currency; - bidObject.ad = html; - bidObject.width = width; - bidObject.height = height; - } else { - // invalid bid response - bidObject = bidfactory.createBid(2, bidRequest); - bidObject.bidderCode = bidRequest.bidder; - } - return bidObject; - } - - /** - * returns the top most accessible window - */ - function getTopMostWindow() { - var res = window; - - try { - while (top !== res) { - if (res.parent.location.href.length) { res = res.parent; } - } - } catch (e) {} - - return res; - } - - /* Create a function bound to a given object (assigning `this`, and arguments, - * optionally). Binding with arguments is also known as `curry`. - * Delegates to **ECMAScript 5**'s native `Function.bind` if available. - * We check for `func.bind` first, to fail fast when `func` is undefined. - * - * @param {function} func - * @param {optional} context - * @param {...any} var_args - * @return {function} - */ - var bind = function(func, context) { - return function() { - return func.apply(context, arguments); - }; - }; - - return Object.assign(this, new Adapter(STICKYADS_BIDDERCODE), { - callBids: _callBids, - formatBidObject: formatBidObject, - formatAdHTML: formatAdHTML, - getBiggerSize: getBiggerSize, - getBid: getBid, - getTopMostWindow: getTopMostWindow, - getComponentId: getComponentId, - getAPIName: getAPIName - }); -}; - -adaptermanager.registerBidAdapter(new StickyAdsTVAdapter(), 'stickyadstv'); -adaptermanager.aliasBidAdapter('stickyadstv', 'freewheel-ssp'); - -module.exports = StickyAdsTVAdapter; diff --git a/modules/tapsenseBidAdapter.js b/modules/tapsenseBidAdapter.js deleted file mode 100644 index a984f6cb8ab..00000000000 --- a/modules/tapsenseBidAdapter.js +++ /dev/null @@ -1,89 +0,0 @@ -// v0.0.1 - -const bidfactory = require('src/bidfactory.js'); -const bidmanager = require('src/bidmanager.js'); -const adloader = require('src/adloader'); -const utils = require('src/utils.js'); -const adaptermanager = require('src/adaptermanager'); - -const TapSenseAdapter = function TapSenseAdapter() { - const version = '0.0.1'; - const creativeSizes = [ - '320x50' - ]; - const validParams = [ - 'ufid', - 'refer', - 'ad_unit_id', // required - 'device_id', - 'lat', - 'long', - 'user', // required - 'price_floor', - 'test' - ]; - const SCRIPT_URL = 'https://ads04.tapsense.com/ads/headerad'; - let bids; - $$PREBID_GLOBAL$$.tapsense = {}; - function _callBids(params) { - bids = params.bids || []; - for (let i = 0; i < bids.length; i++) { - let bid = bids[i]; - let isValidSize = false; - if (!bid.sizes || !bid.params.user || !bid.params.ad_unit_id) { - return; - } - let parsedSizes = utils.parseSizesInput(bid.sizes); - for (let k = 0; k < parsedSizes.length; k++) { - if (creativeSizes.indexOf(parsedSizes[k]) > -1) { - isValidSize = true; - break; - } - } - if (isValidSize) { - let queryString = `?price=true&jsonp=1&callback=$$PREBID_GLOBAL$$.tapsense.callback_with_price_${bid.bidId}&version=${version}&`; - $$PREBID_GLOBAL$$.tapsense[`callback_with_price_${bid.bidId}`] = generateCallback(bid.bidId); - let keys = Object.keys(bid.params); - for (let j = 0; j < keys.length; j++) { - if (validParams.indexOf(keys[j]) < 0) continue; - queryString += encodeURIComponent(keys[j]) + '=' + encodeURIComponent(bid.params[keys[j]]) + '&'; - } - _requestBids(SCRIPT_URL + queryString); - } - } - } - - function generateCallback(bidId) { - return function tapsenseCallback(response, price) { - let bidObj; - if (response && price) { - let bidReq = utils.getBidRequest(bidId); - if (response.status.value === 'ok' && response.count_ad_units > 0) { - bidObj = bidfactory.createBid(1, bidObj); - bidObj.cpm = price; - bidObj.width = response.width; - bidObj.height = response.height; - bidObj.ad = response.ad_units[0].html; - } else { - bidObj = bidfactory.createBid(2, bidObj); - } - bidObj.bidderCode = bidReq.bidder; - bidmanager.addBidResponse(bidReq.placementCode, bidObj); - } else { - utils.logMessage('No prebid response'); - } - }; - } - - function _requestBids(scriptURL) { - adloader.loadScript(scriptURL); - } - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new TapSenseAdapter(), 'tapsense'); - -module.exports = TapSenseAdapter; diff --git a/modules/thoughtleadrBidAdapter.js b/modules/thoughtleadrBidAdapter.js deleted file mode 100644 index 1202575a6cb..00000000000 --- a/modules/thoughtleadrBidAdapter.js +++ /dev/null @@ -1,191 +0,0 @@ -const bidfactory = require('src/bidfactory'); -const bidmanager = require('src/bidmanager'); -const utils = require('src/utils'); -const ajax_1 = require('src/ajax'); -const adaptermanager = require('src/adaptermanager'); - -const COOKIE_SYNC_ID = 'tldr-cookie-sync-div'; -const UID_KEY = 'tldr_uid'; -const URL_API = 'tldr' in window && tldr.config.root_url ? tldr.config.root_url : '//a.thoughtleadr.com/v4/'; -const URL_CDN = 'tldr' in window && tldr.config.cdn_url ? tldr.config.cdn_url : '//cdn.thoughtleadr.com/v4/'; -const BID_AVAILABLE = 1; -const BID_UNAVAILABLE = 2; - -function storageAvailable(type) { - try { - const storage = window[type]; - const x = '__storage_test__'; - storage.setItem(x, x); - storage.removeItem(x); - return true; - } catch (e) { - return e instanceof DOMException && ( - // everything except Firefox - e.code === 22 || - // Firefox - e.code === 1014 || - // test name field too, because code might not be present - // everything except Firefox - e.name === 'QuotaExceededError' || - // Firefox - e.name === 'NS_ERROR_DOM_QUOTA_REACHED') && - // acknowledge QuotaExceededError only if there's something already stored - storage.length !== 0; - } -} - -function getVal(key) { - if (storageAvailable('localStorage')) { - return localStorage[key]; - } - if (storageAvailable('sessionStorage')) { - return sessionStorage[key]; - } - return null; -} - -function setVal(key, val) { - if (storageAvailable('localStorage')) { - localStorage[key] = val; - } - if (storageAvailable('sessionStorage')) { - sessionStorage[key] = val; - } -} - -function getUid() { - let uid = getVal(UID_KEY); - if (!uid) { - uid = utils.generateUUID(null); - setVal(UID_KEY, uid); - } - return uid; -} - -function writeFriendlyFrame(html, container) { - const iframe = document.createElement('iframe'); - iframe.style.width = '0'; - iframe.style.height = '0'; - iframe.style.border = '0'; - - iframe.src = 'javascript:false'; - container.appendChild(iframe); - - const doc = iframe.contentWindow.document; - doc.body.innerHTML = html; - - const scripts = doc.body.getElementsByTagName('script'); - - for (let i = 0; i < scripts.length; i++) { - const scriptEl = scripts.item(i); - if (scriptEl.nodeName === 'SCRIPT') { - executeScript(scriptEl); - } - } - - return iframe; -} - -function executeScript(scriptEl) { - const newEl = document.createElement('script'); - newEl.innerText = scriptEl.text || scriptEl.textContent || scriptEl.innerHTML || ''; - - // ie-compatible copy-paste attributes - const attrs = scriptEl.attributes; - for (let i = attrs.length; i--;) { - newEl.setAttribute(attrs[i].name, attrs[i].value); - } - - if (scriptEl.parentNode) { - scriptEl.parentNode.replaceChild(newEl, scriptEl); - } -} - -const ThoughtleadrAdapter = (function () { - function ThoughtleadrAdapter() { - } - - ThoughtleadrAdapter.prototype.callBids = function (params) { - const bids = (params.bids || []).filter(function (bid) { - return ThoughtleadrAdapter.valid(bid); - }); - - for (let _i = 0, bids_1 = bids; _i < bids_1.length; _i++) { - const bid = bids_1[_i]; - this.requestPlacement(bid); - } - }; - - ThoughtleadrAdapter.prototype.requestPlacement = function (bid) { - const _this = this; - const uid = getUid(); - const size = ThoughtleadrAdapter.getSizes(bid.sizes); - - ajax_1.ajax('' + URL_API + bid.params.placementId + '/header-bid.json?uid=' + uid, function (response) { - const wonBid = JSON.parse(response); - if (wonBid.cookie_syncs) { - _this.syncCookies(wonBid.cookie_syncs); - } - - const script = document.createElement('script'); - script.src = URL_CDN + 'bid.js'; - script.setAttribute('header-bid-token', wonBid.header_bid_token); - - let bidObject; - if (wonBid && wonBid.amount) { - bidObject = bidfactory.createBid(BID_AVAILABLE); - bidObject.bidderCode = 'thoughtleadr'; - bidObject.cpm = wonBid.amount; - bidObject.ad = script.outerHTML; - bidObject.width = size.width; - bidObject.height = size.height; - } else { - bidObject = bidfactory.createBid(BID_UNAVAILABLE); - bidObject.bidderCode = 'thoughtleadr'; - } - bidmanager.addBidResponse(bid.placementCode, bidObject); - }, null); - }; - - ThoughtleadrAdapter.prototype.syncCookies = function (tags) { - if (!tags || !tags.length) { - return; - } - - let container = document.getElementById(COOKIE_SYNC_ID); - if (!container) { - container = document.createElement('div'); - container.id = COOKIE_SYNC_ID; - container.style.width = '0'; - container.style.height = '0'; - document.body.appendChild(container); - } - - for (let _i = 0, tags_1 = tags; _i < tags_1.length; _i++) { - const tag = tags_1[_i]; - writeFriendlyFrame(tag, container); - } - }; - - ThoughtleadrAdapter.valid = function (bid) { - return !!(bid && bid.params && typeof bid.params.placementId === 'string'); - }; - - ThoughtleadrAdapter.getSizes = function (sizes) { - const first = sizes[0]; - if (Array.isArray(first)) { - return ThoughtleadrAdapter.getSizes(first); - } - - return { - width: sizes[0], - height: sizes[1] - }; - }; - - return ThoughtleadrAdapter; -}()); - -adaptermanager.registerBidAdapter(new ThoughtleadrAdapter(), 'thoughtleadr'); - -module.exports = ThoughtleadrAdapter; diff --git a/modules/tremorBidAdapter.js b/modules/tremorBidAdapter.js deleted file mode 100644 index 1294c61e210..00000000000 --- a/modules/tremorBidAdapter.js +++ /dev/null @@ -1,167 +0,0 @@ -/* -* Tremor Video bid Adapter for prebid.js -* */ - -import Adapter from 'src/adapter'; -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import * as utils from 'src/utils'; -import {ajax} from 'src/ajax'; -import {STATUS} from 'src/constants'; -import adaptermanager from 'src/adaptermanager'; - -const ENDPOINT = '.ads.tremorhub.com/ad/tag'; - -const OPTIONAL_PARAMS = [ - 'mediaId', 'mediaUrl', 'mediaTitle', 'contentLength', 'floor', - 'efloor', 'custom', 'categories', 'keywords', 'blockDomains', - 'c2', 'c3', 'c4', 'skip', 'skipmin', 'skipafter', 'delivery', - 'placement', 'videoMinBitrate', 'videoMaxBitrate' -]; - -/** - * Bidder adapter Tremor Video. Given the list of all ad unit tag IDs, - * sends out a bid request. When a bid response is back, registers the bid - * to Prebid.js. - * Steps: - * - Format and send the bid request - * - Evaluate and handle the response - * - Store potential VAST markup - * - Send request to ad server - * - intercept ad server response - * - Check if the vast wrapper URL is http://cdn.tremorhub.com/static/dummy.xml - * - If yes: then render the locally stored VAST markup by directly passing it to your player - * - Else: give the player the VAST wrapper from your ad server - */ -function TremorAdapter() { - let baseAdapter = new Adapter('tremor'); - - /* Prebid executes this function when the page asks to send out bid requests */ - baseAdapter.callBids = function (bidRequest) { - const bids = bidRequest.bids || []; - bids.filter(bid => valid(bid)) - .map(bid => { - let url = generateUrl(bid); - if (url) { - ajax(url, response => { - handleResponse(bid, response); - }, null, {method: 'GET', withCredentials: true}); - } - }); - }; - - /** - * Generates the url based on the parameters given. Sizes are required. - * The format is: [L,W] or [[L1,W1],...] - * @param bid - * @returns {string} - */ - function generateUrl(bid) { - // get the sizes - let width, height; - if (utils.isArray(bid.sizes) && bid.sizes.length === 2 && (!isNaN(bid.sizes[0]) && !isNaN(bid.sizes[1]))) { - width = bid.sizes[0]; - height = bid.sizes[1]; - } else if (typeof bid.sizes === 'object') { - // take the primary (first) size from the array - width = bid.sizes[0][0]; - height = bid.sizes[0][1]; - } - if (width && height) { - let scheme = ((document.location.protocol === 'https:') ? 'https' : 'http') + '://'; - let url = scheme + bid.params.supplyCode + ENDPOINT + '?adCode=' + bid.params.adCode; - - url += ('&playerWidth=' + width); - url += ('&playerHeight=' + height); - url += ('&srcPageUrl=' + encodeURIComponent(document.location.href)); - - OPTIONAL_PARAMS.forEach(param => { - if (bid.params[param]) { - url += ('&' + param + '=' + bid.params[param]); - } - }); - - url = (url + '&fmt=json'); - - return url; - } - } - - /* Notify Prebid of bid responses so bids can get in the auction */ - function handleResponse(bidReq, response) { - let bidResult; - - try { - bidResult = JSON.parse(response); - } catch (error) { - utils.logError(error); - } - - if (!bidResult || bidResult.error) { - let errorMessage = `in response for ${baseAdapter.getBidderCode()} adapter`; - if (bidResult && bidResult.error) { - errorMessage += `: ${bidResult.error}`; - } - utils.logError(errorMessage); - - // signal this response is complete - bidmanager.addBidResponse(bidReq.placementCode, createBid(STATUS.NO_BID)); - } - - if (bidResult.seatbid && bidResult.seatbid.length > 0) { - bidResult.seatbid[0].bid.forEach(tag => { - let status = STATUS.GOOD; - const bid = createBid(status, bidReq, tag); - bidmanager.addBidResponse(bidReq.placementCode, bid); - }); - } else { - // signal this response is complete with no bid - bidmanager.addBidResponse(bidReq.placementCode, createBid(STATUS.NO_BID)); - } - } - - /** - * We require the ad code and the supply code to generate a tag url - * @param bid - * @returns {*} - */ - function valid(bid) { - if (bid.params.adCode && bid.params.supplyCode) { - return bid; - } else { - utils.logError('missing bid params'); - } - } - - /** - * Create and return a bid object based on status and tag - * @param status - * @param reqBid - * @param response - */ - function createBid(status, reqBid, response) { - let bid = bidfactory.createBid(status, reqBid); - bid.code = baseAdapter.getBidderCode(); - bid.bidderCode = baseAdapter.getBidderCode(); - - if (response) { - bid.cpm = response.price; - bid.crid = response.crid; - bid.vastXml = response.adm; - bid.mediaType = 'video'; - } - - return bid; - } - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - }); -} - -adaptermanager.registerBidAdapter(new TremorAdapter(), 'tremor', { - supportedMediaTypes: ['video'] -}); - -module.exports = TremorAdapter; diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js deleted file mode 100644 index 141bdbf32cb..00000000000 --- a/modules/tripleliftBidAdapter.js +++ /dev/null @@ -1,149 +0,0 @@ -var utils = require('src/utils.js'); -var adloader = require('src/adloader.js'); -var bidmanager = require('src/bidmanager.js'); -var bidfactory = require('src/bidfactory.js'); -var adaptermanager = require('src/adaptermanager'); - -/* TripleLift bidder factory function -* Use to create a TripleLiftAdapter object -*/ - -var TripleLiftAdapter = function TripleLiftAdapter() { - var usersync = false; - - function _callBids(params) { - var tlReq = params.bids; - var bidsCount = tlReq.length; - - // set expected bids count for callback execution - // bidmanager.setExpectedBidsCount('triplelift',bidsCount); - - for (var i = 0; i < bidsCount; i++) { - var bidRequest = tlReq[i]; - var callbackId = bidRequest.bidId; - adloader.loadScript(buildTLCall(bidRequest, callbackId)); - // store a reference to the bidRequest from the callback id - // bidmanager.pbCallbackMap[callbackId] = bidRequest; - } - } - - function buildTLCall(bid, callbackId) { - // determine tag params - var inventoryCode = utils.getBidIdParameter('inventoryCode', bid.params); - var floor = utils.getBidIdParameter('floor', bid.params); - - // build our base tag, based on if we are http or https - var tlURI = '//tlx.3lift.com/header/auction?'; - var tlCall = document.location.protocol + tlURI; - - tlCall = utils.tryAppendQueryString(tlCall, 'callback', '$$PREBID_GLOBAL$$.TLCB'); - tlCall = utils.tryAppendQueryString(tlCall, 'lib', 'prebid'); - tlCall = utils.tryAppendQueryString(tlCall, 'v', '$prebid.version$'); - tlCall = utils.tryAppendQueryString(tlCall, 'callback_id', callbackId); - tlCall = utils.tryAppendQueryString(tlCall, 'inv_code', inventoryCode); - tlCall = utils.tryAppendQueryString(tlCall, 'floor', floor); - - // indicate whether flash support exists - tlCall = utils.tryAppendQueryString(tlCall, 'fe', isFlashEnabled()); - - // sizes takes a bit more logic - var sizeQueryString = utils.parseSizesInput(bid.sizes); - if (sizeQueryString) { - tlCall += 'size=' + sizeQueryString + '&'; - } - - // append referrer - var referrer = utils.getTopWindowUrl(); - tlCall = utils.tryAppendQueryString(tlCall, 'referrer', referrer); - - // remove the trailing "&" - if (tlCall.lastIndexOf('&') === tlCall.length - 1) { - tlCall = tlCall.substring(0, tlCall.length - 1); - } - - // @if NODE_ENV='debug' - utils.logMessage('tlCall request built: ' + tlCall); - // @endif - - // append a timer here to track latency - bid.startTime = new Date().getTime(); - - return tlCall; - } - - function isFlashEnabled() { - var hasFlash = 0; - try { - // check for Flash support in IE - var fo = new window.ActiveXObject('ShockwaveFlash.ShockwaveFlash'); - if (fo) { hasFlash = 1; } - } catch (e) { - if (navigator.mimeTypes && - navigator.mimeTypes['application/x-shockwave-flash'] !== undefined && - navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin) { - hasFlash = 1; - } - } - return hasFlash; - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.TLCB = function(tlResponseObj) { - if (tlResponseObj && tlResponseObj.callback_id) { - var bidObj = utils.getBidRequest(tlResponseObj.callback_id); - var placementCode = bidObj && bidObj.placementCode; - - // @if NODE_ENV='debug' - if (bidObj) { utils.logMessage('JSONP callback function called for inventory code: ' + bidObj.params.inventoryCode); } - // @endif - - var bid = []; - if (tlResponseObj && tlResponseObj.cpm && tlResponseObj.cpm !== 0) { - bid = bidfactory.createBid(1, bidObj); - bid.bidderCode = 'triplelift'; - bid.cpm = tlResponseObj.cpm; - bid.ad = tlResponseObj.ad; - bid.width = tlResponseObj.width; - bid.height = tlResponseObj.height; - bid.dealId = tlResponseObj.deal_id; - bidmanager.addBidResponse(placementCode, bid); - } else { - // no response data - // @if NODE_ENV='debug' - if (bidObj) { utils.logMessage('No prebid response from TripleLift for inventory code: ' + bidObj.params.inventoryCode); } - // @endif - bid = bidfactory.createBid(2, bidObj); - bid.bidderCode = 'triplelift'; - bidmanager.addBidResponse(placementCode, bid); - } - - // run usersyncs - if (!usersync) { - var iframe = utils.createInvisibleIframe(); - iframe.src = '//ib.3lift.com/sync'; - try { - document.body.appendChild(iframe); - } catch (error) { - utils.logError(error); - } - usersync = true; - // suppress TL ad tag from running additional usersyncs - window._tlSyncDone = true; - } - } else { - // no response data - // @if NODE_ENV='debug' - utils.logMessage('No prebid response for placement %%PLACEMENT%%'); - // @endif - } - }; - - return { - callBids: _callBids - - }; -}; - -adaptermanager.registerBidAdapter(new TripleLiftAdapter(), 'triplelift'); - -module.exports = TripleLiftAdapter; diff --git a/modules/twengaBidAdapter.js b/modules/twengaBidAdapter.js deleted file mode 100644 index 3a0e1016937..00000000000 --- a/modules/twengaBidAdapter.js +++ /dev/null @@ -1,136 +0,0 @@ -var CONSTANTS = require('src/constants.json'); -var utils = require('src/utils.js'); -var adloader = require('src/adloader.js'); -var bidmanager = require('src/bidmanager.js'); -var bidfactory = require('src/bidfactory.js'); -var Adapter = require('src/adapter.js').default; -var adaptermanager = require('src/adaptermanager'); - -function TwengaAdapter() { - var baseAdapter = new Adapter('twenga'); - - baseAdapter.callBids = function (params) { - for (var i = 0; i < params.bids.length; i++) { - var bidRequest = params.bids[i]; - var callbackId = bidRequest.bidId; - adloader.loadScript(buildBidCall(bidRequest, callbackId)); - } - }; - - function buildBidCall(bid, callbackId) { - var bidUrl = '//rtb.t.c4tw.net/Bid?'; - bidUrl = utils.tryAppendQueryString(bidUrl, 's', 'h'); - bidUrl = utils.tryAppendQueryString(bidUrl, 'callback', '$$PREBID_GLOBAL$$.handleTwCB'); - bidUrl = utils.tryAppendQueryString(bidUrl, 'callback_uid', callbackId); - bidUrl = utils.tryAppendQueryString(bidUrl, 'referrer', utils.getTopWindowUrl()); - if (bid.params) { - for (var key in bid.params) { - var value = bid.params[key]; - switch (key) { - case 'placementId': key = 'id'; break; - case 'siteId': key = 'sid'; break; - case 'publisherId': key = 'pid'; break; - case 'currency': key = 'cur'; break; - case 'bidFloor': key = 'min'; break; - case 'country': key = 'gz'; break; - } - bidUrl = utils.tryAppendQueryString(bidUrl, key, value); - } - } - - var sizes = utils.parseSizesInput(bid.sizes); - if (sizes.length > 0) { - bidUrl = utils.tryAppendQueryString(bidUrl, 'size', sizes.join(',')); - } - - bidUrl += 'ta=1'; - - // @if NODE_ENV='debug' - utils.logMessage('bid request built: ' + bidUrl); - - // @endif - - // append a timer here to track latency - bid.startTime = new Date().getTime(); - - return bidUrl; - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.handleTwCB = function (bidResponseObj) { - var bidCode; - - if (bidResponseObj && bidResponseObj.callback_uid) { - var responseCPM; - var id = bidResponseObj.callback_uid; - var placementCode = ''; - var bidObj = utils.getBidRequest(id); - if (bidObj) { - bidCode = bidObj.bidder; - - placementCode = bidObj.placementCode; - - bidObj.status = CONSTANTS.STATUS.GOOD; - } - - // @if NODE_ENV='debug' - utils.logMessage('JSONP callback function called for ad ID: ' + id); - - // @endif - var bid = []; - if (bidResponseObj.result && - bidResponseObj.result.cpm && - bidResponseObj.result.cpm !== 0 && - bidResponseObj.result.ad) { - var result = bidResponseObj.result; - - responseCPM = parseInt(result.cpm, 10); - - // CPM response from /Bid is dollar/cent multiplied by 10000 - // in order to avoid using floats - // switch CPM to "dollar/cent" - responseCPM = responseCPM / 10000; - - var ad = result.ad.replace('%%WP%%', result.cpm); - - // store bid response - // bid status is good (indicating 1) - bid = bidfactory.createBid(1, bidObj); - bid.creative_id = result.creative_id; - bid.bidderCode = bidCode; - bid.cpm = responseCPM; - if (ad && (ad.lastIndexOf('http', 0) === 0 || ad.lastIndexOf('//', 0) === 0)) { bid.adUrl = ad; } else { bid.ad = ad; } - bid.width = result.width; - bid.height = result.height; - - bidmanager.addBidResponse(placementCode, bid); - } else { - // no response data - // @if NODE_ENV='debug' - utils.logMessage('No prebid response from Twenga for placement code ' + placementCode); - - // @endif - // indicate that there is no bid for this placement - bid = bidfactory.createBid(2, bidObj); - bid.bidderCode = bidCode; - bidmanager.addBidResponse(placementCode, bid); - } - } else { - // no response data - // @if NODE_ENV='debug' - utils.logMessage('No prebid response for placement %%PLACEMENT%%'); - - // @endif - } - }; - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - buildBidCall: buildBidCall - }); -} - -adaptermanager.registerBidAdapter(new TwengaAdapter(), 'twenga'); - -module.exports = TwengaAdapter; diff --git a/modules/ucfunnelBidAdapter.js b/modules/ucfunnelBidAdapter.js deleted file mode 100644 index 978c7508002..00000000000 --- a/modules/ucfunnelBidAdapter.js +++ /dev/null @@ -1,95 +0,0 @@ -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import * as utils from 'src/utils'; -import {ajax} from 'src/ajax'; -import {STATUS} from 'src/constants'; -import adaptermanager from 'src/adaptermanager'; - -const VER = 'ADGENT_PREBID-2017051801'; -const UCFUNNEL_BIDDER_CODE = 'ucfunnel'; - -function UcfunnelAdapter() { - function _callBids(params) { - let bids = params.bids || []; - - bids.forEach((bid) => { - try { - ajax(buildOptimizedCall(bid), bidCallback, undefined, { withCredentials: true }); - } catch (err) { - utils.logError('Error sending ucfunnel request for placement code ' + bid.placementCode, null, err); - } - - function bidCallback(responseText) { - try { - utils.logMessage('XHR callback function called for placement code: ' + bid.placementCode); - handleRpCB(responseText, bid); - } catch (err) { - if (typeof err === 'string') { - utils.logWarn(`${err} when processing ucfunnel response for placement code ${bid.placementCode}`); - } else { - utils.logError('Error processing ucfunnel response for placement code ' + bid.placementCode, null, err); - } - - // indicate that there is no bid for this placement - let badBid = bidfactory.createBid(STATUS.NO_BID, bid); - badBid.bidderCode = bid.bidder; - badBid.error = err; - bidmanager.addBidResponse(bid.placementCode, badBid); - } - } - }); - } - - function buildOptimizedCall(bid) { - bid.startTime = new Date().getTime(); - - const host = utils.getTopWindowLocation().host; - const page = utils.getTopWindowLocation().pathname; - const refer = document.referrer; - const language = navigator.language; - const dnt = (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0; - - let queryString = [ - 'ifr', 0, - 'bl', language, - 'je', 1, - 'dnt', dnt, - 'host', host, - 'u', page, - 'ru', refer, - 'adid', bid.params.adid, - 'ver', VER - ]; - - return queryString.reduce( - (memo, curr, index) => - index % 2 === 0 && queryString[index + 1] !== undefined - ? memo + curr + '=' + encodeURIComponent(queryString[index + 1]) + '&' - : memo, - '//agent.aralego.com/header?' - ).slice(0, -1); - } - - function handleRpCB(responseText, bidRequest) { - let ad = JSON.parse(responseText); // can throw - - let bid = bidfactory.createBid(STATUS.GOOD, bidRequest); - bid.creative_id = ad.ad_id; - bid.bidderCode = UCFUNNEL_BIDDER_CODE; - bid.cpm = ad.cpm || 0; - bid.ad = ad.adm; - bid.width = ad.width; - bid.height = ad.height; - bid.dealId = ad.deal; - - bidmanager.addBidResponse(bidRequest.placementCode, bid); - } - - return { - callBids: _callBids - }; -}; - -adaptermanager.registerBidAdapter(new UcfunnelAdapter(), UCFUNNEL_BIDDER_CODE); - -module.exports = UcfunnelAdapter; diff --git a/modules/unrulyBidAdapter.js b/modules/unrulyBidAdapter.js deleted file mode 100644 index 0f6b6e40901..00000000000 --- a/modules/unrulyBidAdapter.js +++ /dev/null @@ -1,119 +0,0 @@ -import { ajax } from 'src/ajax' -import bidfactory from 'src/bidfactory' -import bidmanager from 'src/bidmanager' -import * as utils from 'src/utils' -import { STATUS } from 'src/constants' -import { Renderer } from 'src/Renderer' -import adaptermanager from 'src/adaptermanager' - -function createRenderHandler({ bidResponseBid, rendererConfig }) { - function createApi() { - parent.window.unruly['native'].prebid = parent.window.unruly['native'].prebid || {} - parent.window.unruly['native'].prebid.uq = parent.window.unruly['native'].prebid.uq || [] - - return { - render(bidResponseBid) { - parent.window.unruly['native'].prebid.uq.push(['render', bidResponseBid]) - }, - onLoaded(bidResponseBid) {} - } - } - - parent.window.unruly = parent.window.unruly || {} - parent.window.unruly['native'] = parent.window.unruly['native'] || {} - parent.window.unruly['native'].siteId = parent.window.unruly['native'].siteId || rendererConfig.siteId - - const api = createApi() - return { - render() { - api.render(bidResponseBid) - }, - onRendererLoad() { - api.onLoaded(bidResponseBid) - } - } -} - -function createBidResponseHandler(bidRequestBids) { - return { - onBidResponse(responseBody) { - try { - const exchangeResponse = JSON.parse(responseBody) - exchangeResponse.bids.forEach((exchangeBid) => { - const bidResponseBid = bidfactory.createBid(exchangeBid.ext.statusCode, exchangeBid) - - Object.assign( - bidResponseBid, - exchangeBid - ) - - if (exchangeBid.ext.renderer) { - const rendererParams = exchangeBid.ext.renderer - const renderHandler = createRenderHandler({ - bidResponseBid, - rendererConfig: rendererParams.config - }) - - bidResponseBid.renderer = Renderer.install( - Object.assign( - {}, - rendererParams, - { callback: () => renderHandler.onRendererLoad() } - ) - ) - bidResponseBid.renderer.setRender(() => renderHandler.render()) - } - - bidmanager.addBidResponse(exchangeBid.ext.placementCode, bidResponseBid) - }) - } catch (error) { - utils.logError(error); - bidRequestBids.forEach(bidRequestBid => { - const bidResponseBid = bidfactory.createBid(STATUS.NO_BID) - bidmanager.addBidResponse(bidRequestBid.placementCode, bidResponseBid) - }) - } - } - } -} - -function UnrulyAdapter() { - const adapter = { - exchangeUrl: 'https://targeting.unrulymedia.com/prebid', - callBids({ bids: bidRequestBids }) { - if (!bidRequestBids || bidRequestBids.length === 0) { - return - } - - const videoMediaType = utils.deepAccess(bidRequestBids[0], 'mediaTypes.video') - const context = utils.deepAccess(bidRequestBids[0], 'mediaTypes.video.context') - if (videoMediaType && context !== 'outstream') { - return - } - - const payload = { - bidRequests: bidRequestBids - } - - const bidResponseHandler = createBidResponseHandler(bidRequestBids) - - ajax( - adapter.exchangeUrl, - bidResponseHandler.onBidResponse, - JSON.stringify(payload), - { - contentType: 'application/json', - withCredentials: true - } - ) - } - } - - return adapter -} - -adaptermanager.registerBidAdapter(new UnrulyAdapter(), 'unruly', { - supportedMediaTypes: ['video'] -}); - -module.exports = UnrulyAdapter diff --git a/modules/vertozBidAdapter.js b/modules/vertozBidAdapter.js deleted file mode 100644 index b6966dd62d1..00000000000 --- a/modules/vertozBidAdapter.js +++ /dev/null @@ -1,72 +0,0 @@ -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.js'); -var adaptermanager = require('src/adaptermanager'); - -function VertozAdapter() { - const BASE_URI = '//hb.vrtzads.com/vzhbidder/bid?'; - const BIDDER_NAME = 'vertoz'; - const QUERY_PARAM_KEY = 'q'; - - function _callBids(params) { - var bids = params.bids || []; - - for (var i = 0; i < bids.length; i++) { - var bid = bids[i]; - let slotBidId = utils.getValue(bid, 'bidId'); - let cb = Math.round(new Date().getTime() / 1000); - let vzEndPoint = BASE_URI; - let reqParams = bid.params || {}; - let placementId = utils.getValue(reqParams, 'placementId'); - let cpm = utils.getValue(reqParams, 'cpmFloor'); - - if (utils.isEmptyStr(placementId)) { - utils.logError('missing params:', BIDDER_NAME, 'Enter valid vzPlacementId'); - return; - } - - let reqSrc = utils.getTopWindowLocation().href; - var vzReq = { - _vzPlacementId: placementId, - _rqsrc: reqSrc, - _cb: cb, - _slotBidId: slotBidId, - _cpm: cpm, - _cbn: '$$PREBID_GLOBAL$$' - }; - - let queryParamValue = JSON.stringify(vzReq); - vzEndPoint = utils.tryAppendQueryString(vzEndPoint, QUERY_PARAM_KEY, queryParamValue); - adloader.loadScript(vzEndPoint); - } - } - - $$PREBID_GLOBAL$$.vzResponse = function (vertozResponse) { - var bidRespObj = vertozResponse; - var bidObject; - var reqBidObj = utils.getBidRequest(bidRespObj.slotBidId); - - if (bidRespObj.cpm) { - bidObject = bidfactory.createBid(CONSTANTS.STATUS.GOOD, reqBidObj); - bidObject.cpm = Number(bidRespObj.cpm); - bidObject.ad = bidRespObj.ad + utils.createTrackPixelHtml(decodeURIComponent(bidRespObj.nurl)); - bidObject.width = bidRespObj.adWidth; - bidObject.height = bidRespObj.adHeight; - } else { - let respStatusText = bidRespObj.statusText; - bidObject = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, reqBidObj); - utils.logMessage(respStatusText); - } - - var adSpaceId = reqBidObj.placementCode; - bidObject.bidderCode = BIDDER_NAME; - bidmanager.addBidResponse(adSpaceId, bidObject); - }; - return { callBids: _callBids }; -} - -adaptermanager.registerBidAdapter(new VertozAdapter(), 'vertoz'); - -module.exports = VertozAdapter; diff --git a/modules/wideorbitBidAdapter.js b/modules/wideorbitBidAdapter.js deleted file mode 100644 index f0ed885f6a3..00000000000 --- a/modules/wideorbitBidAdapter.js +++ /dev/null @@ -1,223 +0,0 @@ -const bidfactory = require('src/bidfactory.js'); -const bidmanager = require('src/bidmanager.js'); -const utils = require('src/utils.js'); -const adloader = require('src/adloader'); -const adaptermanager = require('src/adaptermanager'); - -function WideOrbitAdapter() { - const pageImpression = 'JSAdservingMP.ashx?pc={pc}&pbId={pbId}&clk=&exm=&jsv=1.0&tsv=1.0&cts={cts}&arp=0&fl=0&vitp=&vit=&jscb=window.$$PREBID_GLOBAL$$.handleWideOrbitCallback&url={referrer}&fp=&oid=&exr=&mraid=&apid=&apbndl=&mpp=0&uid=&cb={cb}&hb=1'; - const pageRepeatCommonParam = '&gid{o}={gid}&pp{o}=&clk{o}=&rpos{o}={rpos}&ecpm{o}={ecpm}&ntv{o}=&ntl{o}=&adsid{o}='; - const pageRepeatParamId = '&pId{o}={pId}&rank{o}={rank}'; - const pageRepeatParamNamed = '&wsName{o}={wsName}&wName{o}={wName}&rank{o}={rank}&bfDim{o}={width}x{height}&subp{o}={subp}'; - const base = (window.location.protocol) + '//p{pbId}.atemda.com/'; - let bids; - const adapterName = 'wideorbit'; - - function _fixParamNames(param) { - if (!param) { - return; - } - - const properties = ['site', 'page', 'width', 'height', 'rank', 'subPublisher', 'ecpm', 'atf', 'pId', 'pbId', 'referrer']; - let prop; - - utils._each(properties, function (correctName) { - for (prop in param) { - if (param.hasOwnProperty(prop) && prop.toLowerCase() === correctName.toLowerCase()) { - param[correctName] = param[prop]; - break; - } - } - }); - } - - function _setParam(str, param, value) { - var pattern = new RegExp('{' + param + '}', 'g'); - - if (value === true) { - value = 1; - } - if (value === false) { - value = 0; - } - return str.replace(pattern, value); - } - - function _setParams(str, keyValuePairs) { - utils._each(keyValuePairs, function (keyValuePair) { - str = _setParam(str, keyValuePair[0], keyValuePair[1]); - }); - return str; - } - - function _setCommonParams(pos, params) { - return _setParams(pageRepeatCommonParam, [ - ['o', pos], - ['gid', encodeURIComponent(params.tagId)], - ['rpos', params.atf ? 1001 : 0], - ['ecpm', params.ecpm || ''] - ]); - } - - function _getRankParam(rank, pos) { - return rank || pos; - } - - function _setupIdPlacementParameters(pos, params) { - return _setParams(pageRepeatParamId, [ - ['o', pos], - ['pId', params.pId], - ['rank', _getRankParam(params.rank, pos)] - ]); - } - - function _setupNamedPlacementParameters(pos, params) { - return _setParams(pageRepeatParamNamed, [ - ['o', pos], - ['wsName', encodeURIComponent(decodeURIComponent(params.site))], - ['wName', encodeURIComponent(decodeURIComponent(params.page))], - ['width', params.width], - ['height', params.height], - ['subp', params.subPublisher ? encodeURIComponent(decodeURIComponent(params.subPublisher)) : ''], - ['rank', _getRankParam(params.rank, pos)] - ]); - } - - function _setupAdCall(publisherId, placementCount, placementsComponent, referrer) { - return _setParams(base + pageImpression, [ - ['pbId', publisherId], - ['pc', placementCount], - ['cts', new Date().getTime()], - ['cb', Math.floor(Math.random() * 100000000)], - ['referrer', encodeURIComponent(referrer || '')] - ]) + placementsComponent; - } - - function _setupPlacementParameters(pos, params) { - var commonParams = _setCommonParams(pos, params); - - if (params.pId) { - return _setupIdPlacementParameters(pos, params) + commonParams; - } - - return _setupNamedPlacementParameters(pos, params) + commonParams; - } - - function _callBids(params) { - let publisherId; - let bidUrl = ''; - let i; - let referrer; - - bids = params.bids || []; - - for (i = 0; i < bids.length; i++) { - var requestParams = bids[i].params; - - requestParams.tagId = bids[i].placementCode; - - _fixParamNames(requestParams); - - publisherId = requestParams.pbId; - referrer = referrer || requestParams.referrer; - bidUrl += _setupPlacementParameters(i, requestParams); - } - - bidUrl = _setupAdCall(publisherId, bids.length, bidUrl, referrer); - - utils.logMessage('Calling WO: ' + bidUrl); - - adloader.loadScript(bidUrl); - } - - function _processUserMatchings(userMatchings) { - const headElem = document.getElementsByTagName('head')[0]; - let createdElem; - - utils._each(userMatchings, function (userMatching) { - createdElem = undefined; - switch (userMatching.Type) { - case 'redirect': - createdElem = document.createElement('img'); - break; - case 'iframe': - createdElem = utils.createInvisibleIframe(); - break; - case 'js': - createdElem = document.createElement('script'); - createdElem.type = 'text/javascript'; - createdElem.async = true; - break; - } - if (createdElem) { - createdElem.src = decodeURIComponent(userMatching.Url); - headElem.insertBefore(createdElem, headElem.firstChild); - } - }); - } - - function _getBidResponse(id, placements) { - var i; - - for (i = 0; i < placements.length; i++) { - if (placements[i].ExtPlacementId === id) { - return placements[i]; - } - } - } - - function _isUrl(scr) { - return scr.slice(0, 6) === 'http:/' || scr.slice(0, 7) === 'https:/' || scr.slice(0, 2) === '//'; - } - - function _buildAdCode(placement) { - let adCode = placement.Source; - let pixelTag; - - utils._each(placement.TrackingCodes, function (trackingCode) { - if (_isUrl(trackingCode)) { - pixelTag = ''; - } else { - pixelTag = trackingCode; - } - adCode = pixelTag + adCode; - }); - - return adCode; - } - - window.$$PREBID_GLOBAL$$ = window.$$PREBID_GLOBAL$$ || {}; - window.$$PREBID_GLOBAL$$.handleWideOrbitCallback = function (response) { - var bidResponse, - bidObject; - - utils.logMessage('WO response. Placements: ' + response.Placements.length); - - _processUserMatchings(response.UserMatchings); - - utils._each(bids, function (bid) { - bidResponse = _getBidResponse(bid.placementCode, response.Placements); - - if (bidResponse && bidResponse.Type === 'DirectHTML') { - bidObject = bidfactory.createBid(1); - bidObject.cpm = bidResponse.Bid; - bidObject.ad = _buildAdCode(bidResponse); - bidObject.width = bidResponse.Width; - bidObject.height = bidResponse.Height; - } else { - bidObject = bidfactory.createBid(2); - } - - bidObject.bidderCode = adapterName; - bidmanager.addBidResponse(bid.placementCode, bidObject); - }); - }; - - return { - callBids: _callBids - }; -} - -adaptermanager.registerBidAdapter(new WideOrbitAdapter(), 'wideorbit'); - -module.exports = WideOrbitAdapter; diff --git a/modules/widespaceBidAdapter.js b/modules/widespaceBidAdapter.js deleted file mode 100644 index c9e6fb4a11d..00000000000 --- a/modules/widespaceBidAdapter.js +++ /dev/null @@ -1,127 +0,0 @@ - -const utils = require('src/utils.js'); -const adloader = require('src/adloader.js'); -const bidmanager = require('src/bidmanager.js'); -const bidfactory = require('src/bidfactory.js'); -const adaptermanager = require('src/adaptermanager'); -const WS_ADAPTER_VERSION = '1.0.3'; - -function WidespaceAdapter() { - const useSSL = document.location.protocol === 'https:'; - const baseURL = (useSSL ? 'https:' : 'http:') + '//engine.widespace.com/map/engine/hb/dynamic?'; - const callbackName = '$$PREBID_GLOBAL$$.widespaceHandleCB'; - - function _callBids(params) { - let bids = (params && params.bids) || []; - - for (var i = 0; i < bids.length; i++) { - const bid = bids[i]; - const callbackUid = bid.bidId; - const sid = bid.params.sid; - const currency = bid.params.cur || bid.params.currency; - - // Handle Sizes string - let sizeQueryString = ''; - let parsedSizes = utils.parseSizesInput(bid.sizes); - - sizeQueryString = parsedSizes.reduce((prev, curr) => { - return prev ? `${prev},${curr}` : curr; - }, sizeQueryString); - - let requestURL = baseURL; - requestURL = utils.tryAppendQueryString(requestURL, 'hb.ver', WS_ADAPTER_VERSION); - - const params = { - 'hb': '1', - 'hb.name': 'prebidjs', - 'hb.callback': callbackName, - 'hb.callbackUid': callbackUid, - 'hb.sizes': sizeQueryString, - 'hb.currency': currency, - 'sid': sid - }; - - if (bid.params.demo) { - let demoFields = ['gender', 'country', 'region', 'postal', 'city', 'yob']; - for (let i = 0; i < demoFields.length; i++) { - if (!bid.params.demo[demoFields[i]]) { - continue; - } - params['hb.demo.' + demoFields[i]] = bid.params.demo[demoFields[i]]; - } - } - - requestURL += '#'; - - var paramKeys = Object.keys(params); - - for (var k = 0; k < paramKeys.length; k++) { - var key = paramKeys[k]; - requestURL += key + '=' + params[key] + '&'; - } - - // Expose the callback - $$PREBID_GLOBAL$$.widespaceHandleCB = window[callbackName] = handleCallback; - - adloader.loadScript(requestURL); - } - } - - // Handle our callback - var handleCallback = function handleCallback(bidsArray) { - if (!bidsArray) { return; } - - let bidObject; - let bidCode = 'widespace'; - - for (var i = 0, l = bidsArray.length; i < l; i++) { - const bid = bidsArray[i]; - let placementCode = ''; - let validSizes = []; - - bid.sizes = {height: bid.height, width: bid.width}; - - var inBid = utils.getBidRequest(bid.callbackUid); - - if (inBid) { - bidCode = inBid.bidder; - placementCode = inBid.placementCode; - validSizes = inBid.sizes; - } - - if (bid && bid.callbackUid && bid.status !== 'noad' && verifySize(bid.sizes, validSizes)) { - bidObject = bidfactory.createBid(1); - bidObject.bidderCode = bidCode; - bidObject.cpm = bid.cpm; - bidObject.cur = bid.currency; - bidObject.creative_id = bid.adId; - bidObject.ad = bid.code; - bidObject.width = bid.width; - bidObject.height = bid.height; - bidmanager.addBidResponse(placementCode, bidObject); - } else { - bidObject = bidfactory.createBid(2); - bidObject.bidderCode = bidCode; - bidmanager.addBidResponse(placementCode, bidObject); - } - } - - function verifySize(bid, validSizes) { - for (var j = 0, k = validSizes.length; j < k; j++) { - if (bid.width === validSizes[j][0] && - bid.height === validSizes[j][1]) { - return true; - } - } - return false; - } - }; - - return { - callBids: _callBids - }; -} - -adaptermanager.registerBidAdapter(new WidespaceAdapter(), 'widespace'); - -module.exports = WidespaceAdapter; diff --git a/modules/xhbBidAdapter.js b/modules/xhbBidAdapter.js deleted file mode 100644 index a45bb66bb52..00000000000 --- a/modules/xhbBidAdapter.js +++ /dev/null @@ -1,172 +0,0 @@ -import Adapter from 'src/adapter'; -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import * as utils from 'src/utils'; -import { STATUS } from 'src/constants'; -import adaptermanager from 'src/adaptermanager'; -import { loadScript } from 'src/adloader'; - -const XhbAdapter = function XhbAdapter() { - const baseAdapter = new Adapter('xhb'); - let usersync = false; - - const _defaultBidderSettings = { - alwaysUseBid: true, - adserverTargeting: [ - { - key: 'hb_xhb_deal', - val: function (bidResponse) { - return bidResponse.dealId; - } - }, - { - key: 'hb_xhb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, - { - key: 'hb_xhb_size', - val: function (bidResponse) { - return bidResponse.width + 'x' + bidResponse.height; - } - } - ] - }; - bidmanager.registerDefaultBidderSetting('xhb', _defaultBidderSettings); - - baseAdapter.callBids = function (params) { - const anArr = params.bids; - for (let i = 0; i < anArr.length; i++) { - let bidRequest = anArr[i]; - let callbackId = bidRequest.bidId; - loadScript(buildJPTCall(bidRequest, callbackId)); - } - }; - - function buildJPTCall(bid, callbackId) { - // determine tag params - const placementId = utils.getBidIdParameter('placementId', bid.params); - const member = utils.getBidIdParameter('member', bid.params); - const inventoryCode = utils.getBidIdParameter('invCode', bid.params); - let referrer = utils.getBidIdParameter('referrer', bid.params); - const altReferrer = utils.getBidIdParameter('alt_referrer', bid.params); - - // Build tag, always use https - let jptCall = 'https://ib.adnxs.com/jpt?'; - - jptCall = utils.tryAppendQueryString(jptCall, 'callback', '$$PREBID_GLOBAL$$.handleXhbCB'); - jptCall = utils.tryAppendQueryString(jptCall, 'callback_uid', callbackId); - jptCall = utils.tryAppendQueryString(jptCall, 'id', placementId); - jptCall = utils.tryAppendQueryString(jptCall, 'psa', '0'); - jptCall = utils.tryAppendQueryString(jptCall, 'member', member); - jptCall = utils.tryAppendQueryString(jptCall, 'code', inventoryCode); - jptCall = utils.tryAppendQueryString(jptCall, 'traffic_source_code', (utils.getBidIdParameter('trafficSourceCode', bid.params))); - - // sizes takes a bit more logic - let sizeQueryString = ''; - let parsedSizes = utils.parseSizesInput(bid.sizes); - - // combine string into proper querystring for impbus - let parsedSizesLength = parsedSizes.length; - if (parsedSizesLength > 0) { - // first value should be "size" - sizeQueryString = 'size=' + parsedSizes[0]; - if (parsedSizesLength > 1) { - // any subsequent values should be "promo_sizes" - sizeQueryString += '&promo_sizes='; - for (let j = 1; j < parsedSizesLength; j++) { - sizeQueryString += parsedSizes[j] += ','; - } - // remove trailing comma - if (sizeQueryString && sizeQueryString.charAt(sizeQueryString.length - 1) === ',') { - sizeQueryString = sizeQueryString.slice(0, sizeQueryString.length - 1); - } - } - } - - if (sizeQueryString) { - jptCall += sizeQueryString + '&'; - } - - // append referrer - if (referrer === '') { - referrer = utils.getTopWindowUrl(); - } - - jptCall = utils.tryAppendQueryString(jptCall, 'referrer', referrer); - jptCall = utils.tryAppendQueryString(jptCall, 'alt_referrer', altReferrer); - - // remove the trailing "&" - if (jptCall.lastIndexOf('&') === jptCall.length - 1) { - jptCall = jptCall.substring(0, jptCall.length - 1); - } - - return jptCall; - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.handleXhbCB = function (jptResponseObj) { - let bidCode; - - if (jptResponseObj && jptResponseObj.callback_uid) { - let responseCPM; - const id = jptResponseObj.callback_uid; - let placementCode = ''; - const bidObj = utils.getBidRequest(id); - if (bidObj) { - bidCode = bidObj.bidder; - placementCode = bidObj.placementCode; - - // set the status - bidObj.status = STATUS.GOOD; - } - - let bid = []; - if (jptResponseObj.result && jptResponseObj.result.ad && jptResponseObj.result.ad !== '') { - responseCPM = 0.00; - - // store bid response - // bid status is good (indicating 1) - let adId = jptResponseObj.result.creative_id; - bid = bidfactory.createBid(STATUS.GOOD, bidObj); - bid.creative_id = adId; - bid.bidderCode = bidCode; - bid.cpm = responseCPM; - bid.adUrl = jptResponseObj.result.ad; - bid.width = jptResponseObj.result.width; - bid.height = jptResponseObj.result.height; - bid.dealId = '99999999'; - - bidmanager.addBidResponse(placementCode, bid); - } else { - // no response data - // indicate that there is no bid for this placement - bid = bidfactory.createBid(STATUS.NO_BID, bidObj); - bid.bidderCode = bidCode; - bidmanager.addBidResponse(placementCode, bid); - } - - if (!usersync) { - let iframe = utils.createInvisibleIframe(); - iframe.src = '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html'; - try { - document.body.appendChild(iframe); - } catch (error) { - utils.logError(error); - } - usersync = true; - } - } - }; - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode, - buildJPTCall: buildJPTCall - }); -}; - -adaptermanager.registerBidAdapter(new XhbAdapter(), 'xhb'); - -module.exports = XhbAdapter; diff --git a/modules/yieldbotBidAdapter.js b/modules/yieldbotBidAdapter.js deleted file mode 100644 index 4f874a82502..00000000000 --- a/modules/yieldbotBidAdapter.js +++ /dev/null @@ -1,200 +0,0 @@ -/** - * @overview Yieldbot sponsored Prebid.js adapter. - * @author elljoh - */ -var adloader = require('src/adloader'); -var bidfactory = require('src/bidfactory'); -var bidmanager = require('src/bidmanager'); -var utils = require('src/utils'); -var adaptermanager = require('src/adaptermanager'); - -/** - * Adapter for requesting bids from Yieldbot. - * - * @returns {Object} Object containing implementation for invocation in {@link module:adaptermanger.callBids} - * @class - */ -function YieldbotAdapter() { - window.ybotq = window.ybotq || []; - - var ybotlib = { - BID_STATUS: { - PENDING: 0, - AVAILABLE: 1, - EMPTY: 2 - }, - pageLevelOption: false, - /** - * Builds the Yieldbot creative tag. - * - * @param {String} slot - The slot name to bid for - * @param {String} size - The dimenstions of the slot - * @private - */ - buildCreative: function (slot, size) { - return '' + - ''; - }, - /** - * Bid response builder. - * - * @param {Object} slotCriteria - Yieldbot bid criteria - * @private - */ - buildBid: function (slotCriteria) { - var bid = {}; - - if (slotCriteria && slotCriteria.ybot_ad && slotCriteria.ybot_ad !== 'n') { - bid = bidfactory.createBid(ybotlib.BID_STATUS.AVAILABLE); - - bid.cpm = parseInt(slotCriteria.ybot_cpm) / 100.0 || 0; // Yieldbot CPM bids are in cents - - var szArr = slotCriteria.ybot_size ? slotCriteria.ybot_size.split('x') : [0, 0]; - var slot = slotCriteria.ybot_slot || ''; - var sizeStr = slotCriteria.ybot_size || ''; // Creative template needs the dimensions string - - bid.width = szArr[0] || 0; - bid.height = szArr[1] || 0; - - bid.ad = ybotlib.buildCreative(slot, sizeStr); - - // Add Yieldbot parameters to allow publisher bidderSettings.yieldbot specific targeting - for (var k in slotCriteria) { - bid[k] = slotCriteria[k]; - } - } else { - bid = bidfactory.createBid(ybotlib.BID_STATUS.EMPTY); - } - - bid.bidderCode = 'yieldbot'; - return bid; - }, - /** - * Unique'ify slot sizes for a Yieldbot bid request
- * Bids may refer to a slot and dimension multiple times on a page, but should exist once in the request. - * @param {Array} sizes An array of sizes to deduplicate - * @private - */ - getUniqueSlotSizes: function(sizes) { - var newSizes = []; - var hasSize = {}; - if (utils.isArray(sizes)) { - for (var idx = 0; idx < sizes.length; idx++) { - var bidSize = sizes[idx] || ''; - if (bidSize && utils.isStr(bidSize) && !hasSize[bidSize]) { - var nSize = bidSize.split('x'); - if (nSize.length > 1) { - newSizes.push([nSize[0], nSize[1]]); - } - hasSize[bidSize] = true; - } - } - } - return newSizes; - }, - /** - * Yieldbot implementation of {@link module:adaptermanger.callBids} - * @param {Object} params - Adapter bid configuration object - * @private - */ - callBids: function (params) { - var bids = params.bids || []; - var ybotq = window.ybotq || []; - - ybotlib.pageLevelOption = false; - - ybotq.push(function () { - var yieldbot = window.yieldbot; - // Empty defined slot bids object - ybotlib.bids = {}; - ybotlib.parsedBidSizes = {}; - // Iterate through bids to obtain Yieldbot slot config - // - Slot config can be different between initial and refresh requests - var psn = 'ERROR_PREBID_DEFINE_YB_PSN'; - var slots = {}; - utils._each(bids, function (v) { - var bid = v; - // bidder params config: http://prebid.org/dev-docs/bidders/yieldbot.html - // - last psn wins - psn = bid.params && bid.params.psn ? bid.params.psn : psn; - var slotName = bid.params && bid.params.slot ? bid.params.slot : 'ERROR_PREBID_DEFINE_YB_SLOT'; - var parsedSizes = utils.parseSizesInput(bid.sizes) || []; - slots[slotName] = slots[slotName] || []; - slots[slotName] = slots[slotName].concat(parsedSizes); - ybotlib.bids[bid.bidId] = bid; - ybotlib.parsedBidSizes[bid.bidId] = parsedSizes; - }); - - for (var bidSlots in slots) { - if (slots.hasOwnProperty(bidSlots)) { - // The same slot name and size may be used for multiple bids. Get unique sizes - // for the request. - slots[bidSlots] = ybotlib.getUniqueSlotSizes(slots[bidSlots]); - } - } - - if (yieldbot._initialized !== true) { - yieldbot.pub(psn); - for (var slotName in slots) { - if (slots.hasOwnProperty(slotName)) { - yieldbot.defineSlot(slotName, { sizes: slots[slotName] }); - } - } - yieldbot.enableAsync(); - yieldbot.go(); - } else if (!utils.isEmpty(slots)) { - yieldbot.nextPageview(slots); - } - }); - - ybotq.push(function () { - ybotlib.handleUpdateState(); - }); - adloader.loadScript('//cdn.yldbt.com/js/yieldbot.intent.js', null, true); - }, - /** - * Yieldbot bid request callback handler. - * - * @see {@link YieldbotAdapter~_callBids} - * @private - */ - handleUpdateState: function () { - var yieldbot = window.yieldbot; - var slotUsed = {}; - - for (var bidId in ybotlib.bids) { - if (ybotlib.bids.hasOwnProperty(bidId)) { - var bidRequest = ybotlib.bids[bidId] || null; - - if (bidRequest && bidRequest.params && bidRequest.params.slot) { - var placementCode = bidRequest.placementCode || 'ERROR_YB_NO_PLACEMENT'; - var criteria = yieldbot.getSlotCriteria(bidRequest.params.slot); - var requestedSizes = ybotlib.parsedBidSizes[bidId] || []; - - var slotSizeOk = false; - for (var idx = 0; idx < requestedSizes.length; idx++) { - var requestedSize = requestedSizes[idx]; - - if (!slotUsed[criteria.ybot_slot] && requestedSize === criteria.ybot_size) { - slotSizeOk = true; - slotUsed[criteria.ybot_slot] = true; - break; - } - } - var bid = ybotlib.buildBid(slotSizeOk ? criteria : { ybot_ad: 'n' }); - bidmanager.addBidResponse(placementCode, bid); - } - } - } - } - }; - return { - callBids: ybotlib.callBids, - getUniqueSlotSizes: ybotlib.getUniqueSlotSizes - }; -} - -adaptermanager.registerBidAdapter(new YieldbotAdapter(), 'yieldbot'); - -module.exports = YieldbotAdapter; diff --git a/modules/yieldmoBidAdapter.js b/modules/yieldmoBidAdapter.js deleted file mode 100644 index b7a5ceda08c..00000000000 --- a/modules/yieldmoBidAdapter.js +++ /dev/null @@ -1,151 +0,0 @@ -var utils = require('src/utils.js'); -var adloader = require('src/adloader.js'); -var bidmanager = require('src/bidmanager.js'); -var bidfactory = require('src/bidfactory.js'); -var adaptermanager = require('src/adaptermanager'); - -/** - * Adapter for requesting bids from Yieldmo. - * - * @returns {{callBids: _callBids}} - * @constructor - */ - -var YieldmoAdapter = function YieldmoAdapter() { - function _callBids(params) { - var bids = params.bids; - adloader.loadScript(buildYieldmoCall(bids)); - } - - function buildYieldmoCall(bids) { - // build our base tag, based on if we are http or https - var ymURI = '//ads.yieldmo.com/exchange/prebid?'; - var ymCall = document.location.protocol + ymURI; - - // Placement specific information - ymCall = _appendPlacementInformation(ymCall, bids); - - // General impression params - ymCall = _appendImpressionInformation(ymCall); - - // remove the trailing "&" - if (ymCall.lastIndexOf('&') === ymCall.length - 1) { - ymCall = ymCall.substring(0, ymCall.length - 1); - } - - utils.logMessage('ymCall request built: ' + ymCall); - - return ymCall; - } - - function _appendPlacementInformation(url, bids) { - var placements = []; - var placement; - var bid; - - for (var i = 0; i < bids.length; i++) { - bid = bids[i]; - - placement = {}; - placement.callback_id = bid.bidId; - placement.placement_id = bid.placementCode; - placement.sizes = bid.sizes; - - if (bid.params && bid.params.placementId) { - placement.ym_placement_id = bid.params.placementId; - } - - placements.push(placement); - } - - url = utils.tryAppendQueryString(url, 'p', JSON.stringify(placements)); - return url; - } - - function _appendImpressionInformation(url) { - var page_url = document.location; // page url - var pr = document.referrer || ''; // page's referrer - var dnt = (navigator.doNotTrack || false).toString(); // true if user enabled dnt (false by default) - var _s = document.location.protocol === 'https:' ? 1 : 0; // 1 if page is secure - var description = _getPageDescription(); - var title = document.title || ''; // Value of the title from the publisher's page. - var bust = new Date().getTime().toString(); // cache buster - var scrd = window.devicePixelRatio || 0; // screen pixel density - - url = utils.tryAppendQueryString(url, 'callback', '$$PREBID_GLOBAL$$.YMCB'); - url = utils.tryAppendQueryString(url, 'page_url', page_url); - url = utils.tryAppendQueryString(url, 'pr', pr); - url = utils.tryAppendQueryString(url, 'bust', bust); - url = utils.tryAppendQueryString(url, '_s', _s); - url = utils.tryAppendQueryString(url, 'scrd', scrd); - url = utils.tryAppendQueryString(url, 'dnt', dnt); - url = utils.tryAppendQueryString(url, 'description', description); - url = utils.tryAppendQueryString(url, 'title', title); - - return url; - } - - function _getPageDescription() { - if (document.querySelector('meta[name="description"]')) { - return document.querySelector('meta[name="description"]').getAttribute('content'); // Value of the description metadata from the publisher's page. - } else { - return ''; - } - } - - // expose the callback to the global object: - $$PREBID_GLOBAL$$.YMCB = function(ymResponses) { - if (ymResponses && ymResponses.constructor === Array && ymResponses.length > 0) { - for (var i = 0; i < ymResponses.length; i++) { - _registerPlacementBid(ymResponses[i]); - } - } else { - // If an incorrect response is returned, register error bids for all placements - // to prevent Prebid waiting till timeout for response - _registerNoResponseBids(); - - utils.logMessage('No prebid response for placement %%PLACEMENT%%'); - } - }; - - function _registerPlacementBid(response) { - var bidObj = utils.getBidRequest(response.callback_id); - var placementCode = bidObj && bidObj.placementCode; - var bid = []; - - if (response && response.cpm && response.cpm !== 0) { - bid = bidfactory.createBid(1, bidObj); - bid.bidderCode = 'yieldmo'; - bid.cpm = response.cpm; - bid.ad = response.ad; - bid.width = response.width; - bid.height = response.height; - bidmanager.addBidResponse(placementCode, bid); - } else { - // no response data - if (bidObj) { utils.logMessage('No prebid response from yieldmo for placementCode: ' + bidObj.placementCode); } - bid = bidfactory.createBid(2, bidObj); - bid.bidderCode = 'yieldmo'; - bidmanager.addBidResponse(placementCode, bid); - } - } - - function _registerNoResponseBids() { - var yieldmoBidRequests = $$PREBID_GLOBAL$$._bidsRequested.find(bid => bid.bidderCode === 'yieldmo'); - - utils._each(yieldmoBidRequests.bids, function (currentBid) { - var bid = []; - bid = bidfactory.createBid(2, currentBid); - bid.bidderCode = 'yieldmo'; - bidmanager.addBidResponse(currentBid.placementCode, bid); - }); - } - - return Object.assign(this, { - callBids: _callBids - }); -}; - -adaptermanager.registerBidAdapter(new YieldmoAdapter(), 'yieldmo'); - -module.exports = YieldmoAdapter; diff --git a/package.json b/package.json index 99558bec6e9..61c9edf2b82 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "0.34.1", + "version": "1.0.0", "description": "Header Bidding Management Library", "main": "src/prebid.js", "scripts": { diff --git a/src/adaptermanager.js b/src/adaptermanager.js index b463f7abe8b..95db1e74b2a 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -1,9 +1,12 @@ /** @module adaptermanger */ import { flatten, getBidderCodes, getDefinedParams, shuffle } from './utils'; -import { mapSizes } from './sizeMapping'; +import { resolveStatus } from './sizeMapping'; import { processNativeAdUnitParams, nativeAdapters } from './native'; import { newBidder } from './adapters/bidderFactory'; +import { ajaxBuilder } from 'src/ajax'; +import { config, RANDOM } from 'src/config'; +import includes from 'core-js/library/fn/array/includes'; var utils = require('./utils.js'); var CONSTANTS = require('./constants.json'); @@ -13,100 +16,149 @@ let s2sTestingModule; // store s2sTesting module if it's loaded var _bidderRegistry = {}; exports.bidderRegistry = _bidderRegistry; -// create s2s settings objectType_function -let _s2sConfig = { - endpoint: CONSTANTS.S2S.DEFAULT_ENDPOINT, - adapter: CONSTANTS.S2S.ADAPTER, - syncEndpoint: CONSTANTS.S2S.SYNC_ENDPOINT -}; +let _s2sConfig = {}; +config.getConfig('s2sConfig', config => { + _s2sConfig = config.s2sConfig; +}); -const RANDOM = 'random'; -const FIXED = 'fixed'; +var _analyticsRegistry = {}; -const VALID_ORDERS = {}; -VALID_ORDERS[RANDOM] = true; -VALID_ORDERS[FIXED] = true; +/** + * @typedef {object} LabelDescriptor + * @property {boolean} labelAll describes whether or not this object expects all labels to match, or any label to match + * @property {Array} labels the labels listed on the bidder or adUnit + * @property {Array} activeLabels the labels specified as being active by requestBids + */ + +/** + * Returns object describing the status of labels on the adUnit or bidder along with labels passed into requestBids + * @param bidOrAdUnit the bidder or adUnit to get label info on + * @param activeLabels the labels passed to requestBids + * @returns {LabelDescriptor} + */ +function getLabels(bidOrAdUnit, activeLabels) { + if (bidOrAdUnit.labelAll) { + return {labelAll: true, labels: bidOrAdUnit.labelAll, activeLabels}; + } + return {labelAll: false, labels: bidOrAdUnit.labelAny, activeLabels}; +} -var _analyticsRegistry = {}; -let _bidderSequence = RANDOM; - -function getBids({bidderCode, requestId, bidderRequestId, adUnits}) { - return adUnits.map(adUnit => { - return adUnit.bids.filter(bid => bid.bidder === bidderCode) - .map(bid => { - let sizes = adUnit.sizes; - if (adUnit.sizeMapping) { - let sizeMapping = mapSizes(adUnit); - if (sizeMapping === '') { - return ''; +function getBids({bidderCode, auctionId, bidderRequestId, adUnits, labels}) { + return adUnits.reduce((result, adUnit) => { + let {active, sizes: filteredAdUnitSizes} = resolveStatus(getLabels(adUnit, labels), adUnit.sizes); + + if (active) { + result.push(adUnit.bids.filter(bid => bid.bidder === bidderCode) + .reduce((bids, bid) => { + if (adUnit.mediaTypes) { + if (utils.isValidMediaTypes(adUnit.mediaTypes)) { + bid = Object.assign({}, bid, {mediaTypes: adUnit.mediaTypes}); + } else { + utils.logError( + `mediaTypes is not correctly configured for adunit ${adUnit.code}` + ); + } } - sizes = sizeMapping; - } - if (adUnit.mediaTypes) { - if (utils.isValidMediaTypes(adUnit.mediaTypes)) { - bid = Object.assign({}, bid, { mediaTypes: adUnit.mediaTypes }); - } else { - utils.logError( - `mediaTypes is not correctly configured for adunit ${adUnit.code}` - ); + const nativeParams = + adUnit.nativeParams || utils.deepAccess(adUnit, 'mediaTypes.native'); + if (nativeParams) { + bid = Object.assign({}, bid, { + nativeParams: processNativeAdUnitParams(nativeParams), + }); } - } - const nativeParams = - adUnit.nativeParams || utils.deepAccess(adUnit, 'mediaTypes.native'); - if (nativeParams) { - bid = Object.assign({}, bid, { - nativeParams: processNativeAdUnitParams(nativeParams), - }); - } - - bid = Object.assign({}, bid, getDefinedParams(adUnit, [ - 'mediaType', - 'renderer' - ])); - - return Object.assign({}, bid, { - placementCode: adUnit.code, - transactionId: adUnit.transactionId, - sizes: sizes, - bidId: bid.bid_id || utils.getUniqueIdentifierStr(), - bidderRequestId, - requestId - }); - } + bid = Object.assign({}, bid, getDefinedParams(adUnit, [ + 'mediaType', + 'renderer' + ])); + + let {active, sizes} = resolveStatus(getLabels(bid, labels), filteredAdUnitSizes); + + if (active) { + bids.push(Object.assign({}, bid, { + adUnitCode: adUnit.code, + transactionId: adUnit.transactionId, + sizes: sizes, + bidId: bid.bid_id || utils.getUniqueIdentifierStr(), + bidderRequestId, + auctionId + })); + } + return bids; + }, []) ); - }).reduce(flatten, []).filter(val => val !== ''); + } + return result; + }, []).reduce(flatten, []).filter(val => val !== ''); +} + +function transformHeightWidth(adUnit) { + let sizesObj = []; + let sizes = utils.parseSizesInput(adUnit.sizes); + sizes.forEach(size => { + let heightWidth = size.split('x'); + let sizeObj = { + 'w': parseInt(heightWidth[0]), + 'h': parseInt(heightWidth[1]) + }; + sizesObj.push(sizeObj); + }); + return sizesObj; +} + +function getAdUnitCopyForPrebidServer(adUnits) { + let adaptersServerSide = _s2sConfig.bidders; + let adUnitsCopy = utils.deepClone(adUnits); + + adUnitsCopy.forEach((adUnit) => { + adUnit.sizes = transformHeightWidth(adUnit); + + // filter out client side bids + adUnit.bids = adUnit.bids.filter((bid) => { + return includes(adaptersServerSide, bid.bidder) && (!doingS2STesting() || bid.finalSource !== s2sTestingModule.CLIENT); + }).map((bid) => { + bid.bid_id = utils.getUniqueIdentifierStr(); + return bid; + }); + }); + + // don't send empty requests + adUnitsCopy = adUnitsCopy.filter(adUnit => { + return adUnit.bids.length !== 0; + }); + return adUnitsCopy; } -exports.callBids = ({adUnits, cbTimeout}) => { - const requestId = utils.generateUUID(); - const auctionStart = Date.now(); +function getAdUnitCopyForClientAdapters(adUnits) { + let adUnitsClientCopy = utils.deepClone(adUnits); + // filter out s2s bids + adUnitsClientCopy.forEach((adUnit) => { + adUnit.bids = adUnit.bids.filter((bid) => { + return !doingS2STesting() || bid.finalSource !== s2sTestingModule.SERVER; + }) + }); + + // don't send empty requests + adUnitsClientCopy = adUnitsClientCopy.filter(adUnit => { + return adUnit.bids.length !== 0; + }); - const auctionInit = { - timestamp: auctionStart, - requestId, - timeout: cbTimeout - }; - events.emit(CONSTANTS.EVENTS.AUCTION_INIT, auctionInit); + return adUnitsClientCopy; +} +exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, labels) { + let bidRequests = []; let bidderCodes = getBidderCodes(adUnits); - if (_bidderSequence === RANDOM) { + if (config.getConfig('bidderSequence') === RANDOM) { bidderCodes = shuffle(bidderCodes); } - const s2sAdapter = _bidderRegistry[_s2sConfig.adapter]; - if (s2sAdapter) { - s2sAdapter.setConfig(_s2sConfig); - s2sAdapter.queueSync({bidderCodes}); - } - + let clientBidderCodes = bidderCodes; let clientTestAdapters = []; - let s2sTesting = false; if (_s2sConfig.enabled) { // if s2sConfig.bidderControl testing is turned on - s2sTesting = _s2sConfig.testing && typeof s2sTestingModule !== 'undefined'; - if (s2sTesting) { + if (doingS2STesting()) { // get all adapters doing client testing clientTestAdapters = s2sTestingModule.getSourceBidderMap(adUnits)[s2sTestingModule.CLIENT]; } @@ -115,124 +167,125 @@ exports.callBids = ({adUnits, cbTimeout}) => { let adaptersServerSide = _s2sConfig.bidders; // don't call these client side (unless client request is needed for testing) - bidderCodes = bidderCodes.filter((elm) => { - return !adaptersServerSide.includes(elm) || clientTestAdapters.includes(elm); - }); - let adUnitsS2SCopy = utils.deepClone(adUnits); - - // filter out client side bids - adUnitsS2SCopy.forEach((adUnit) => { - if (adUnit.sizeMapping) { - adUnit.sizes = mapSizes(adUnit); - delete adUnit.sizeMapping; - } - adUnit.sizes = transformHeightWidth(adUnit); - adUnit.bids = adUnit.bids.filter((bid) => { - return adaptersServerSide.includes(bid.bidder) && (!s2sTesting || bid.finalSource !== s2sTestingModule.CLIENT); - }).map((bid) => { - bid.bid_id = utils.getUniqueIdentifierStr(); - return bid; - }); - }); - - // don't send empty requests - adUnitsS2SCopy = adUnitsS2SCopy.filter(adUnit => { - return adUnit.bids.length !== 0; + clientBidderCodes = bidderCodes.filter((elm) => { + return !includes(adaptersServerSide, elm) || includes(clientTestAdapters, elm); }); + let adUnitsS2SCopy = getAdUnitCopyForPrebidServer(adUnits); let tid = utils.generateUUID(); adaptersServerSide.forEach(bidderCode => { const bidderRequestId = utils.getUniqueIdentifierStr(); const bidderRequest = { bidderCode, - requestId, + auctionId, bidderRequestId, tid, - bids: getBids({bidderCode, requestId, bidderRequestId, 'adUnits': adUnitsS2SCopy}), - start: new Date().getTime(), + bids: getBids({bidderCode, auctionId, bidderRequestId, 'adUnits': adUnitsS2SCopy, labels}), auctionStart: auctionStart, timeout: _s2sConfig.timeout, src: CONSTANTS.S2S.SRC }; if (bidderRequest.bids.length !== 0) { - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - events.emit(CONSTANTS.EVENTS.BID_REQUESTED, bidderRequest); + bidRequests.push(bidderRequest); } }); + } - let s2sBidRequest = {tid, 'ad_units': adUnitsS2SCopy}; - utils.logMessage(`CALLING S2S HEADER BIDDERS ==== ${adaptersServerSide.join(',')}`); - if (s2sBidRequest.ad_units.length) { - s2sAdapter.callBids(s2sBidRequest); + // client adapters + let adUnitsClientCopy = getAdUnitCopyForClientAdapters(adUnits); + clientBidderCodes.forEach(bidderCode => { + const bidderRequestId = utils.getUniqueIdentifierStr(); + const bidderRequest = { + bidderCode, + auctionId, + bidderRequestId, + bids: getBids({bidderCode, auctionId, bidderRequestId, 'adUnits': adUnitsClientCopy, labels}), + auctionStart: auctionStart, + timeout: cbTimeout + }; + if (bidderRequest.bids && bidderRequest.bids.length !== 0) { + bidRequests.push(bidderRequest); } + }); + return bidRequests; +}; + +exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => { + if (!bidRequests.length) { + utils.logWarn('callBids executed with no bidRequests. Were they filtered by labels or sizing?'); + return; } - let _bidderRequests = []; - // client side adapters - let adUnitsClientCopy = utils.deepClone(adUnits); - // filter out s2s bids - adUnitsClientCopy.forEach((adUnit) => { - adUnit.bids = adUnit.bids.filter((bid) => { - return !s2sTesting || bid.finalSource !== s2sTestingModule.SERVER; - }) - }); + let ajax = ajaxBuilder(bidRequests[0].timeout); - // don't send empty requests - adUnitsClientCopy = adUnitsClientCopy.filter(adUnit => { - return adUnit.bids.length !== 0; - }); + let [clientBidRequests, serverBidRequests] = bidRequests.reduce((partitions, bidRequest) => { + partitions[Number(typeof bidRequest.src !== 'undefined' && bidRequest.src === CONSTANTS.S2S.SRC)].push(bidRequest); + return partitions; + }, [[], []]); - bidderCodes.forEach(bidderCode => { - const adapter = _bidderRegistry[bidderCode]; - if (adapter) { - const bidderRequestId = utils.getUniqueIdentifierStr(); - const bidderRequest = { - bidderCode, - requestId, - bidderRequestId, - bids: getBids({bidderCode, requestId, bidderRequestId, 'adUnits': adUnitsClientCopy}), - auctionStart: auctionStart, - timeout: cbTimeout - }; + if (serverBidRequests.length) { + let adaptersServerSide = _s2sConfig.bidders; + const s2sAdapter = _bidderRegistry[_s2sConfig.adapter]; + let tid = serverBidRequests[0].tid; + + if (s2sAdapter) { + let s2sBidRequest = {tid, 'ad_units': getAdUnitCopyForPrebidServer(adUnits)}; + if (s2sBidRequest.ad_units.length) { + let doneCbs = serverBidRequests.map(bidRequest => { + bidRequest.doneCbCallCount = 0; + return doneCb(bidRequest.bidderRequestId) + }); - if (bidderRequest.bids && bidderRequest.bids.length !== 0) { - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - _bidderRequests.push(bidderRequest); + // only log adapters that actually have adUnit bids + let allBidders = s2sBidRequest.ad_units.reduce((adapters, adUnit) => { + return adapters.concat((adUnit.bids || []).reduce((adapters, bid) => { return adapters.concat(bid.bidder) }, [])); + }, []); + utils.logMessage(`CALLING S2S HEADER BIDDERS ==== ${adaptersServerSide.filter(adapter => { + return includes(allBidders, adapter); + }).join(',')}`); + + // fire BID_REQUESTED event for each s2s bidRequest + serverBidRequests.forEach(bidRequest => { + events.emit(CONSTANTS.EVENTS.BID_REQUESTED, bidRequest); + }); + + // make bid requests + s2sAdapter.callBids( + s2sBidRequest, + serverBidRequests, + addBidResponse, + () => doneCbs.forEach(done => done()), + ajax + ); } - } else { - utils.logError(`Adapter trying to be called which does not exist: ${bidderCode} adaptermanager.callBids`); } - }); + } - _bidderRequests.forEach(bidRequest => { + // handle client adapter requests + clientBidRequests.forEach(bidRequest => { bidRequest.start = new Date().getTime(); + // TODO : Do we check for bid in pool from here and skip calling adapter again ? const adapter = _bidderRegistry[bidRequest.bidderCode]; - if (bidRequest.bids && bidRequest.bids.length !== 0) { + if (adapter) { utils.logMessage(`CALLING BIDDER ======= ${bidRequest.bidderCode}`); events.emit(CONSTANTS.EVENTS.BID_REQUESTED, bidRequest); - adapter.callBids(bidRequest); + bidRequest.doneCbCallCount = 0; + let done = doneCb(bidRequest.bidderRequestId); + adapter.callBids(bidRequest, addBidResponse, done, ajax); + } else { + utils.logError(`Adapter trying to be called which does not exist: ${bidRequest.bidderCode} adaptermanager.callBids`); } - }) -}; - -function transformHeightWidth(adUnit) { - let sizesObj = []; - let sizes = utils.parseSizesInput(adUnit.sizes); - sizes.forEach(size => { - let heightWidth = size.split('x'); - let sizeObj = { - 'w': parseInt(heightWidth[0]), - 'h': parseInt(heightWidth[1]) - }; - sizesObj.push(sizeObj); }); - return sizesObj; +} + +function doingS2STesting() { + return _s2sConfig && _s2sConfig.enabled && _s2sConfig.testing && s2sTestingModule; } function getSupportedMediaTypes(bidderCode) { let result = []; - if (exports.videoAdapters.includes(bidderCode)) result.push('video'); - if (nativeAdapters.includes(bidderCode)) result.push('native'); + if (includes(exports.videoAdapters, bidderCode)) result.push('video'); + if (includes(nativeAdapters, bidderCode)) result.push('native'); return result; } @@ -243,10 +296,10 @@ exports.registerBidAdapter = function (bidAdaptor, bidderCode, {supportedMediaTy if (typeof bidAdaptor.callBids === 'function') { _bidderRegistry[bidderCode] = bidAdaptor; - if (supportedMediaTypes.includes('video')) { + if (includes(supportedMediaTypes, 'video')) { exports.videoAdapters.push(bidderCode); } - if (supportedMediaTypes.includes('native')) { + if (includes(supportedMediaTypes, 'native')) { nativeAdapters.push(bidderCode); } } else { @@ -319,22 +372,10 @@ exports.enableAnalytics = function (config) { }); }; -exports.setBidderSequence = function (order) { - if (VALID_ORDERS[order]) { - _bidderSequence = order; - } else { - utils.logWarn(`Invalid order: ${order}. Bidder Sequence was not set.`); - } -}; - exports.getBidAdapter = function(bidder) { return _bidderRegistry[bidder]; }; -exports.setS2SConfig = function (config) { - _s2sConfig = config; -}; - // the s2sTesting module is injected when it's loaded rather than being imported // importing it causes the packager to include it even when it's not explicitly included in the build exports.setS2STestingModule = function (module) { diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 7535d6ad613..ed3cc28db32 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -1,13 +1,14 @@ import Adapter from 'src/adapter'; import adaptermanager from 'src/adaptermanager'; import { config } from 'src/config'; -import { ajax } from 'src/ajax'; -import bidmanager from 'src/bidmanager'; import bidfactory from 'src/bidfactory'; import { STATUS } from 'src/constants'; import { userSync } from 'src/userSync'; +import { nativeBidIsValid } from 'src/native'; +import { isValidVideoBid } from 'src/video'; +import includes from 'core-js/library/fn/array/includes'; -import { logWarn, logError, parseQueryStringParameters, delayExecution } from 'src/utils'; +import { logWarn, logError, parseQueryStringParameters, delayExecution, parseSizesInput, getBidderRequest } from 'src/utils'; /** * This file aims to support Adapters during the Prebid 0.x -> 1.x transition. @@ -155,47 +156,24 @@ export function newBidder(spec) { return Object.freeze(spec); }, registerSyncs, - callBids: function(bidderRequest) { + callBids: function(bidderRequest, addBidResponse, done, ajax) { if (!Array.isArray(bidderRequest.bids)) { return; } - // callBids must add a NO_BID response for _every_ AdUnit code, in order for the auction to - // end properly. This map stores placement codes which we've made _real_ bids on. - // - // As we add _real_ bids to the bidmanager, we'll log the ad unit codes here too. Once all the real - // bids have been added, fillNoBids() can be called to add NO_BID bids for any extra ad units, which - // will end the auction. - // - // In Prebid 1.0, this will be simplified to use the `addBidResponse` and `done` callbacks. const adUnitCodesHandled = {}; function addBidWithCode(adUnitCode, bid) { adUnitCodesHandled[adUnitCode] = true; - addBid(adUnitCode, bid); - } - function fillNoBids() { - bidderRequest.bids - .map(bidRequest => bidRequest.placementCode) - .forEach(adUnitCode => { - if (adUnitCode && !adUnitCodesHandled[adUnitCode]) { - addBid(adUnitCode, newEmptyBid()); - } - }); - } - - function addBid(code, bid) { - try { - bidmanager.addBidResponse(code, bid); - } catch (err) { - logError('Error adding bid', code, err); + if (isValid(adUnitCode, bid, [bidderRequest])) { + addBidResponse(adUnitCode, bid); } } - // After all the responses have come back, fill up the "no bid" bids and + // After all the responses have come back, call done() and // register any required usersync pixels. const responses = []; function afterAllResponses() { - fillNoBids(); + done(); registerSyncs(responses); } @@ -222,7 +200,7 @@ export function newBidder(spec) { requests = [requests]; } - // Callbacks don't compose as nicely as Promises. We should call fillNoBids() once _all_ the + // Callbacks don't compose as nicely as Promises. We should call done() once _all_ the // Server requests have returned and been processed. Since `ajax` accepts a single callback, // we need to rig up a function which only executes after all the requests have been responded. const onResponse = delayExecution(afterAllResponses, requests.length) @@ -274,7 +252,7 @@ export function newBidder(spec) { // If the server responds successfully, use the adapter code to unpack the Bids from it. // If the adapter code fails, no bids should be added. After all the bids have been added, make - // sure to call the `onResponse` function so that we're one step closer to calling fillNoBids(). + // sure to call the `onResponse` function so that we're one step closer to calling done(). function onSuccess(response, responseObj) { try { response = JSON.parse(response); @@ -306,17 +284,12 @@ export function newBidder(spec) { onResponse(); function addBidUsingRequestMap(bid) { - // In Prebid 1.0 all the validation logic from bidmanager will move here, as of now we are only validating new params so that adapters dont miss adding them. - if (hasValidKeys(bid)) { - const bidRequest = bidRequestMap[bid.requestId]; - if (bidRequest) { - const prebidBid = Object.assign(bidfactory.createBid(STATUS.GOOD, bidRequest), bid); - addBidWithCode(bidRequest.placementCode, prebidBid); - } else { - logWarn(`Bidder ${spec.code} made bid for unknown request ID: ${bid.requestId}. Ignoring.`); - } + const bidRequest = bidRequestMap[bid.requestId]; + if (bidRequest) { + const prebidBid = Object.assign(bidfactory.createBid(STATUS.GOOD, bidRequest), bid); + addBidWithCode(bidRequest.adUnitCode, prebidBid); } else { - logError(`Bidder ${spec.code} is missing required params. Check http://prebid.org/dev-docs/bidder-adapter-1.html for list of params.`); + logWarn(`Bidder ${spec.code} made bid for unknown request ID: ${bid.requestId}. Ignoring.`); } } @@ -328,7 +301,7 @@ export function newBidder(spec) { } // If the server responds with an error, there's not much we can do. Log it, and make sure to - // call onResponse() so that we're one step closer to calling fillNoBids(). + // call onResponse() so that we're one step closer to calling done(). function onFailure(err) { logError(`Server call for ${spec.code} failed: ${err}. Continuing without bids.`); onResponse(); @@ -361,16 +334,69 @@ export function newBidder(spec) { } return true; } +} + +// check that the bid has a width and height set +function validBidSize(adUnitCode, bid, bidRequests) { + if ((bid.width || bid.width === 0) && (bid.height || bid.height === 0)) { + return true; + } + + const adUnit = getBidderRequest(bidRequests, bid.bidderCode, adUnitCode); + + const sizes = adUnit && adUnit.bids && adUnit.bids[0] && adUnit.bids[0].sizes; + const parsedSizes = parseSizesInput(sizes); + + // if a banner impression has one valid size, we assign that size to any bid + // response that does not explicitly set width or height + if (parsedSizes.length === 1) { + const [ width, height ] = parsedSizes[0].split('x'); + bid.width = width; + bid.height = height; + return true; + } - function hasValidKeys(bid) { + return false; +} + +// Validate the arguments sent to us by the adapter. If this returns false, the bid should be totally ignored. +export function isValid(adUnitCode, bid, bidRequests) { + function hasValidKeys() { let bidKeys = Object.keys(bid); - return COMMON_BID_RESPONSE_KEYS.every(key => bidKeys.includes(key)); + return COMMON_BID_RESPONSE_KEYS.every(key => includes(bidKeys, key)); + } + + function errorMessage(msg) { + return `Invalid bid from ${bid.bidderCode}. Ignoring bid: ${msg}`; } - function newEmptyBid() { - const bid = bidfactory.createBid(STATUS.NO_BID); - bid.code = spec.code; - bid.bidderCode = spec.code; - return bid; + if (!adUnitCode) { + logWarn('No adUnitCode was supplied to addBidResponse.'); + return false; } + + if (!bid) { + logWarn(`Some adapter tried to add an undefined bid for ${adUnitCode}.`); + return false; + } + + if (!hasValidKeys()) { + logError(errorMessage(`Bidder ${bid.bidderCode} is missing required params. Check http://prebid.org/dev-docs/bidder-adapter-1.html for list of params.`)); + return false; + } + + if (bid.mediaType === 'native' && !nativeBidIsValid(bid, bidRequests)) { + logError(errorMessage('Native bid missing some required properties.')); + return false; + } + if (bid.mediaType === 'video' && !isValidVideoBid(bid, bidRequests)) { + logError(errorMessage(`Video bid does not have required vastUrl or renderer property`)); + return false; + } + if (bid.mediaType === 'banner' && !validBidSize(adUnitCode, bid, bidRequests)) { + logError(errorMessage(`Banner bids require a width and height`)); + return false; + } + + return true; } diff --git a/src/adserver.js b/src/adserver.js index 55f4ee9b44f..cfde042e46e 100644 --- a/src/adserver.js +++ b/src/adserver.js @@ -1,12 +1,12 @@ -import {formatQS} from './url'; -import {getWinningBids} from './targeting'; +import { formatQS } from './url'; +import { targeting } from './targeting'; // Adserver parent class const AdServer = function(attr) { this.name = attr.adserver; this.code = attr.code; this.getWinningBidByCode = function() { - return getWinningBids(this.code)[0]; + return targeting.getWinningBids(this.code)[0]; }; }; diff --git a/src/ajax.js b/src/ajax.js index 44ff00a0fe0..19dc1b3869f 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -3,7 +3,6 @@ import {parse as parseURL, format as formatURL} from './url'; var utils = require('./utils'); const XHR_DONE = 4; -let _timeout = 3000; /** * Simple IE9+ and cross-browser ajax request function @@ -14,91 +13,94 @@ let _timeout = 3000; * @param data mixed data * @param options object */ -export function setAjaxTimeout(timeout) { - _timeout = timeout; -} +export const ajax = ajaxBuilder(); -export function ajax(url, callback, data, options = {}) { - try { - let x; - let useXDomainRequest = false; - let method = options.method || (data ? 'POST' : 'GET'); +export function ajaxBuilder(timeout = 3000) { + return function(url, callback, data, options = {}) { + try { + let x; + let useXDomainRequest = false; + let method = options.method || (data ? 'POST' : 'GET'); - let callbacks = typeof callback === 'object' ? callback : { - success: function() { - utils.logMessage('xhr success'); - }, - error: function(e) { - utils.logError('xhr error', null, e); - } - }; + let callbacks = typeof callback === 'object' ? callback : { + success: function() { + utils.logMessage('xhr success'); + }, + error: function(e) { + utils.logError('xhr error', null, e); + } + }; - if (typeof callback === 'function') { - callbacks.success = callback; - } + if (typeof callback === 'function') { + callbacks.success = callback; + } - if (!window.XMLHttpRequest) { - useXDomainRequest = true; - } else { - x = new window.XMLHttpRequest(); - if (x.responseType === undefined) { + if (!window.XMLHttpRequest) { useXDomainRequest = true; + } else { + x = new window.XMLHttpRequest(); + if (x.responseType === undefined) { + useXDomainRequest = true; + } } - } - if (useXDomainRequest) { - x = new window.XDomainRequest(); - x.onload = function () { - callbacks.success(x.responseText, x); - }; + if (useXDomainRequest) { + x = new window.XDomainRequest(); + x.onload = function () { + callbacks.success(x.responseText, x); + }; - // http://stackoverflow.com/questions/15786966/xdomainrequest-aborts-post-on-ie-9 - x.onerror = function () { - callbacks.error('error', x); - }; - x.ontimeout = function () { - callbacks.error('timeout', x); - }; - x.onprogress = function() { - utils.logMessage('xhr onprogress'); - }; - } else { - x.onreadystatechange = function () { - if (x.readyState === XHR_DONE) { - let status = x.status; - if ((status >= 200 && status < 300) || status === 304) { - callbacks.success(x.responseText, x); - } else { - callbacks.error(x.statusText, x); + // http://stackoverflow.com/questions/15786966/xdomainrequest-aborts-post-on-ie-9 + x.onerror = function () { + callbacks.error('error', x); + }; + x.ontimeout = function () { + callbacks.error('timeout', x); + }; + x.onprogress = function() { + utils.logMessage('xhr onprogress'); + }; + } else { + x.onreadystatechange = function () { + if (x.readyState === XHR_DONE) { + let status = x.status; + if ((status >= 200 && status < 300) || status === 304) { + callbacks.success(x.responseText, x); + } else { + callbacks.error(x.statusText, x); + } } - } - }; - } + }; + x.ontimeout = function () { + utils.logError(' xhr timeout after ', x.timeout, 'ms'); + }; + } - if (method === 'GET' && data) { - let urlInfo = parseURL(url, options); - Object.assign(urlInfo.search, data); - url = formatURL(urlInfo); - } + if (method === 'GET' && data) { + let urlInfo = parseURL(url, options); + Object.assign(urlInfo.search, data); + url = formatURL(urlInfo); + } - x.open(method, url); - // IE needs timoeut to be set after open - see #1410 - x.timeout = _timeout; + x.open(method, url); + // IE needs timoeut to be set after open - see #1410 + x.timeout = timeout; - if (!useXDomainRequest) { - if (options.withCredentials) { - x.withCredentials = true; - } - utils._each(options.customHeaders, (value, header) => { - x.setRequestHeader(header, value); - }); - if (options.preflight) { - x.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + if (!useXDomainRequest) { + if (options.withCredentials) { + x.withCredentials = true; + } + utils._each(options.customHeaders, (value, header) => { + x.setRequestHeader(header, value); + }); + if (options.preflight) { + x.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + } + x.setRequestHeader('Content-Type', options.contentType || 'text/plain'); } - x.setRequestHeader('Content-Type', options.contentType || 'text/plain'); + x.send(method === 'POST' && data); + } catch (error) { + utils.logError('xhr construction', error); } - x.send(method === 'POST' && data); - } catch (error) { - utils.logError('xhr construction', error); } } diff --git a/src/auction.js b/src/auction.js new file mode 100644 index 00000000000..82aaa88cf56 --- /dev/null +++ b/src/auction.js @@ -0,0 +1,506 @@ +/** + * Module for auction instances. + * + * In Prebid 0.x, $$PREBID_GLOBAL$$ had _bidsRequested and _bidsReceived as public properties. + * Starting 1.0, Prebid will support concurrent auctions. Each auction instance will store private properties, bidsRequested and bidsReceived. + * + * AuctionManager will create instance of auction and will store all the auctions. + * + */ + +/** + * @typedef {Object} AdUnit An object containing the adUnit configuration. + * + * @property {string} code A code which will be used to uniquely identify this bidder. This should be the same + * one as is used in the call to registerBidAdapter + * @property {Array.} sizes A list of size for adUnit. + * @property {object} params Any bidder-specific params which the publisher used in their bid request. + * This is guaranteed to have passed the spec.areParamsValid() test. + */ + +/** + * @typedef {Array.} size + */ + +/** + * @typedef {Array.} AdUnitCode + */ + +/** + * @typedef {Object} BidRequest + * //TODO add all properties + */ + +/** + * @typedef {Object} BidReceived + * //TODO add all properties + */ + +/** + * @typedef {Object} Auction + * + * @property {function(): string} getAuctionStatus - returns the auction status which can be any one of 'started', 'in progress' or 'completed' + * @property {function(): AdUnit[]} getAdUnits - return the adUnits for this auction instance + * @property {function(): AdUnitCode[]} getAdUnitCodes - return the adUnitCodes for this auction instance + * @property {function(): BidRequest[]} getBidRequests - get all bid requests for this auction instance + * @property {function(): BidReceived[]} getBidsReceived - get all bid received for this auction instance + * @property {function(): void} startAuctionTimer - sets the bidsBackHandler callback and starts the timer for auction + * @property {function(): void} callBids - sends requests to all adapters for bids + */ + +import { uniques, flatten, timestamp, adUnitsFilter, delayExecution, getBidderRequest } from './utils'; +import { getPriceBucketString } from './cpmBucketManager'; +import { getNativeTargeting } from './native'; +import { getCacheUrl, store } from './videoCache'; +import { Renderer } from 'src/Renderer'; +import { config } from 'src/config'; +import { userSync } from 'src/userSync'; +import { createHook } from 'src/hook'; +import { videoAdUnit } from 'src/video'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; + +const { syncUsers } = userSync; +const utils = require('./utils'); +const adaptermanager = require('./adaptermanager'); +const events = require('./events'); +const CONSTANTS = require('./constants.json'); + +export const AUCTION_STARTED = 'started'; +export const AUCTION_IN_PROGRESS = 'inProgress'; +export const AUCTION_COMPLETED = 'completed'; + +// register event for bid adjustment +events.on(CONSTANTS.EVENTS.BID_ADJUSTMENT, function (bid) { + adjustBids(bid); +}); + +/** + * Creates new auction instance + * + * @param {Object} requestConfig + * @param {AdUnit} requestConfig.adUnits + * @param {AdUnitCode} requestConfig.adUnitCode + * + * @returns {Auction} auction instance + */ +export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) { + let _adUnits = adUnits; + let _labels = labels; + let _adUnitCodes = adUnitCodes; + let _bidderRequests = []; + let _bidsReceived = []; + let _auctionStart; + let _auctionId = utils.generateUUID(); + let _auctionStatus; + let _callback = callback; + let _timer; + let _timeout = cbTimeout; + let _winningBid; + + function addBidRequests(bidderRequests) { _bidderRequests = _bidderRequests.concat(bidderRequests) }; + function addBidReceived(bidsReceived) { _bidsReceived = _bidsReceived.concat(bidsReceived); } + + function startAuctionTimer() { + const timedOut = true; + const timeoutCallback = executeCallback.bind(null, timedOut); + let timer = setTimeout(timeoutCallback, _timeout); + _timer = timer; + } + + function executeCallback(timedOut, cleartimer) { + // clear timer when done calls executeCallback + if (cleartimer) { + clearTimeout(_timer); + } + + if (_callback != null) { + if (timedOut) { + utils.logMessage(`Auction ${_auctionId} timedOut`); + const timedOutBidders = getTimedOutBids(_bidderRequests, _bidsReceived); + if (timedOutBidders.length) { + events.emit(CONSTANTS.EVENTS.BID_TIMEOUT, timedOutBidders); + } + } + + events.emit(CONSTANTS.EVENTS.AUCTION_END, {auctionId: _auctionId}); + + try { + _auctionStatus = AUCTION_COMPLETED; + const adUnitCodes = _adUnitCodes; + const bids = [_bidsReceived + .filter(adUnitsFilter.bind(this, adUnitCodes)) + .reduce(groupByPlacement, {})]; + _callback.apply($$PREBID_GLOBAL$$, bids); + } catch (e) { + utils.logError('Error executing bidsBackHandler', null, e); + } finally { + // Only automatically sync if the publisher has not chosen to "enableOverride" + let userSyncConfig = config.getConfig('userSync') || {}; + if (!userSyncConfig.enableOverride) { + // Delay the auto sync by the config delay + syncUsers(userSyncConfig.syncDelay); + } + } + _callback = null; + } + } + + function done(bidRequestId) { + var innerBidRequestId = bidRequestId; + return delayExecution(function() { + let request = find(_bidderRequests, (bidRequest) => { + return innerBidRequestId === bidRequest.bidderRequestId; + }); + request.doneCbCallCount += 1; + // In case of mediaType video and prebidCache enabled, call bidsBackHandler after cache is stored. + if ((request.bids.filter(videoAdUnit).length == 0) || (request.bids.filter(videoAdUnit).length > 0 && !config.getConfig('cache.url'))) { + bidsBackAll() + } + }, 1); + } + + /** + * Execute bidBackHandler if all bidders have called done. + */ + function bidsBackAll() { + if (_bidderRequests.every((bidRequest) => bidRequest.doneCbCallCount >= 1)) { + // when all bidders have called done callback atleast once it means auction is complete + utils.logInfo(`Bids Received for Auction with id: ${_auctionId}`, _bidsReceived); + _auctionStatus = AUCTION_COMPLETED; + executeCallback(false, true); + } + } + + function callBids() { + startAuctionTimer(); + _auctionStatus = AUCTION_STARTED; + _auctionStart = Date.now(); + + const auctionInit = { + timestamp: _auctionStart, + auctionId: _auctionId, + timeout: _timeout + }; + events.emit(CONSTANTS.EVENTS.AUCTION_INIT, auctionInit); + + let bidRequests = adaptermanager.makeBidRequests(_adUnits, _auctionStart, _auctionId, _timeout, _labels); + utils.logInfo(`Bids Requested for Auction with id: ${_auctionId}`, bidRequests); + bidRequests.forEach(bidRequest => { + addBidRequests(bidRequest); + }); + + _auctionStatus = AUCTION_IN_PROGRESS; + adaptermanager.callBids(_adUnits, bidRequests, addBidResponse.bind(this), done.bind(this)); + }; + + return { + addBidReceived, + executeCallback, + callBids, + bidsBackAll, + setWinningBid: (winningBid) => { _winningBid = winningBid }, + getWinningBid: () => _winningBid, + getTimeout: () => _timeout, + getAuctionId: () => _auctionId, + getAuctionStatus: () => _auctionStatus, + getAdUnits: () => _adUnits, + getAdUnitCodes: () => _adUnitCodes, + getBidRequests: () => _bidderRequests, + getBidsReceived: () => _bidsReceived, + } +} + +export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid) { + let auctionInstance = this; + let bidRequests = auctionInstance.getBidRequests(); + let auctionId = auctionInstance.getAuctionId(); + + let bidResponse = getPreparedBidForAuction({adUnitCode, bid, bidRequests, auctionId}); + if (bidResponse.mediaType === 'video') { + tryAddVideoBid(bidResponse); + } else { + doCallbacksIfNeeded(); + addBidToAuction(bidResponse); + } + + function doCallbacksIfNeeded() { + if (bidResponse.timeToRespond > auctionInstance.getTimeout() + config.getConfig('timeoutBuffer')) { + auctionInstance.executeCallback(true); + } + } + + // Add a bid to the auction. + function addBidToAuction() { + events.emit(CONSTANTS.EVENTS.BID_RESPONSE, bidResponse); + auctionInstance.addBidReceived(bidResponse); + } + + // Video bids may fail if the cache is down, or there's trouble on the network. + function tryAddVideoBid(bidResponse) { + if (config.getConfig('cache.url')) { + store([bidResponse], function(error, cacheIds) { + if (error) { + utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`); + } else { + bidResponse.videoCacheKey = cacheIds[0].uuid; + if (!bid.vastUrl) { + bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); + } + addBidToAuction(bidResponse); + auctionInstance.bidsBackAll(); + } + doCallbacksIfNeeded(); + }); + } else { + addBidToAuction(bidResponse); + doCallbacksIfNeeded(); + } + } +}, 'addBidResponse'); + +// Postprocess the bids so that all the universal properties exist, no matter which bidder they came from. +// This should be called before addBidToAuction(). +function getPreparedBidForAuction({adUnitCode, bid, bidRequests, auctionId}) { + let bidRequest = getBidderRequest(bidRequests, bid.bidderCode, adUnitCode); + + const start = bidRequest.start; + + let bidObject = Object.assign({}, bid, { + auctionId, + requestId: bidRequest.requestId, + responseTimestamp: timestamp(), + requestTimestamp: start, + cpm: parseFloat(bid.cpm) || 0, + bidder: bid.bidderCode, + adUnitCode + }); + + bidObject.timeToRespond = bidObject.responseTimestamp - bidObject.requestTimestamp; + + // Let listeners know that now is the time to adjust the bid, if they want to. + // + // CAREFUL: Publishers rely on certain bid properties to be available (like cpm), + // but others to not be set yet (like priceStrings). See #1372 and #1389. + events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, bidObject); + + // a publisher-defined renderer can be used to render bids + const adUnitRenderer = + bidRequest.bids && bidRequest.bids[0] && bidRequest.bids[0].renderer; + + if (adUnitRenderer) { + bidObject.renderer = Renderer.install({ url: adUnitRenderer.url }); + bidObject.renderer.setRender(adUnitRenderer.render); + } + + const priceStringsObj = getPriceBucketString( + bidObject.cpm, + config.getConfig('customPriceBucket'), + config.getConfig('currency.granularityMultiplier') + ); + bidObject.pbLg = priceStringsObj.low; + bidObject.pbMg = priceStringsObj.med; + bidObject.pbHg = priceStringsObj.high; + bidObject.pbAg = priceStringsObj.auto; + bidObject.pbDg = priceStringsObj.dense; + bidObject.pbCg = priceStringsObj.custom; + + // if there is any key value pairs to map do here + var keyValues; + if (bidObject.bidderCode && (bidObject.cpm > 0 || bidObject.dealId)) { + keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject); + } + + // use any targeting provided as defaults, otherwise just set from getKeyValueTargetingPairs + bidObject.adserverTargeting = Object.assign(bidObject.adserverTargeting || {}, keyValues); + + return bidObject; +} + +export function getStandardBidderSettings() { + let granularity = config.getConfig('priceGranularity'); + let bidder_settings = $$PREBID_GLOBAL$$.bidderSettings; + if (!bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]) { + bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] = {}; + } + if (!bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { + bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING] = [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + if (granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) { + return bidResponse.pbAg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) { + return bidResponse.pbDg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) { + return bidResponse.pbLg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) { + return bidResponse.pbMg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) { + return bidResponse.pbHg; + } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.CUSTOM) { + return bidResponse.pbCg; + } + } + }, { + key: 'hb_size', + val: function (bidResponse) { + return bidResponse.size; + } + }, { + key: 'hb_deal', + val: function (bidResponse) { + return bidResponse.dealId; + } + } + ] + } + return bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]; +} + +export function getKeyValueTargetingPairs(bidderCode, custBidObj) { + var keyValues = {}; + var bidder_settings = $$PREBID_GLOBAL$$.bidderSettings; + + // 1) set the keys from "standard" setting or from prebid defaults + if (custBidObj && bidder_settings) { + // initialize default if not set + const standardSettings = getStandardBidderSettings(); + setKeys(keyValues, standardSettings, custBidObj); + } + + // 2) set keys from specific bidder setting override if they exist + if (bidderCode && custBidObj && bidder_settings && bidder_settings[bidderCode] && bidder_settings[bidderCode][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { + setKeys(keyValues, bidder_settings[bidderCode], custBidObj); + custBidObj.sendStandardTargeting = bidder_settings[bidderCode].sendStandardTargeting; + } + + // set native key value targeting + if (custBidObj.native) { + keyValues = Object.assign({}, keyValues, getNativeTargeting(custBidObj)); + } + + return keyValues; +} + +function setKeys(keyValues, bidderSettings, custBidObj) { + var targeting = bidderSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]; + custBidObj.size = custBidObj.getSize(); + + utils._each(targeting, function (kvPair) { + var key = kvPair.key; + var value = kvPair.val; + + if (keyValues[key]) { + utils.logWarn('The key: ' + key + ' is getting ovewritten'); + } + + if (utils.isFn(value)) { + try { + value = value(custBidObj); + } catch (e) { + utils.logError('bidmanager', 'ERROR', e); + } + } + + if ( + ((typeof bidderSettings.suppressEmptyKeys !== 'undefined' && bidderSettings.suppressEmptyKeys === true) || + key === 'hb_deal') && // hb_deal is suppressed automatically if not set + ( + utils.isEmptyStr(value) || + value === null || + value === undefined + ) + ) { + utils.logInfo("suppressing empty key '" + key + "' from adserver targeting"); + } else { + keyValues[key] = value; + } + }); + + return keyValues; +} + +export function adjustBids(bid) { + let code = bid.bidderCode; + let bidPriceAdjusted = bid.cpm; + let bidCpmAdjustment; + if ($$PREBID_GLOBAL$$.bidderSettings) { + if (code && $$PREBID_GLOBAL$$.bidderSettings[code] && typeof $$PREBID_GLOBAL$$.bidderSettings[code].bidCpmAdjustment === 'function') { + bidCpmAdjustment = $$PREBID_GLOBAL$$.bidderSettings[code].bidCpmAdjustment; + } else if ($$PREBID_GLOBAL$$.bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] && typeof $$PREBID_GLOBAL$$.bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD].bidCpmAdjustment === 'function') { + bidCpmAdjustment = $$PREBID_GLOBAL$$.bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD].bidCpmAdjustment; + } + if (bidCpmAdjustment) { + try { + bidPriceAdjusted = bidCpmAdjustment(bid.cpm, Object.assign({}, bid)); + } catch (e) { + utils.logError('Error during bid adjustment', 'bidmanager.js', e); + } + } + } + + if (bidPriceAdjusted >= 0) { + bid.cpm = bidPriceAdjusted; + } +} + +/** + * groupByPlacement is a reduce function that converts an array of Bid objects + * to an object with placement codes as keys, with each key representing an object + * with an array of `Bid` objects for that placement + * @returns {*} as { [adUnitCode]: { bids: [Bid, Bid, Bid] } } + */ +function groupByPlacement(bidsByPlacement, bid) { + if (!bidsByPlacement[bid.adUnitCode]) { bidsByPlacement[bid.adUnitCode] = { bids: [] }; } + bidsByPlacement[bid.adUnitCode].bids.push(bid); + return bidsByPlacement; +} + +/** + * Returns a list of bids that we haven't received a response yet + * @param {BidRequest[]} bidderRequests List of bids requested for auction instance + * @param {BidReceived[]} bidsReceived List of bids received for auction instance + * + * @typedef {Object} TimedOutBid + * @property {string} bidId The id representing the bid + * @property {string} bidder The string name of the bidder + * @property {string} adUnitCode The code used to uniquely identify the ad unit on the publisher's page + * @property {string} auctionId The id representing the auction + * + * @return {Array} List of bids that Prebid hasn't received a response for + */ +function getTimedOutBids(bidderRequests, bidsReceived) { + const bidRequestedCodes = bidderRequests + .map(bid => bid.bidderCode) + .filter(uniques); + + const bidReceivedCodes = bidsReceived + .map(bid => bid.bidder) + .filter(uniques); + + const timedOutBidderCodes = bidRequestedCodes + .filter(bidder => !includes(bidReceivedCodes, bidder)); + + const timedOutBids = bidderRequests + .map(bid => (bid.bids || []).filter(bid => includes(timedOutBidderCodes, bid.bidder))) + .reduce(flatten, []) + .map(bid => ({ + bidId: bid.bidId, + bidder: bid.bidder, + adUnitCode: bid.adUnitCode, + auctionId: bid.auctionId, + })); + + return timedOutBids; +} diff --git a/src/auctionManager.js b/src/auctionManager.js new file mode 100644 index 00000000000..65723d6c199 --- /dev/null +++ b/src/auctionManager.js @@ -0,0 +1,98 @@ +/** + * AuctionManager modules is responsible for creating auction instances. + * This module is the gateway for Prebid core to access auctions. + * It stores all created instances of auction and can be used to get consolidated values from auction. + */ + +/** + * @typedef {Object} AuctionManager + * + * @property {function(): Array} getBidsRequested - returns cosolidated bid requests + * @property {function(): Array} getBidsReceived - returns cosolidated bid received + * @property {function(): Array} getAdUnits - returns cosolidated adUnits + * @property {function(): Array} getAdUnitCodes - returns cosolidated adUnitCodes + * @property {function(): Object} createAuction - creates auction instance and stores it for future reference + * @property {function(): Object} findBidByAdId - find bid received by adId. This function will be called by $$PREBID_GLOBAL$$.renderAd + * @property {function(): Object} getStandardBidderAdServerTargeting - returns standard bidder targeting for all the adapters. Refer http://prebid.org/dev-docs/publisher-api-reference.html#module_pbjs.bidderSettings for more details + */ + +import { uniques, flatten } from './utils'; +import { newAuction, getStandardBidderSettings, AUCTION_COMPLETED } from 'src/auction'; +import find from 'core-js/library/fn/array/find'; + +const CONSTANTS = require('./constants.json'); + +/** + * Creates new instance of auctionManager. There will only be one instance of auctionManager but + * a factory is created to assist in testing. + * + * @returns {AuctionManager} auctionManagerInstance + */ +export function newAuctionManager() { + let _auctions = []; + let auctionManager = {}; + + auctionManager.addWinningBid = function(bid) { + const auction = find(_auctions, auction => auction.getAuctionId() === bid.auctionId); + if (auction) { + auction.setWinningBid(bid); + } else { + utils.logWarn(`Auction not found when adding winning bid`); + } + } + + auctionManager.getAllWinningBids = function() { + return _auctions.map(auction => auction.getWinningBid()) + .reduce(flatten, []); + } + + auctionManager.getBidsRequested = function() { + return _auctions.map(auction => auction.getBidRequests()) + .reduce(flatten, []); + }; + + auctionManager.getBidsReceived = function() { + // As of now, an old bid which is not used in auction 1 can be used in auction n. + // To prevent this, bid.ttl (time to live) will be added to this logic and bid pool will also be added + // As of now none of the adapters are sending back bid.ttl + return _auctions.map((auction) => { + if (auction.getAuctionStatus() === AUCTION_COMPLETED) { + return auction.getBidsReceived(); + } + }).reduce(flatten, []) + .filter(bid => bid); + }; + + auctionManager.getAdUnits = function() { + return _auctions.map(auction => auction.getAdUnits()) + .reduce(flatten, []); + }; + + auctionManager.getAdUnitCodes = function() { + return _auctions.map(auction => auction.getAdUnitCodes()) + .reduce(flatten, []) + .filter(uniques); + }; + + auctionManager.createAuction = function({ adUnits, adUnitCodes, callback, cbTimeout, labels }) { + const auction = newAuction({ adUnits, adUnitCodes, callback, cbTimeout, labels }); + _addAuction(auction); + return auction; + }; + + auctionManager.findBidByAdId = function(adId) { + return find(_auctions.map(auction => auction.getBidsReceived()).reduce(flatten, []), bid => bid.adId === adId); + }; + + auctionManager.getStandardBidderAdServerTargeting = function() { + return getStandardBidderSettings()[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]; + }; + + function _addAuction(auction) { + _auctions.push(auction); + } + + return auctionManager; +} + +export const auctionManager = newAuctionManager(); diff --git a/src/bidmanager.js b/src/bidmanager.js deleted file mode 100644 index f3379e7fee4..00000000000 --- a/src/bidmanager.js +++ /dev/null @@ -1,509 +0,0 @@ -import { uniques, flatten, adUnitsFilter, getBidderRequest } from './utils'; -import { getPriceBucketString } from './cpmBucketManager'; -import { nativeBidIsValid, getNativeTargeting } from './native'; -import { isValidVideoBid } from './video'; -import { getCacheUrl, store } from './videoCache'; -import { Renderer } from 'src/Renderer'; -import { config } from 'src/config'; -import { createHook } from 'src/hook'; - -var CONSTANTS = require('./constants.json'); -var AUCTION_END = CONSTANTS.EVENTS.AUCTION_END; -var utils = require('./utils.js'); -var events = require('./events'); - -var externalCallbacks = {byAdUnit: [], all: [], oneTime: null, timer: false}; -var defaultBidderSettingsMap = {}; - -/** - * Returns a list of bidders that we haven't received a response yet - * @return {array} [description] - */ -exports.getTimedOutBidders = function () { - return $$PREBID_GLOBAL$$._bidsRequested - .map(getBidderCode) - .filter(uniques) - .filter(bidder => $$PREBID_GLOBAL$$._bidsReceived - .map(getBidders) - .filter(uniques) - .indexOf(bidder) < 0); -}; - -function timestamp() { return new Date().getTime(); } - -function getBidderCode(bidSet) { - return bidSet.bidderCode; -} - -function getBidders(bid) { - return bid.bidder; -} - -function bidsBackAdUnit(adUnitCode) { - const requested = $$PREBID_GLOBAL$$._bidsRequested - .map(request => request.bids - .filter(adUnitsFilter.bind(this, $$PREBID_GLOBAL$$._adUnitCodes)) - .filter(bid => bid.placementCode === adUnitCode)) - .reduce(flatten, []) - .map(bid => { - return bid.bidder === 'indexExchange' - ? bid.sizes.length - : 1; - }).reduce(add, 0); - - const received = $$PREBID_GLOBAL$$._bidsReceived.filter(bid => bid.adUnitCode === adUnitCode).length; - return requested === received; -} - -function add(a, b) { - return a + b; -} - -function bidsBackAll() { - const requested = $$PREBID_GLOBAL$$._bidsRequested - .map(request => request.bids) - .reduce(flatten, []) - .filter(adUnitsFilter.bind(this, $$PREBID_GLOBAL$$._adUnitCodes)) - .map(bid => { - return bid.bidder === 'indexExchange' - ? bid.sizes.length - : 1; - }).reduce((a, b) => a + b, 0); - - const received = $$PREBID_GLOBAL$$._bidsReceived - .filter(adUnitsFilter.bind(this, $$PREBID_GLOBAL$$._adUnitCodes)).length; - - return requested === received; -} - -exports.bidsBackAll = function () { - return bidsBackAll(); -}; - -// Validate the arguments sent to us by the adapter. If this returns false, the bid should be totally ignored. -function isValidBid(bid, adUnitCode) { - function errorMessage(msg) { - return `Invalid bid from ${bid.bidderCode}. Ignoring bid: ${msg}`; - } - - if (!bid) { - utils.logError(`Some adapter tried to add an undefined bid for ${adUnitCode}.`); - return false; - } - if (!adUnitCode) { - utils.logError(errorMessage('No adUnitCode was supplied to addBidResponse.')); - return false; - } - - const bidRequest = getBidderRequest(bid.bidderCode, adUnitCode); - if (!bidRequest.start) { - utils.logError(errorMessage('Cannot find valid matching bid request.')); - return false; - } - - if (bid.mediaType === 'native' && !nativeBidIsValid(bid)) { - utils.logError(errorMessage('Native bid missing some required properties.')); - return false; - } - if (bid.mediaType === 'video' && !isValidVideoBid(bid)) { - utils.logError(errorMessage(`Video bid does not have required vastUrl or renderer property`)); - return false; - } - if (bid.mediaType === 'banner' && !validBidSize(bid, adUnitCode)) { - utils.logError(errorMessage(`Banner bids require a width and height`)); - return false; - } - - return true; -} - -// check that the bid has a width and height set -function validBidSize(bid, adUnitCode) { - if ((bid.width || bid.width === 0) && (bid.height || bid.height === 0)) { - return true; - } - - const adUnit = getBidderRequest(bid.bidderCode, adUnitCode); - const sizes = adUnit && adUnit.bids && adUnit.bids[0] && adUnit.bids[0].sizes; - const parsedSizes = utils.parseSizesInput(sizes); - - // if a banner impression has one valid size, we assign that size to any bid - // response that does not explicitly set width or height - if (parsedSizes.length === 1) { - const [ width, height ] = parsedSizes[0].split('x'); - bid.width = width; - bid.height = height; - return true; - } - - return false; -} - -// Postprocess the bids so that all the universal properties exist, no matter which bidder they came from. -// This should be called before addBidToAuction(). -function prepareBidForAuction(bid, adUnitCode) { - const bidRequest = getBidderRequest(bid.bidderCode, adUnitCode); - - Object.assign(bid, { - requestId: bidRequest.requestId, - responseTimestamp: timestamp(), - requestTimestamp: bidRequest.start, - cpm: parseFloat(bid.cpm) || 0, - bidder: bid.bidderCode, - adUnitCode - }); - - bid.timeToRespond = bid.responseTimestamp - bid.requestTimestamp; - - // Let listeners know that now is the time to adjust the bid, if they want to. - // - // CAREFUL: Publishers rely on certain bid properties to be available (like cpm), - // but others to not be set yet (like priceStrings). See #1372 and #1389. - events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, bid); - - // a publisher-defined renderer can be used to render bids - const adUnitRenderer = - bidRequest.bids && bidRequest.bids[0] && bidRequest.bids[0].renderer; - - if (adUnitRenderer) { - bid.renderer = Renderer.install({ url: adUnitRenderer.url }); - bid.renderer.setRender(adUnitRenderer.render); - } - - const priceStringsObj = getPriceBucketString( - bid.cpm, - config.getConfig('customPriceBucket'), - config.getConfig('currency.granularityMultiplier') - ); - bid.pbLg = priceStringsObj.low; - bid.pbMg = priceStringsObj.med; - bid.pbHg = priceStringsObj.high; - bid.pbAg = priceStringsObj.auto; - bid.pbDg = priceStringsObj.dense; - bid.pbCg = priceStringsObj.custom; - - // if there is any key value pairs to map do here - var keyValues; - if (bid.bidderCode && (bid.cpm > 0 || bid.dealId)) { - keyValues = getKeyValueTargetingPairs(bid.bidderCode, bid); - } - - // use any targeting provided as defaults, otherwise just set from getKeyValueTargetingPairs - bid.adserverTargeting = Object.assign(bid.adserverTargeting || {}, keyValues); -} - -function doCallbacksIfNeeded(bid) { - if (bid.timeToRespond > $$PREBID_GLOBAL$$.cbTimeout + $$PREBID_GLOBAL$$.timeoutBuffer) { - const timedOut = true; - exports.executeCallback(timedOut); - } -} - -// Add a bid to the auction. -function addBidToAuction(bid) { - events.emit(CONSTANTS.EVENTS.BID_RESPONSE, bid); - - $$PREBID_GLOBAL$$._bidsReceived.push(bid); - - if (bid.adUnitCode && bidsBackAdUnit(bid.adUnitCode)) { - triggerAdUnitCallbacks(bid.adUnitCode); - } - - if (bidsBackAll()) { - exports.executeCallback(); - } -} - -// Video bids may fail if the cache is down, or there's trouble on the network. -function tryAddVideoBid(bid) { - if (config.getConfig('usePrebidCache')) { - store([bid], function(error, cacheIds) { - if (error) { - utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`); - } else { - bid.videoCacheKey = cacheIds[0].uuid; - if (!bid.vastUrl) { - bid.vastUrl = getCacheUrl(bid.videoCacheKey); - } - addBidToAuction(bid); - } - doCallbacksIfNeeded(bid); - }); - } else { - addBidToAuction(bid); - doCallbacksIfNeeded(bid); - } -} - -/* - * This function should be called to by the bidder adapter to register a bid response - */ -exports.addBidResponse = createHook('asyncSeries', function (adUnitCode, bid) { - if (!isValidBid(bid, adUnitCode)) { - return; - } - prepareBidForAuction(bid, adUnitCode); - - if (bid.mediaType === 'video') { - tryAddVideoBid(bid); - } else { - addBidToAuction(bid); - doCallbacksIfNeeded(bid); - } -}); - -function getKeyValueTargetingPairs(bidderCode, custBidObj) { - var keyValues = {}; - var bidder_settings = $$PREBID_GLOBAL$$.bidderSettings; - - // 1) set the keys from "standard" setting or from prebid defaults - if (custBidObj && bidder_settings) { - // initialize default if not set - const standardSettings = getStandardBidderSettings(); - setKeys(keyValues, standardSettings, custBidObj); - } - - if (bidderCode && custBidObj && bidder_settings && bidder_settings[bidderCode] && bidder_settings[bidderCode][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { - // 2) set keys from specific bidder setting override if they exist - setKeys(keyValues, bidder_settings[bidderCode], custBidObj); - custBidObj.alwaysUseBid = bidder_settings[bidderCode].alwaysUseBid; - custBidObj.sendStandardTargeting = bidder_settings[bidderCode].sendStandardTargeting; - } else if (defaultBidderSettingsMap[bidderCode]) { - // 2) set keys from standard setting. NOTE: this API doesn't seem to be in use by any Adapter - setKeys(keyValues, defaultBidderSettingsMap[bidderCode], custBidObj); - custBidObj.alwaysUseBid = defaultBidderSettingsMap[bidderCode].alwaysUseBid; - custBidObj.sendStandardTargeting = defaultBidderSettingsMap[bidderCode].sendStandardTargeting; - } - - if (custBidObj['native']) { - keyValues = Object.assign({}, keyValues, getNativeTargeting(custBidObj)); - } - - return keyValues; -} - -exports.getKeyValueTargetingPairs = function() { - return getKeyValueTargetingPairs(...arguments); -}; - -function setKeys(keyValues, bidderSettings, custBidObj) { - var targeting = bidderSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]; - custBidObj.size = custBidObj.getSize(); - - utils._each(targeting, function (kvPair) { - var key = kvPair.key; - var value = kvPair.val; - - if (keyValues[key]) { - utils.logWarn('The key: ' + key + ' is getting ovewritten'); - } - - if (utils.isFn(value)) { - try { - value = value(custBidObj); - } catch (e) { - utils.logError('bidmanager', 'ERROR', e); - } - } - - if ( - ((typeof bidderSettings.suppressEmptyKeys !== 'undefined' && bidderSettings.suppressEmptyKeys === true) || - key === 'hb_deal') && // hb_deal is suppressed automatically if not set - ( - utils.isEmptyStr(value) || - value === null || - value === undefined - ) - ) { - utils.logInfo("suppressing empty key '" + key + "' from adserver targeting"); - } else { - keyValues[key] = value; - } - }); - - return keyValues; -} - -exports.registerDefaultBidderSetting = function (bidderCode, defaultSetting) { - defaultBidderSettingsMap[bidderCode] = defaultSetting; -}; - -exports.executeCallback = function (timedOut) { - // if there's still a timeout running, clear it now - if (!timedOut && externalCallbacks.timer) { - clearTimeout(externalCallbacks.timer); - } - - if (externalCallbacks.all.called !== true) { - processCallbacks(externalCallbacks.all); - externalCallbacks.all.called = true; - - if (timedOut) { - const timedOutBidders = exports.getTimedOutBidders(); - - if (timedOutBidders.length) { - events.emit(CONSTANTS.EVENTS.BID_TIMEOUT, timedOutBidders); - } - } - } - - // execute one time callback - if (externalCallbacks.oneTime) { - events.emit(AUCTION_END); - try { - processCallbacks([externalCallbacks.oneTime]); - } catch (e) { - utils.logError('Error executing bidsBackHandler', null, e); - } finally { - externalCallbacks.oneTime = null; - externalCallbacks.timer = false; - $$PREBID_GLOBAL$$.clearAuction(); - } - } -}; - -exports.externalCallbackReset = function () { - externalCallbacks.all.called = false; -}; - -function triggerAdUnitCallbacks(adUnitCode) { - // todo : get bid responses and send in args - var singleAdUnitCode = [adUnitCode]; - processCallbacks(externalCallbacks.byAdUnit, singleAdUnitCode); -} - -function processCallbacks(callbackQueue, singleAdUnitCode) { - if (utils.isArray(callbackQueue)) { - callbackQueue.forEach(callback => { - const adUnitCodes = singleAdUnitCode || $$PREBID_GLOBAL$$._adUnitCodes; - const bids = [$$PREBID_GLOBAL$$._bidsReceived - .filter(adUnitsFilter.bind(this, adUnitCodes)) - .reduce(groupByPlacement, {})]; - - callback.apply($$PREBID_GLOBAL$$, bids); - }); - } -} - -/** - * groupByPlacement is a reduce function that converts an array of Bid objects - * to an object with placement codes as keys, with each key representing an object - * with an array of `Bid` objects for that placement - * @returns {*} as { [adUnitCode]: { bids: [Bid, Bid, Bid] } } - */ -function groupByPlacement(bidsByPlacement, bid) { - if (!bidsByPlacement[bid.adUnitCode]) { bidsByPlacement[bid.adUnitCode] = { bids: [] }; } - - bidsByPlacement[bid.adUnitCode].bids.push(bid); - - return bidsByPlacement; -} - -/** - * Add a one time callback, that is discarded after it is called - * @param {Function} callback - * @param timer Timer to clear if callback is triggered before timer time's out - */ -exports.addOneTimeCallback = function (callback, timer) { - externalCallbacks.oneTime = callback; - externalCallbacks.timer = timer; -}; - -exports.addCallback = function (id, callback, cbEvent) { - callback.id = id; - if (CONSTANTS.CB.TYPE.ALL_BIDS_BACK === cbEvent) { - externalCallbacks.all.push(callback); - } else if (CONSTANTS.CB.TYPE.AD_UNIT_BIDS_BACK === cbEvent) { - externalCallbacks.byAdUnit.push(callback); - } -}; - -// register event for bid adjustment -events.on(CONSTANTS.EVENTS.BID_ADJUSTMENT, function (bid) { - adjustBids(bid); -}); - -function adjustBids(bid) { - var code = bid.bidderCode; - var bidPriceAdjusted = bid.cpm; - let bidCpmAdjustment; - if ($$PREBID_GLOBAL$$.bidderSettings) { - if (code && $$PREBID_GLOBAL$$.bidderSettings[code] && typeof $$PREBID_GLOBAL$$.bidderSettings[code].bidCpmAdjustment === 'function') { - bidCpmAdjustment = $$PREBID_GLOBAL$$.bidderSettings[code].bidCpmAdjustment; - } else if ($$PREBID_GLOBAL$$.bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] && typeof $$PREBID_GLOBAL$$.bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD].bidCpmAdjustment === 'function') { - bidCpmAdjustment = $$PREBID_GLOBAL$$.bidderSettings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD].bidCpmAdjustment; - } - if (bidCpmAdjustment) { - try { - bidPriceAdjusted = bidCpmAdjustment(bid.cpm, Object.assign({}, bid)); - } catch (e) { - utils.logError('Error during bid adjustment', 'bidmanager.js', e); - } - } - } - - if (bidPriceAdjusted >= 0) { - bid.cpm = bidPriceAdjusted; - } -} - -exports.adjustBids = function() { - return adjustBids(...arguments); -}; - -function getStandardBidderSettings() { - let granularity = config.getConfig('priceGranularity'); - let bidder_settings = $$PREBID_GLOBAL$$.bidderSettings; - if (!bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]) { - bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] = {}; - } - if (!bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) { - bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING] = [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - if (granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) { - return bidResponse.pbAg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) { - return bidResponse.pbDg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) { - return bidResponse.pbLg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) { - return bidResponse.pbMg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) { - return bidResponse.pbHg; - } else if (granularity === CONSTANTS.GRANULARITY_OPTIONS.CUSTOM) { - return bidResponse.pbCg; - } - } - }, { - key: 'hb_size', - val: function (bidResponse) { - return bidResponse.size; - } - }, { - key: 'hb_deal', - val: function (bidResponse) { - return bidResponse.dealId; - } - } - ]; - } - return bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]; -} - -function getStandardBidderAdServerTargeting() { - return getStandardBidderSettings()[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]; -} - -exports.getStandardBidderAdServerTargeting = getStandardBidderAdServerTargeting; diff --git a/src/config.js b/src/config.js index 5ed83e555b2..146c0f17a65 100644 --- a/src/config.js +++ b/src/config.js @@ -8,13 +8,26 @@ * continue to work during a deprecation window. */ import { isValidPriceConfig } from './cpmBucketManager'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; const utils = require('./utils'); const DEFAULT_DEBUG = false; const DEFAULT_BIDDER_TIMEOUT = 3000; const DEFAULT_PUBLISHER_DOMAIN = window.location.origin; const DEFAULT_COOKIESYNC_DELAY = 100; -const DEFAULT_ENABLE_SEND_ALL_BIDS = false; +const DEFAULT_ENABLE_SEND_ALL_BIDS = true; + +const DEFAULT_TIMEOUTBUFFER = 200; + +export const RANDOM = 'random'; +const FIXED = 'fixed'; + +const VALID_ORDERS = {}; +VALID_ORDERS[RANDOM] = true; +VALID_ORDERS[FIXED] = true; + +const DEFAULT_BIDDER_SEQUENCE = RANDOM; const GRANULARITY_OPTIONS = { LOW: 'low', @@ -30,117 +43,128 @@ const ALL_TOPICS = '*'; /** * @typedef {object} PrebidConfig * - * @property {bool} usePrebidCache True if we should use prebid-cache to store video bids before adding - * bids to the auction, and false otherwise. **NOTE** This must be true if you want to use the - * dfpAdServerVideo module. + * @property {string} cache.url Set a url if we should use prebid-cache to store video bids before adding + * bids to the auction. **NOTE** This must be set if you want to use the dfpAdServerVideo module. */ export function newConfig() { let listeners = []; - - let defaults = {}; - - let config = { - // `debug` is equivalent to legacy `pbjs.logging` property - _debug: DEFAULT_DEBUG, - get debug() { - if ($$PREBID_GLOBAL$$.logging || $$PREBID_GLOBAL$$.logging === false) { - return $$PREBID_GLOBAL$$.logging; - } - return this._debug; - }, - set debug(val) { - this._debug = val; - }, - - // default timeout for all bids - _bidderTimeout: DEFAULT_BIDDER_TIMEOUT, - get bidderTimeout() { - return $$PREBID_GLOBAL$$.bidderTimeout || this._bidderTimeout; - }, - set bidderTimeout(val) { - this._bidderTimeout = val; - }, - - // domain where prebid is running for cross domain iframe communication - _publisherDomain: DEFAULT_PUBLISHER_DOMAIN, - get publisherDomain() { - return $$PREBID_GLOBAL$$.publisherDomain || this._publisherDomain; - }, - set publisherDomain(val) { - this._publisherDomain = val; - }, - - // delay to request cookie sync to stay out of critical path - _cookieSyncDelay: DEFAULT_COOKIESYNC_DELAY, - get cookieSyncDelay() { - return $$PREBID_GLOBAL$$.cookieSyncDelay || this._cookieSyncDelay; - }, - set cookieSyncDelay(val) { - this._cookieSyncDelay = val; - }, - - // calls existing function which may be moved after deprecation - _priceGranularity: GRANULARITY_OPTIONS.MEDIUM, - set priceGranularity(val) { - if (validatePriceGranularity(val)) { - if (typeof val === 'string') { - this._priceGranularity = (hasGranularity(val)) ? val : GRANULARITY_OPTIONS.MEDIUM; - } else if (typeof val === 'object') { - this._customPriceBucket = val; - this._priceGranularity = GRANULARITY_OPTIONS.CUSTOM; - utils.logMessage('Using custom price granularity'); + let defaults; + let config; + + function resetConfig() { + defaults = {}; + config = { + // `debug` is equivalent to legacy `pbjs.logging` property + _debug: DEFAULT_DEBUG, + get debug() { + return this._debug; + }, + set debug(val) { + this._debug = val; + }, + + // default timeout for all bids + _bidderTimeout: DEFAULT_BIDDER_TIMEOUT, + get bidderTimeout() { + return this._bidderTimeout; + }, + set bidderTimeout(val) { + this._bidderTimeout = val; + }, + + // domain where prebid is running for cross domain iframe communication + _publisherDomain: DEFAULT_PUBLISHER_DOMAIN, + get publisherDomain() { + return this._publisherDomain; + }, + set publisherDomain(val) { + this._publisherDomain = val; + }, + + // delay to request cookie sync to stay out of critical path + _cookieSyncDelay: DEFAULT_COOKIESYNC_DELAY, + get cookieSyncDelay() { + return $$PREBID_GLOBAL$$.cookieSyncDelay || this._cookieSyncDelay; + }, + set cookieSyncDelay(val) { + this._cookieSyncDelay = val; + }, + + // calls existing function which may be moved after deprecation + _priceGranularity: GRANULARITY_OPTIONS.MEDIUM, + set priceGranularity(val) { + if (validatePriceGranularity(val)) { + if (typeof val === 'string') { + this._priceGranularity = (hasGranularity(val)) ? val : GRANULARITY_OPTIONS.MEDIUM; + } else if (typeof val === 'object') { + this._customPriceBucket = val; + this._priceGranularity = GRANULARITY_OPTIONS.CUSTOM; + utils.logMessage('Using custom price granularity'); + } } - } - }, - get priceGranularity() { - return this._priceGranularity; - }, - - _customPriceBucket: {}, - get customPriceBucket() { - return this._customPriceBucket; - }, - - _sendAllBids: DEFAULT_ENABLE_SEND_ALL_BIDS, - get enableSendAllBids() { - return this._sendAllBids; - }, - set enableSendAllBids(val) { - this._sendAllBids = val; - }, - - // calls existing function which may be moved after deprecation - set bidderSequence(val) { - $$PREBID_GLOBAL$$.setBidderSequence(val); - }, - - // calls existing function which may be moved after deprecation - set s2sConfig(val) { - $$PREBID_GLOBAL$$.setS2SConfig(val); - } - }; + }, + get priceGranularity() { + return this._priceGranularity; + }, + + _customPriceBucket: {}, + get customPriceBucket() { + return this._customPriceBucket; + }, + + _sendAllBids: DEFAULT_ENABLE_SEND_ALL_BIDS, + get enableSendAllBids() { + return this._sendAllBids; + }, + set enableSendAllBids(val) { + this._sendAllBids = val; + }, + + _bidderSequence: DEFAULT_BIDDER_SEQUENCE, + get bidderSequence() { + return this._bidderSequence; + }, + set bidderSequence(val) { + if (VALID_ORDERS[val]) { + this._bidderSequence = val; + } else { + utils.logWarn(`Invalid order: ${val}. Bidder Sequence was not set.`); + } + }, - function hasGranularity(val) { - return Object.keys(GRANULARITY_OPTIONS).find(option => val === GRANULARITY_OPTIONS[option]); - } + // timeout buffer to adjust for bidder CDN latency + _timoutBuffer: DEFAULT_TIMEOUTBUFFER, + get timeoutBuffer() { + return this._timoutBuffer; + }, + set timeoutBuffer(val) { + this._timoutBuffer = val; + }, - function validatePriceGranularity(val) { - if (!val) { - utils.logError('Prebid Error: no value passed to `setPriceGranularity()`'); - return false; + }; + + function hasGranularity(val) { + return find(Object.keys(GRANULARITY_OPTIONS), option => val === GRANULARITY_OPTIONS[option]); } - if (typeof val === 'string') { - if (!hasGranularity(val)) { - utils.logWarn('Prebid Warning: setPriceGranularity was called with invalid setting, using `medium` as default.'); - } - } else if (typeof val === 'object') { - if (!isValidPriceConfig(val)) { - utils.logError('Invalid custom price value passed to `setPriceGranularity()`'); + + function validatePriceGranularity(val) { + if (!val) { + utils.logError('Prebid Error: no value passed to `setPriceGranularity()`'); return false; } + if (typeof val === 'string') { + if (!hasGranularity(val)) { + utils.logWarn('Prebid Warning: setPriceGranularity was called with invalid setting, using `medium` as default.'); + } + } else if (typeof val === 'object') { + if (!isValidPriceConfig(val)) { + utils.logError('Invalid custom price value passed to `setPriceGranularity()`'); + return false; + } + } + return true; } - return true; } /* @@ -253,7 +277,7 @@ export function newConfig() { // call subscribers of a specific topic, passing only that configuration listeners - .filter(listener => TOPICS.includes(listener.topic)) + .filter(listener => includes(TOPICS, listener.topic)) .forEach(listener => { listener.callback({ [listener.topic]: options[listener.topic] }); }); @@ -264,10 +288,13 @@ export function newConfig() { .forEach(listener => listener.callback(options)); } + resetConfig(); + return { getConfig, setConfig, - setDefaults + setDefaults, + resetConfig }; } diff --git a/src/constants.json b/src/constants.json index 806b3790c12..3e20d462ac7 100644 --- a/src/constants.json +++ b/src/constants.json @@ -54,10 +54,7 @@ "hb_deal" ], "S2S" : { - "DEFAULT_ENDPOINT" : "https://prebid.adnxs.com/pbs/v1/auction", "SRC" : "s2s", - "ADAPTER" : "prebidServer", - "SYNC_ENDPOINT" : "https://prebid.adnxs.com/pbs/v1/cookie_sync", "SYNCED_BIDDERS_KEY": "pbjsSyncs" } } diff --git a/src/cpmBucketManager.js b/src/cpmBucketManager.js index 5eb66bc1376..0061d35f483 100644 --- a/src/cpmBucketManager.js +++ b/src/cpmBucketManager.js @@ -1,3 +1,4 @@ +import find from 'core-js/library/fn/array/find'; const utils = require('src/utils'); const _defaultPrecision = 2; @@ -86,7 +87,7 @@ function getCpmStringValue(cpm, config, granularityMultiplier) { }, { 'max': 0, }); - let bucket = config.buckets.find(bucket => { + let bucket = find(config.buckets, bucket => { if (cpm > cap.max * granularityMultiplier) { // cpm exceeds cap, just return the cap. let precision = bucket.precision; diff --git a/src/native.js b/src/native.js index 9c591aa539c..bfe4b64405d 100644 --- a/src/native.js +++ b/src/native.js @@ -1,4 +1,5 @@ import { deepAccess, getBidRequest, logError, triggerPixel } from './utils'; +import includes from 'core-js/library/fn/array/includes'; export const nativeAdapters = []; @@ -46,7 +47,7 @@ export function processNativeAdUnitParams(params) { * Check if the native type specified in the adUnit is supported by Prebid. */ function typeIsSupported(type) { - if (!(type && Object.keys(SUPPORTED_TYPES).includes(type))) { + if (!(type && includes(Object.keys(SUPPORTED_TYPES), type))) { logError(`${type} nativeParam is not supported`); return false; } @@ -64,19 +65,20 @@ export const nativeAdUnit = adUnit => { const mediaTypes = deepAccess(adUnit, 'mediaTypes.native'); return mediaType || mediaTypes; } -export const nativeBidder = bid => nativeAdapters.includes(bid.bidder); +export const nativeBidder = bid => includes(nativeAdapters, bid.bidder); export const hasNonNativeBidder = adUnit => adUnit.bids.filter(bid => !nativeBidder(bid)).length; -/* +/** * Validate that the native assets on this bid contain all assets that were * marked as required in the adUnit configuration. + * @param {Bid} bid Native bid to validate + * @param {BidRequest[]} bidRequests All bid requests for an auction + * @return {Boolean} If object is valid */ -export function nativeBidIsValid(bid) { - const bidRequest = getBidRequest(bid.adId); - if (!bidRequest) { - return false; - } +export function nativeBidIsValid(bid, bidRequests) { + const bidRequest = getBidRequest(bid.adId, bidRequests); + if (!bidRequest) { return false; } // all native bid responses must define a landing page url if (!deepAccess(bid, 'native.clickUrl')) { @@ -95,7 +97,7 @@ export function nativeBidIsValid(bid) { key => bid['native'][key] ); - return requiredAssets.every(asset => returnedAssets.includes(asset)); + return requiredAssets.every(asset => includes(returnedAssets, asset)); } /* diff --git a/src/polyfill.js b/src/polyfill.js deleted file mode 100644 index 1c8913824ae..00000000000 --- a/src/polyfill.js +++ /dev/null @@ -1,14 +0,0 @@ -/** @module polyfill -Misc polyfills -*/ -require('core-js/fn/array/find'); -require('core-js/fn/array/find-index'); -require('core-js/fn/array/includes'); -require('core-js/fn/object/assign'); - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger -Number.isInteger = Number.isInteger || function(value) { - return typeof value === 'number' && - isFinite(value) && - Math.floor(value) === value; -}; diff --git a/src/prebid.js b/src/prebid.js index 2b61a839b5e..ffecabe05eb 100644 --- a/src/prebid.js +++ b/src/prebid.js @@ -4,65 +4,40 @@ import { getGlobal } from './prebidGlobal'; import { flatten, uniques, isGptPubadsDefined, adUnitsFilter } from './utils'; import { videoAdUnit, videoBidder, hasNonVideoBidder } from './video'; import { nativeAdUnit, nativeBidder, hasNonNativeBidder } from './native'; -import './polyfill'; -import { parse as parseURL, format as formatURL } from './url'; import { listenMessagesFromCreative } from './secureCreatives'; import { userSync } from 'src/userSync.js'; import { loadScript } from './adloader'; -import { setAjaxTimeout } from './ajax'; import { config } from './config'; +import { auctionManager } from './auctionManager'; +import { targeting } from './targeting'; +import includes from 'core-js/library/fn/array/includes'; var $$PREBID_GLOBAL$$ = getGlobal(); var CONSTANTS = require('./constants.json'); var utils = require('./utils.js'); -var bidmanager = require('./bidmanager.js'); var adaptermanager = require('./adaptermanager'); var bidfactory = require('./bidfactory'); var events = require('./events'); -var adserver = require('./adserver.js'); -var targeting = require('./targeting.js'); -const { syncUsers, triggerUserSyncs } = userSync; +const { triggerUserSyncs } = userSync; /* private variables */ +const RENDERED = 'rendered'; var BID_WON = CONSTANTS.EVENTS.BID_WON; var SET_TARGETING = CONSTANTS.EVENTS.SET_TARGETING; var ADD_AD_UNITS = CONSTANTS.EVENTS.ADD_AD_UNITS; -var auctionRunning = false; -var bidRequestQueue = []; - var eventValidators = { bidWon: checkDefinedPlacement }; /* Public vars */ - -$$PREBID_GLOBAL$$._bidsRequested = []; -$$PREBID_GLOBAL$$._bidsReceived = []; -// _adUnitCodes stores the current filter to use for adUnits as an array of adUnitCodes -$$PREBID_GLOBAL$$._adUnitCodes = []; -$$PREBID_GLOBAL$$._winningBids = []; -$$PREBID_GLOBAL$$._adsReceived = []; - $$PREBID_GLOBAL$$.bidderSettings = $$PREBID_GLOBAL$$.bidderSettings || {}; -/** @deprecated - use pbjs.setConfig({ bidderTimeout: }) */ -$$PREBID_GLOBAL$$.bidderTimeout = $$PREBID_GLOBAL$$.bidderTimeout; - // current timeout set in `requestBids` or to default `bidderTimeout` $$PREBID_GLOBAL$$.cbTimeout = $$PREBID_GLOBAL$$.cbTimeout || 200; -// timeout buffer to adjust for bidder CDN latency -$$PREBID_GLOBAL$$.timeoutBuffer = 200; - -/** @deprecated - use pbjs.setConfig({ debug: }) */ -$$PREBID_GLOBAL$$.logging = $$PREBID_GLOBAL$$.logging; - -/** @deprecated - use pbjs.setConfig({ publisherDomain: ) */ -$$PREBID_GLOBAL$$.publisherDomain = $$PREBID_GLOBAL$$.publisherDomain; - // let the world know we are loaded $$PREBID_GLOBAL$$.libLoaded = true; @@ -77,11 +52,11 @@ $$PREBID_GLOBAL$$.adUnits = $$PREBID_GLOBAL$$.adUnits || []; $$PREBID_GLOBAL$$.triggerUserSyncs = triggerUserSyncs; function checkDefinedPlacement(id) { - var placementCodes = $$PREBID_GLOBAL$$._bidsRequested.map(bidSet => bidSet.bids.map(bid => bid.placementCode)) + var adUnitCodes = auctionManager.getBidsRequested().map(bidSet => bidSet.bids.map(bid => bid.adUnitCode)) .reduce(flatten) .filter(uniques); - if (!utils.contains(placementCodes, id)) { + if (!utils.contains(adUnitCodes, id)) { utils.logError('The "' + id + '" placement is not defined.'); return; } @@ -89,18 +64,6 @@ function checkDefinedPlacement(id) { return true; } -/** - * When a request for bids is made any stale bids remaining will be cleared for - * a placement included in the outgoing bid request. - */ -function clearPlacements() { - $$PREBID_GLOBAL$$._bidsRequested = []; - - // leave bids received for ad slots not in this bid request - $$PREBID_GLOBAL$$._bidsReceived = $$PREBID_GLOBAL$$._bidsReceived - .filter(bid => !$$PREBID_GLOBAL$$._adUnitCodes.includes(bid.adUnitCode)); -} - function setRenderSize(doc, width, height) { if (doc.defaultView && doc.defaultView.frameElement) { doc.defaultView.frameElement.width = width; @@ -150,22 +113,7 @@ $$PREBID_GLOBAL$$.getAdserverTargetingForAdUnitCode = function(adUnitCode) { $$PREBID_GLOBAL$$.getAdserverTargeting = function (adUnitCode) { utils.logInfo('Invoking $$PREBID_GLOBAL$$.getAdserverTargeting', arguments); - return targeting.getAllTargeting(adUnitCode) - .map(targeting => { - return { - [Object.keys(targeting)[0]]: targeting[Object.keys(targeting)[0]] - .map(target => { - return { - [Object.keys(target)[0]]: target[Object.keys(target)[0]].join(', ') - }; - }).reduce((p, c) => Object.assign(c, p), {}) - }; - }) - .reduce(function (accumulator, targeting) { - var key = Object.keys(targeting)[0]; - accumulator[key] = Object.assign({}, accumulator[key], targeting[key]); - return accumulator; - }, {}); + return targeting.getAllTargeting(adUnitCode); }; /** @@ -176,8 +124,8 @@ $$PREBID_GLOBAL$$.getAdserverTargeting = function (adUnitCode) { $$PREBID_GLOBAL$$.getBidResponses = function () { utils.logInfo('Invoking $$PREBID_GLOBAL$$.getBidResponses', arguments); - const responses = $$PREBID_GLOBAL$$._bidsReceived - .filter(adUnitsFilter.bind(this, $$PREBID_GLOBAL$$._adUnitCodes)); + const responses = auctionManager.getBidsReceived() + .filter(adUnitsFilter.bind(this, auctionManager.getAdUnitCodes())); // find the last requested id to get responses for most recent auction only const currentRequestId = responses && responses.length && responses[responses.length - 1].requestId; @@ -202,7 +150,7 @@ $$PREBID_GLOBAL$$.getBidResponses = function () { */ $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode = function (adUnitCode) { - const bids = $$PREBID_GLOBAL$$._bidsReceived.filter(bid => bid.adUnitCode === adUnitCode); + const bids = auctionManager.getBidsReceived().filter(bid => bid.adUnitCode === adUnitCode); return { bids: bids }; @@ -227,7 +175,7 @@ $$PREBID_GLOBAL$$.setTargetingForGPTAsync = function (adUnit) { targeting.resetPresetTargeting(adUnit); // now set new targeting keys - targeting.setTargeting(targetingSet); + targeting.setTargetingForGPT(targetingSet); // emit event events.emit(SET_TARGETING); @@ -250,21 +198,6 @@ $$PREBID_GLOBAL$$.setTargetingForAst = function() { events.emit(SET_TARGETING); }; -/** - * Returns a bool if all the bids have returned or timed out - * @alias module:pbjs.allBidsAvailable - * @return {bool} all bids available - * - * @deprecated This function will be removed in Prebid 1.0 - * Alternative solution is in progress. - * See https://github.com/prebid/Prebid.js/issues/1087 for more details. - */ -$$PREBID_GLOBAL$$.allBidsAvailable = function () { - utils.logWarn('$$PREBID_GLOBAL$$.allBidsAvailable will be removed in Prebid 1.0. Alternative solution is in progress. See https://github.com/prebid/Prebid.js/issues/1087 for more details.'); - utils.logInfo('Invoking $$PREBID_GLOBAL$$.allBidsAvailable', arguments); - return bidmanager.bidsBackAll(); -}; - /** * This function will render the ad (based on params) in the given iframe document passed through. * Note that doc SHOULD NOT be the parent document page as we can't doc.write() asynchronously @@ -278,13 +211,14 @@ $$PREBID_GLOBAL$$.renderAd = function (doc, id) { if (doc && id) { try { // lookup ad by ad Id - const bid = $$PREBID_GLOBAL$$._bidsReceived.find(bid => bid.adId === id); + const bid = auctionManager.findBidByAdId(id); if (bid) { + bid.status = RENDERED; // replace macros according to openRTB with price paid = bid.cpm bid.ad = utils.replaceAuctionPrice(bid.ad, bid.cpm); bid.adUrl = utils.replaceAuctionPrice(bid.adUrl, bid.cpm); // save winning bids - $$PREBID_GLOBAL$$._winningBids.push(bid); + auctionManager.addWinningBid(bid); // emit 'bid won' event here events.emit(BID_WON, bid); @@ -339,42 +273,25 @@ $$PREBID_GLOBAL$$.removeAdUnit = function (adUnitCode) { } }; -/** - * @alias module:pbjs.clearAuction - */ -$$PREBID_GLOBAL$$.clearAuction = function() { - auctionRunning = false; - // Only automatically sync if the publisher has not chosen to "enableOverride" - let userSyncConfig = config.getConfig('userSync') || {}; - if (!userSyncConfig.enableOverride) { - // Delay the auto sync by the config delay - syncUsers(userSyncConfig.syncDelay); - } - - utils.logMessage('Prebid auction cleared'); - if (bidRequestQueue.length) { - bidRequestQueue.shift()(); - } -}; - /** * @param {Object} requestOptions * @param {function} requestOptions.bidsBackHandler * @param {number} requestOptions.timeout * @param {Array} requestOptions.adUnits * @param {Array} requestOptions.adUnitCodes + * @param {Array} requestOptions.labels * @alias module:pbjs.requestBids */ -$$PREBID_GLOBAL$$.requestBids = function ({ bidsBackHandler, timeout, adUnits, adUnitCodes } = {}) { +$$PREBID_GLOBAL$$.requestBids = function ({ bidsBackHandler, timeout, adUnits, adUnitCodes, labels } = {}) { events.emit('requestBids'); - const cbTimeout = $$PREBID_GLOBAL$$.cbTimeout = timeout || config.getConfig('bidderTimeout'); + const cbTimeout = timeout || config.getConfig('bidderTimeout'); adUnits = adUnits || $$PREBID_GLOBAL$$.adUnits; utils.logInfo('Invoking $$PREBID_GLOBAL$$.requestBids', arguments); if (adUnitCodes && adUnitCodes.length) { // if specific adUnitCodes supplied filter adUnits for those codes - adUnits = adUnits.filter(unit => adUnitCodes.includes(unit.code)); + adUnits = adUnits.filter(unit => includes(adUnitCodes, unit.code)); } else { // otherwise derive adUnitCodes from adUnits adUnitCodes = adUnits && adUnits.map(unit => unit.code); @@ -400,43 +317,21 @@ $$PREBID_GLOBAL$$.requestBids = function ({ bidsBackHandler, timeout, adUnits, a adUnit.bids = adUnit.bids.filter(nativeBidder); }); - if (auctionRunning) { - bidRequestQueue.push(() => { - $$PREBID_GLOBAL$$.requestBids({ bidsBackHandler, timeout: cbTimeout, adUnits, adUnitCodes }); - }); - return; - } - - auctionRunning = true; - - // we will use adUnitCodes for filtering the current auction - $$PREBID_GLOBAL$$._adUnitCodes = adUnitCodes; - - bidmanager.externalCallbackReset(); - clearPlacements(); - if (!adUnits || adUnits.length === 0) { utils.logMessage('No adUnits configured. No bids requested.'); if (typeof bidsBackHandler === 'function') { - bidmanager.addOneTimeCallback(bidsBackHandler, false); + // executeCallback, this will only be called in case of first request + try { + bidsBackHandler(); + } catch (e) { + utils.logError('Error executing bidsBackHandler', null, e); + } } - bidmanager.executeCallback(); return; } - // set timeout for all bids - const timedOut = true; - const timeoutCallback = bidmanager.executeCallback.bind(bidmanager, timedOut); - const timer = setTimeout(timeoutCallback, cbTimeout); - setAjaxTimeout(cbTimeout); - if (typeof bidsBackHandler === 'function') { - bidmanager.addOneTimeCallback(bidsBackHandler, timer); - } - - adaptermanager.callBids({ adUnits, adUnitCodes, cbTimeout }); - if ($$PREBID_GLOBAL$$._bidsRequested.length === 0) { - bidmanager.executeCallback(); - } + const auction = auctionManager.createAuction({adUnits, adUnitCodes, callback: bidsBackHandler, cbTimeout, labels}); + auction.callBids(); }; /** @@ -507,46 +402,7 @@ $$PREBID_GLOBAL$$.offEvent = function (event, handler, id) { events.off(event, handler, id); }; -/** - * Add a callback event - * @param {string} eventStr event to attach callback to Options: "allRequestedBidsBack" | "adUnitBidsBack" - * @param {Function} func function to execute. Parameters passed into the function: (bidResObj), [adUnitCode]); - * @alias module:pbjs.addCallback - * @returns {string} id for callback - * - * @deprecated This function will be removed in Prebid 1.0 - * Please use onEvent instead. - */ -$$PREBID_GLOBAL$$.addCallback = function (eventStr, func) { - utils.logWarn('$$PREBID_GLOBAL$$.addCallback will be removed in Prebid 1.0. Please use onEvent instead'); - utils.logInfo('Invoking $$PREBID_GLOBAL$$.addCallback', arguments); - var id = null; - if (!eventStr || !func || typeof func !== 'function') { - utils.logError('error registering callback. Check method signature'); - return id; - } - - id = utils.getUniqueIdentifierStr; - bidmanager.addCallback(id, func, eventStr); - return id; -}; - -/** - * Remove a callback event - * //@param {string} cbId id of the callback to remove - * @alias module:pbjs.removeCallback - * @returns {string} id for callback - * - * @deprecated This function will be removed in Prebid 1.0 - * Please use offEvent instead. - */ -$$PREBID_GLOBAL$$.removeCallback = function (/* cbId */) { - // todo - utils.logWarn('$$PREBID_GLOBAL$$.removeCallback will be removed in Prebid 1.0. Please use offEvent instead.'); - return null; -}; - -/** +/* * Wrapper to register bidderAdapter externally (adaptermanager.registerBidAdapter()) * @param {Function} bidderAdaptor [description] * @param {string} bidderCode [description] @@ -575,22 +431,6 @@ $$PREBID_GLOBAL$$.registerAnalyticsAdapter = function (options) { } }; -/** - * @alias module:pbjs.bidsAvailableForAdapter -*/ -$$PREBID_GLOBAL$$.bidsAvailableForAdapter = function (bidderCode) { - utils.logInfo('Invoking $$PREBID_GLOBAL$$.bidsAvailableForAdapter', arguments); - - $$PREBID_GLOBAL$$._bidsRequested.find(bidderRequest => bidderRequest.bidderCode === bidderCode).bids - .map(bid => { - return Object.assign(bid, bidfactory.createBid(1), { - bidderCode, - adUnitCode: bid.placementCode - }); - }) - .map(bid => $$PREBID_GLOBAL$$._bidsReceived.push(bid)); -}; - /** * Wrapper to bidfactory.createBid() * @param {string} statusCode [description] @@ -602,21 +442,6 @@ $$PREBID_GLOBAL$$.createBid = function (statusCode) { return bidfactory.createBid(statusCode); }; -/** - * Wrapper to bidmanager.addBidResponse - * @param {string} adUnitCode [description] - * @param {Object} bid [description] - * @alias module:pbjs.addBidResponse - * @deprecated This function will be removed in Prebid 1.0 - * Each bidder will be passed a reference to addBidResponse function in callBids as an argument. - * See https://github.com/prebid/Prebid.js/issues/1087 for more details. - */ -$$PREBID_GLOBAL$$.addBidResponse = function (adUnitCode, bid) { - utils.logWarn('$$PREBID_GLOBAL$$.addBidResponse will be removed in Prebid 1.0. Each bidder will be passed a reference to addBidResponse function in callBids as an argument. See https://github.com/prebid/Prebid.js/issues/1087 for more details.'); - utils.logInfo('Invoking $$PREBID_GLOBAL$$.addBidResponse', arguments); - bidmanager.addBidResponse(adUnitCode, bid); -}; - /** * Wrapper to adloader.loadScript * @param {string} tagSrc [description] @@ -664,36 +489,6 @@ $$PREBID_GLOBAL$$.aliasBidder = function (bidderCode, alias) { }; /** - * Sets a default price granularity scheme. - * @param {string|Object} granularity - the granularity scheme. - * @alias module:pbjs.setPriceGranularity - * @deprecated - use pbjs.setConfig({ priceGranularity: }) - * "low": $0.50 increments, capped at $5 CPM - * "medium": $0.10 increments, capped at $20 CPM (the default) - * "high": $0.01 increments, capped at $20 CPM - * "auto": Applies a sliding scale to determine granularity - * "dense": Like "auto", but the bid price granularity uses smaller increments, especially at lower CPMs - * - * Alternatively a custom object can be specified: - * { "buckets" : [{"min" : 0,"max" : 20,"increment" : 0.1,"cap" : true}]}; - * See http://prebid.org/dev-docs/publisher-api-reference.html#module_pbjs.setPriceGranularity for more details - */ -$$PREBID_GLOBAL$$.setPriceGranularity = function (granularity) { - utils.logWarn('$$PREBID_GLOBAL$$.setPriceGranularity will be removed in Prebid 1.0. Use $$PREBID_GLOBAL$$.setConfig({ priceGranularity: }) instead.') - utils.logInfo('Invoking $$PREBID_GLOBAL$$.setPriceGranularity', arguments); - config.setConfig({ priceGranularity: granularity }); -}; - -/** - * @alias module:pbjs.enableSendAllBids - * @deprecated - use pbjs.setConfig({ enableSendAllBids: }) -*/ -$$PREBID_GLOBAL$$.enableSendAllBids = function () { - config.setConfig({ enableSendAllBids: true }); -}; - -/** - * @alias module:pbjs.getAllWinningBids * The bid response object returned by an external bidder adapter during the auction. * @typedef {Object} AdapterBidResponse * @property {string} pbAg Auto granularity price bucket; CPM <= 5 ? increment = 0.05 : CPM > 5 && CPM <= 10 ? increment = 0.10 : CPM > 10 && CPM <= 20 ? increment = 0.50 : CPM > 20 ? priceCap = 20.00. Example: `"0.80"`. @@ -733,56 +528,9 @@ $$PREBID_GLOBAL$$.enableSendAllBids = function () { * @return {Array} A list of bids that have won their respective auctions. */ $$PREBID_GLOBAL$$.getAllWinningBids = function () { - return $$PREBID_GLOBAL$$._winningBids; -}; - -/** - * Build master video tag from publishers adserver tag - * @param {string} adserverTag default url - * @param {Object} options options for video tag - * @alias module:pbjs.buildMasterVideoTagFromAdserverTag - * @deprecated Include the dfpVideoSupport module in your build, and use the $$PREBID_GLOBAL$$.adservers.dfp.buildVideoAdUrl function instead. - * This function will be removed in Prebid 1.0. - */ -$$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag = function (adserverTag, options) { - utils.logWarn('$$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag will be removed in Prebid 1.0. Include the dfpVideoSupport module in your build, and use the $$PREBID_GLOBAL$$.adservers.dfp.buildVideoAdUrl function instead'); - utils.logInfo('Invoking $$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag', arguments); - var urlComponents = parseURL(adserverTag); - - // return original adserverTag if no bids received - if ($$PREBID_GLOBAL$$._bidsReceived.length === 0) { - return adserverTag; - } - - var masterTag = ''; - if (options.adserver.toLowerCase() === 'dfp') { - var dfpAdserverObj = adserver.dfpAdserver(options, urlComponents); - if (!dfpAdserverObj.verifyAdserverTag()) { - utils.logError('Invalid adserverTag, required google params are missing in query string'); - } - dfpAdserverObj.appendQueryParams(); - masterTag = formatURL(dfpAdserverObj.urlComponents); - } else { - utils.logError('Only DFP adserver is supported'); - return; - } - return masterTag; + return auctionManager.getAllWinningBids(); }; -/** - * Set the order bidders are called in. Valid values are: - * - * "fixed": Bidders will be called in the order in which they were defined within the adUnit.bids array. - * "random": Bidders will be called in random order. - * - * If never called, Prebid will use "random" as the default. - * - * @param {string} order One of the valid orders, described above. - * @alias module:pbjs.setBidderSequence - * @deprecated - use pbjs.setConfig({ bidderSequence: }) - */ -$$PREBID_GLOBAL$$.setBidderSequence = adaptermanager.setBidderSequence; - /** * Get array of highest cpm bids for all adUnits, or highest cpm bid * object for the given adUnit @@ -794,44 +542,6 @@ $$PREBID_GLOBAL$$.getHighestCpmBids = function (adUnitCode) { return targeting.getWinningBids(adUnitCode); }; -/** - * Set config for server to server header bidding - * @deprecated - use pbjs.setConfig({ s2sConfig: }) - * @typedef {Object} options - required - * @property {boolean} enabled enables S2S bidding - * @property {string[]} bidders bidders to request S2S - * === optional params below === - * @property {string} [endpoint] endpoint to contact - * @property {number} [timeout] timeout for S2S bidders - should be lower than `pbjs.requestBids({timeout})` - * @property {string} [adapter] adapter code to use for S2S - * @property {string} [syncEndpoint] endpoint URL for syncing cookies - * @property {boolean} [cookieSet] enables cookieSet functionality - * @alias module:pbjs.setS2SConfig - */ -$$PREBID_GLOBAL$$.setS2SConfig = function(options) { - if (!utils.contains(Object.keys(options), 'accountId')) { - utils.logError('accountId missing in Server to Server config'); - return; - } - - if (!utils.contains(Object.keys(options), 'bidders')) { - utils.logError('bidders missing in Server to Server config'); - return; - } - - const config = Object.assign({ - enabled: false, - endpoint: CONSTANTS.S2S.DEFAULT_ENDPOINT, - timeout: 1000, - maxBids: 1, - adapter: CONSTANTS.S2S.ADAPTER, - syncEndpoint: CONSTANTS.S2S.SYNC_ENDPOINT, - cookieSet: true, - bidders: [] - }, options); - adaptermanager.setS2SConfig(config); -}; - /** * Get Prebid config options * @param {Object} options diff --git a/src/secureCreatives.js b/src/secureCreatives.js index efc1386fde3..424d1402831 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -6,6 +6,9 @@ import events from './events'; import { fireNativeTrackers } from './native'; import { EVENTS } from './constants'; +import { isSlotMatchingAdUnitCode } from './utils'; +import { auctionManager } from './auctionManager'; +import find from 'core-js/library/fn/array/find'; const BID_WON = EVENTS.BID_WON; @@ -23,7 +26,7 @@ function receiveMessage(ev) { } if (data.adId) { - const adObject = $$PREBID_GLOBAL$$._bidsReceived.find(function (bid) { + const adObject = find(auctionManager.getBidsReceived(), function (bid) { return bid.adId === data.adId; }); @@ -31,7 +34,7 @@ function receiveMessage(ev) { sendAdToCreative(adObject, data.adServerDomain, ev.source); // save winning bids - $$PREBID_GLOBAL$$._winningBids.push(adObject); + auctionManager.addWinningBid(adObject); events.emit(BID_WON, adObject); } @@ -43,7 +46,7 @@ function receiveMessage(ev) { // }), '*'); if (data.message === 'Prebid Native') { fireNativeTrackers(data, adObject); - $$PREBID_GLOBAL$$._winningBids.push(adObject); + auctionManager.addWinningBid(adObject); events.emit(BID_WON, adObject); } } @@ -66,11 +69,9 @@ function sendAdToCreative(adObject, remoteDomain, source) { } function resizeRemoteCreative({ adUnitCode, width, height }) { - const iframe = document.getElementById(window.googletag.pubads() - .getSlots().find(slot => { - return slot.getAdUnitPath() === adUnitCode || - slot.getSlotElementId() === adUnitCode; - }).getSlotElementId()).querySelector('iframe'); + const iframe = document.getElementById( + find(window.googletag.pubads().getSlots().filter(isSlotMatchingAdUnitCode(adUnitCode)), slot => slot) + .getSlotElementId()).querySelector('iframe'); iframe.width = '' + width; iframe.height = '' + height; diff --git a/src/sizeMapping.js b/src/sizeMapping.js index 9529c567308..4a4c9ff77c1 100644 --- a/src/sizeMapping.js +++ b/src/sizeMapping.js @@ -1,61 +1,85 @@ +import { config } from 'src/config'; +import includes from 'core-js/library/fn/array/includes'; + +let sizeConfig = []; + /** - * @module sizeMapping + * @typedef {object} SizeConfig + * + * @property {string} [mediaQuery] A CSS media query string that will to be interpreted by window.matchMedia. If the + * media query matches then the this config will be active and sizesSupported will filter bid and adUnit sizes. If + * this property is not present then this SizeConfig will only be active if triggered manually by a call to + * pbjs.setConfig({labels:['label']) specifying one of the labels present on this SizeConfig. + * @property {Array} sizesSupported The sizes to be accepted if this SizeConfig is enabled. + * @property {Array} labels The active labels to match this SizeConfig to an adUnits and/or bidders. */ -import * as utils from './utils'; -let _win; - -function mapSizes(adUnit) { - if (!isSizeMappingValid(adUnit.sizeMapping)) { - return adUnit.sizes; - } - const width = getScreenWidth(); - if (!width) { - // size not detected - get largest value set for desktop - const mapping = adUnit.sizeMapping.reduce((prev, curr) => { - return prev.minWidth < curr.minWidth ? curr : prev; - }); - if (mapping.sizes && mapping.sizes.length) { - return mapping.sizes; - } - return adUnit.sizes; - } - let sizes = ''; - const mapping = adUnit.sizeMapping.find(sizeMapping => { - return width >= sizeMapping.minWidth; - }); - if (mapping && mapping.sizes && mapping.sizes.length) { - sizes = mapping.sizes; - utils.logMessage(`AdUnit : ${adUnit.code} resized based on device width to : ${sizes}`); - } else { - utils.logMessage(`AdUnit : ${adUnit.code} not mapped to any sizes for device width. This request will be suppressed.`); - } - return sizes; -} -function isSizeMappingValid(sizeMapping) { - if (utils.isArray(sizeMapping) && sizeMapping.length > 0) { - return true; - } - utils.logInfo('No size mapping defined'); - return false; +/** + * + * @param {Array} config + */ +export function setSizeConfig(config) { + sizeConfig = config; } +config.getConfig('sizeConfig', config => setSizeConfig(config.sizeConfig)); -function getScreenWidth(win) { - var w = win || _win || window; - var d = w.document; +/** + * Resolves the unique set of the union of all sizes and labels that are active from a SizeConfig.mediaQuery match + * @param {Array} labels Labels specified on adUnit or bidder + * @param {boolean} labelAll if true, all labels must match to be enabled + * @param {Array} activeLabels Labels passed in through requestBids + * @param {Array>} sizes Sizes specified on adUnit + * @param {Array} configs + * @returns {{labels: Array, sizes: Array>}} + */ +export function resolveStatus({labels = [], labelAll = false, activeLabels = []} = {}, sizes = [], configs = sizeConfig) { + let maps = evaluateSizeConfig(configs); - if (w.innerWidth) { - return w.innerWidth; - } else if (d.body.clientWidth) { - return d.body.clientWidth; - } else if (d.documentElement.clientWidth) { - return d.documentElement.clientWidth; + let filteredSizes; + if (maps.shouldFilter) { + filteredSizes = sizes.filter(size => maps.sizesSupported[size]); + } else { + filteredSizes = sizes; } - return 0; -} -function setWindow(win) { - _win = win; + return { + active: filteredSizes.length > 0 && ( + labels.length === 0 || ( + (!labelAll && ( + labels.some(label => maps.labels[label]) || + labels.some(label => includes(activeLabels, label)) + )) || + (labelAll && ( + labels.reduce((result, label) => !result ? result : ( + maps.labels[label] || includes(activeLabels, label) + ), true) + )) + ) + ), + sizes: filteredSizes + }; } -export { mapSizes, getScreenWidth, setWindow }; +function evaluateSizeConfig(configs) { + return configs.reduce((results, config) => { + if ( + typeof config === 'object' && + typeof config.mediaQuery === 'string' && + matchMedia(config.mediaQuery).matches + ) { + if (Array.isArray(config.sizesSupported)) { + results.shouldFilter = true; + } + ['labels', 'sizesSupported'].forEach( + type => (config[type] || []).forEach( + thing => results[type][thing] = true + ) + ); + } + return results; + }, { + labels: {}, + sizesSupported: {}, + shouldFilter: false + }); +} diff --git a/src/targeting.js b/src/targeting.js index 3081100c8e4..2169af21b2b 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -1,210 +1,366 @@ -import { uniques, isGptPubadsDefined, getHighestCpm, adUnitsFilter, groupBy } from './utils'; +import { uniques, isGptPubadsDefined, getHighestCpm, groupBy, isAdUnitCodeMatchingSlot, timestamp } from './utils'; import { config } from './config'; import { NATIVE_TARGETING_KEYS } from './native'; -const bidmanager = require('./bidmanager'); -const utils = require('./utils'); -var CONSTANTS = require('./constants'); +import { auctionManager } from './auctionManager'; +import includes from 'core-js/library/fn/array/includes'; + +const utils = require('./utils.js'); +var CONSTANTS = require('./constants.json'); -var targeting = exports; var pbTargetingKeys = []; -targeting.resetPresetTargeting = function(adUnitCode) { - if (isGptPubadsDefined()) { +export const BID_TARGETING_SET = 'targetingSet'; + +const MAX_DFP_KEYLENGTH = 20; + +// return unexpired bids +export const isBidExpired = (bid) => (timestamp() - bid.responseTimestamp) < bid.ttl * 1000; + +// return bids whose status is not set. Winning bid can have status `targetingSet` or `rendered`. +const isUnusedBid = (bid) => bid && ((bid.status && bid.status === BID_TARGETING_SET) || !bid.status); + +/** + * @typedef {Object.} targeting + * @property {string} targeting_key + */ + +/** + * @typedef {Object.[]>[]} targetingArray + */ + +export function newTargeting(auctionManager) { + let targeting = {}; + + targeting.resetPresetTargeting = function(adUnitCode) { + if (isGptPubadsDefined()) { + const adUnitCodes = getAdUnitCodes(adUnitCode); + const adUnits = auctionManager.getAdUnits().filter(adUnit => includes(adUnitCodes, adUnit.code)); + window.googletag.pubads().getSlots().forEach(slot => { + pbTargetingKeys.forEach(function(key) { + // reset only registered adunits + adUnits.forEach(function(unit) { + if (unit.code === slot.getAdUnitPath() || + unit.code === slot.getSlotElementId()) { + slot.setTargeting(key, null); + } + }); + }); + }); + } + }; + + /** + * Returns all ad server targeting for all ad units. + * @param {string=} adUnitCode + * @return {Object.} targeting + */ + targeting.getAllTargeting = function(adUnitCode) { const adUnitCodes = getAdUnitCodes(adUnitCode); - const adUnits = $$PREBID_GLOBAL$$.adUnits.filter(adUnit => adUnitCodes.includes(adUnit.code)); - window.googletag.pubads().getSlots().forEach(slot => { - pbTargetingKeys.forEach(function(key) { - // reset only registered adunits - adUnits.forEach(function(unit) { - if (unit.code === slot.getAdUnitPath() || - unit.code === slot.getSlotElementId()) { - slot.setTargeting(key, null); + + // Get targeting for the winning bid. Add targeting for any bids that have + // `alwaysUseBid=true`. If sending all bids is enabled, add targeting for losing bids. + var targeting = getWinningBidTargeting(adUnitCodes) + .concat(getCustomBidTargeting(adUnitCodes)) + .concat(config.getConfig('enableSendAllBids') ? getBidLandscapeTargeting(adUnitCodes) : []); + + // store a reference of the targeting keys + targeting.map(adUnitCode => { + Object.keys(adUnitCode).map(key => { + adUnitCode[key].map(targetKey => { + if (pbTargetingKeys.indexOf(Object.keys(targetKey)[0]) === -1) { + pbTargetingKeys = Object.keys(targetKey).concat(pbTargetingKeys); } }); }); }); + + targeting = flattenTargeting(targeting); + return targeting; + }; + + /** + * Converts targeting array and flattens to make it easily iteratable + * e.g: Sample input to this function + * ``` + * [ + * { + * "div-gpt-ad-1460505748561-0": [{"hb_bidder": ["appnexusAst"]}] + * }, + * { + * "div-gpt-ad-1460505748561-0": [{"hb_bidder_appnexusAs": ["appnexusAst"]}] + * } + * ] + * ``` + * Resulting array + * ``` + * { + * "div-gpt-ad-1460505748561-0": { + * "hb_bidder": "appnexusAst", + * "hb_bidder_appnexusAs": "appnexusAst" + * } + * } + * ``` + * + * @param {targetingArray} targeting + * @return {Object.} targeting + */ + function flattenTargeting(targeting) { + let targetingObj = targeting.map(targeting => { + return { + [Object.keys(targeting)[0]]: targeting[Object.keys(targeting)[0]] + .map(target => { + return { + [Object.keys(target)[0]]: target[Object.keys(target)[0]].join(', ') + }; + }).reduce((p, c) => Object.assign(c, p), {}) + }; + }).reduce(function (accumulator, targeting) { + var key = Object.keys(targeting)[0]; + accumulator[key] = Object.assign({}, accumulator[key], targeting[key]); + return accumulator; + }, {}); + return targetingObj; } -}; - -targeting.getAllTargeting = function(adUnitCode) { - const adUnitCodes = getAdUnitCodes(adUnitCode); - - // Get targeting for the winning bid. Add targeting for any bids that have - // `alwaysUseBid=true`. If sending all bids is enabled, add targeting for losing bids. - var targeting = getWinningBidTargeting(adUnitCodes) - .concat(getAlwaysUseBidTargeting(adUnitCodes)) - .concat(config.getConfig('enableSendAllBids') ? getBidLandscapeTargeting(adUnitCodes) : []); - - // store a reference of the targeting keys - targeting.map(adUnitCode => { - Object.keys(adUnitCode).map(key => { - adUnitCode[key].map(targetKey => { - if (pbTargetingKeys.indexOf(Object.keys(targetKey)[0]) === -1) { - pbTargetingKeys = Object.keys(targetKey).concat(pbTargetingKeys); - } - }); - }); - }); - return targeting; -}; - -targeting.setTargeting = function(targetingConfig) { - window.googletag.pubads().getSlots().forEach(slot => { - targetingConfig.filter(targeting => Object.keys(targeting)[0] === slot.getAdUnitPath() || - Object.keys(targeting)[0] === slot.getSlotElementId()) - .forEach(targeting => targeting[Object.keys(targeting)[0]] - .forEach(key => { - key[Object.keys(key)[0]] - .map((value) => { - utils.logMessage(`Attempting to set key value for slot: ${slot.getSlotElementId()} key: ${Object.keys(key)[0]} value: ${value}`); + + /** + * Sets targeting for DFP + * @param {Object.>} targetingConfig + */ + targeting.setTargetingForGPT = function(targetingConfig) { + window.googletag.pubads().getSlots().forEach(slot => { + Object.keys(targetingConfig).filter(isAdUnitCodeMatchingSlot(slot)) + .forEach(targetId => + Object.keys(targetingConfig[targetId]).forEach(key => { + let valueArr = targetingConfig[targetId][key].split(','); + valueArr = (valueArr.length > 1) ? [valueArr] : valueArr; + valueArr.map((value) => { + utils.logMessage(`Attempting to set key value for slot: ${slot.getSlotElementId()} key: ${key} value: ${value}`); return value; - }) - .forEach(value => { - slot.setTargeting(Object.keys(key)[0], value); + }).forEach(value => { + slot.setTargeting(key, value); }); - })); - }); -}; + }) + ) + }) + }; -/** - * normlizes input to a `adUnit.code` array - * @param {(string|string[])} adUnitCode [description] - * @return {string[]} AdUnit code array - */ -function getAdUnitCodes(adUnitCode) { - if (typeof adUnitCode === 'string') { - return [adUnitCode]; - } else if (utils.isArray(adUnitCode)) { - return adUnitCode; + /** + * normlizes input to a `adUnit.code` array + * @param {(string|string[])} adUnitCode [description] + * @return {string[]} AdUnit code array + */ + function getAdUnitCodes(adUnitCode) { + if (typeof adUnitCode === 'string') { + return [adUnitCode]; + } else if (utils.isArray(adUnitCode)) { + return adUnitCode; + } + return auctionManager.getAdUnitCodes() || []; } - return $$PREBID_GLOBAL$$._adUnitCodes || []; -} -/** - * Returns top bids for a given adUnit or set of adUnits. - * @param {(string|string[])} adUnitCode adUnitCode or array of adUnitCodes - * @return {[type]} [description] - */ -targeting.getWinningBids = function(adUnitCode) { - const adUnitCodes = getAdUnitCodes(adUnitCode); - - return $$PREBID_GLOBAL$$._bidsReceived - .filter(bid => adUnitCodes.includes(bid.adUnitCode)) - .filter(bid => bid.cpm > 0) - .map(bid => bid.adUnitCode) - .filter(uniques) - .map(adUnitCode => $$PREBID_GLOBAL$$._bidsReceived - .filter(bid => bid.adUnitCode === adUnitCode ? bid : null) - .reduce(getHighestCpm, getEmptyBid(adUnitCode))); -}; - -targeting.setTargetingForAst = function() { - let targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); - Object.keys(targeting).forEach(targetId => - Object.keys(targeting[targetId]).forEach(key => { - utils.logMessage(`Attempting to set targeting for targetId: ${targetId} key: ${key} value: ${targeting[targetId][key]}`); - // setKeywords supports string and array as value - if (utils.isStr(targeting[targetId][key]) || utils.isArray(targeting[targetId][key])) { - let keywordsObj = {}; - let input = 'hb_adid'; - let nKey = (key.substring(0, input.length) === input) ? key.toUpperCase() : key; - keywordsObj[nKey] = targeting[targetId][key]; - window.apntag.setKeywords(targetId, keywordsObj); + function getBidsReceived() { + return auctionManager.getBidsReceived() + .filter(isUnusedBid) + .filter(exports.isBidExpired) + } + + /** + * Returns top bids for a given adUnit or set of adUnits. + * @param {(string|string[])} adUnitCode adUnitCode or array of adUnitCodes + * @return {[type]} [description] + */ + targeting.getWinningBids = function(adUnitCode) { + const adUnitCodes = getAdUnitCodes(adUnitCode); + + return getBidsReceived() + .filter(bid => includes(adUnitCodes, bid.adUnitCode)) + .filter(bid => bid.cpm > 0) + .map(bid => bid.adUnitCode) + .filter(uniques) + .map(adUnitCode => getBidsReceived() + .filter(bid => bid.adUnitCode === adUnitCode ? bid : null) + .reduce(getHighestCpm, getEmptyBid(adUnitCode))); + }; + + /** + * Sets targeting for AST + */ + targeting.setTargetingForAst = function() { + let astTargeting = targeting.getAllTargeting(); + Object.keys(astTargeting).forEach(targetId => + Object.keys(astTargeting[targetId]).forEach(key => { + utils.logMessage(`Attempting to set targeting for targetId: ${targetId} key: ${key} value: ${astTargeting[targetId][key]}`); + // setKeywords supports string and array as value + if (utils.isStr(astTargeting[targetId][key]) || utils.isArray(astTargeting[targetId][key])) { + let keywordsObj = {}; + let input = 'hb_adid'; + let nKey = (key.substring(0, input.length) === input) ? key.toUpperCase() : key; + keywordsObj[nKey] = astTargeting[targetId][key]; + window.apntag.setKeywords(targetId, keywordsObj); + } + }) + ); + }; + + /** + * Get targeting key value pairs for winning bid. + * @param {string[]} AdUnit code array + * @return {targetingArray} winning bids targeting + */ + function getWinningBidTargeting(adUnitCodes) { + let winners = targeting.getWinningBids(adUnitCodes); + winners.forEach((winner) => { + winner.status = BID_TARGETING_SET; + }); + + // TODO : Add losing bids to pool from here ? + let standardKeys = getStandardKeys(); + + winners = winners.map(winner => { + return { + [winner.adUnitCode]: Object.keys(winner.adserverTargeting) + .filter(key => + typeof winner.sendStandardTargeting === 'undefined' || + winner.sendStandardTargeting || + standardKeys.indexOf(key) === -1) + .map(key => ({ + [(key === 'hb_deal') ? `${key}_${winner.bidderCode}`.substring(0, MAX_DFP_KEYLENGTH) : key.substring(0, MAX_DFP_KEYLENGTH)]: [winner.adserverTargeting[key]] + })) + }; + }); + + return winners; + } + + function getStandardKeys() { + return auctionManager.getStandardBidderAdServerTargeting() // in case using a custom standard key set + .map(targeting => targeting.key) + .concat(CONSTANTS.TARGETING_KEYS).filter(uniques); // standard keys defined in the library. + } + + /** + * Merge custom adserverTargeting with same key name for same adUnitCode. + * e.g: Appnexus defining custom keyvalue pair foo:bar and Rubicon defining custom keyvalue pair foo:baz will be merged to foo: ['bar','baz'] + * + * @param {Object[]} acc Accumulator for reducer. It will store updated bidResponse objects + * @param {Object} bid BidResponse + * @param {number} index current index + * @param {Array} arr original array + */ + function mergeAdServerTargeting(acc, bid, index, arr) { + function concatTargetingValue(key) { + return function(currentBidElement) { + if (!utils.isArray(currentBidElement.adserverTargeting[key])) { + currentBidElement.adserverTargeting[key] = [currentBidElement.adserverTargeting[key]]; + } + currentBidElement.adserverTargeting[key] = currentBidElement.adserverTargeting[key].concat(bid.adserverTargeting[key]).filter(uniques); + delete bid.adserverTargeting[key]; } - }) - ); -}; + } -function getWinningBidTargeting(adUnitCodes) { - let winners = targeting.getWinningBids(adUnitCodes); - let standardKeys = getStandardKeys(); + function hasSameAdunitCodeAndKey(key) { + return function(currentBidElement) { + return currentBidElement.adUnitCode === bid.adUnitCode && currentBidElement.adserverTargeting[key] + } + } - winners = winners.map(winner => { - return { - [winner.adUnitCode]: Object.keys(winner.adserverTargeting) - .filter(key => - typeof winner.sendStandardTargeting === 'undefined' || - winner.sendStandardTargeting || - standardKeys.indexOf(key) === -1) - .map(key => ({ [key.substring(0, 20)]: [winner.adserverTargeting[key]] })) - }; - }); + Object.keys(bid.adserverTargeting) + .filter(getCustomKeys()) + .forEach(key => { + if (acc.length) { + acc.filter(hasSameAdunitCodeAndKey(key)) + .forEach(concatTargetingValue(key)); + } + }); + acc.push(bid); + return acc; + } - return winners; -} + function getCustomKeys() { + let standardKeys = getStandardKeys(); + return function(key) { + return standardKeys.indexOf(key) === -1; + } + } -function getStandardKeys() { - return bidmanager.getStandardBidderAdServerTargeting() // in case using a custom standard key set - .map(targeting => targeting.key) - .concat(CONSTANTS.TARGETING_KEYS).filter(uniques); // standard keys defined in the library. -} + function truncateCustomKeys(bid) { + return { + [bid.adUnitCode]: Object.keys(bid.adserverTargeting) + // Get only the non-standard keys of the losing bids, since we + // don't want to override the standard keys of the winning bid. + .filter(getCustomKeys()) + .map(key => { + return { + [key.substring(0, MAX_DFP_KEYLENGTH)]: [bid.adserverTargeting[key]] + }; + }) + } + } -/** - * Get custom targeting keys for bids that have `alwaysUseBid=true`. - */ -function getAlwaysUseBidTargeting(adUnitCodes) { - let standardKeys = getStandardKeys(); - return $$PREBID_GLOBAL$$._bidsReceived - .filter(adUnitsFilter.bind(this, adUnitCodes)) - .map(bid => { - if (bid.alwaysUseBid) { - return { - [bid.adUnitCode]: Object.keys(bid.adserverTargeting).map(key => { - // Get only the non-standard keys of the losing bids, since we - // don't want to override the standard keys of the winning bid. - if (standardKeys.indexOf(key) > -1) { - return; - } + /** + * Get custom targeting key value pairs for bids. + * @param {string[]} AdUnit code array + * @return {targetingArray} bids with custom targeting defined in bidderSettings + */ + function getCustomBidTargeting(adUnitCodes) { + return getBidsReceived() + .filter(bid => includes(adUnitCodes, bid.adUnitCode)) + .map(bid => Object.assign({}, bid)) + .reduce(mergeAdServerTargeting, []) + .map(truncateCustomKeys) + .filter(bid => bid); // removes empty elements in array; + } - return { [key.substring(0, 20)]: [bid.adserverTargeting[key]] }; - }).filter(key => key) // remove empty elements + /** + * Get targeting key value pairs for non-winning bids. + * @param {string[]} AdUnit code array + * @return {targetingArray} all non-winning bids targeting + */ + function getBidLandscapeTargeting(adUnitCodes) { + const standardKeys = CONSTANTS.TARGETING_KEYS.concat(NATIVE_TARGETING_KEYS); + const bids = []; + // bucket by adUnitcode + let buckets = groupBy(getBidsReceived(), 'adUnitCode'); + // filter top bid for each bucket by bidder + Object.keys(buckets).forEach(bucketKey => { + let bidsByBidder = groupBy(buckets[bucketKey], 'bidderCode'); + Object.keys(bidsByBidder).forEach(key => bids.push(bidsByBidder[key].reduce(getHighestCpm, getEmptyBid()))); + }); + // populate targeting keys for the remaining bids + return bids.map(bid => { + if (bid.adserverTargeting) { + return { + [bid.adUnitCode]: getTargetingMap(bid, standardKeys.filter( + key => typeof bid.adserverTargeting[key] !== 'undefined') + ) }; } - }) - .filter(bid => bid); // removes empty elements in array; -} + }).filter(bid => bid); // removes empty elements in array + } -function getBidLandscapeTargeting(adUnitCodes) { - const standardKeys = CONSTANTS.TARGETING_KEYS.concat(NATIVE_TARGETING_KEYS); - const bids = []; - // bucket by adUnitcode - let buckets = groupBy($$PREBID_GLOBAL$$._bidsReceived, 'adUnitCode'); - // filter top bid for each bucket by bidder - Object.keys(buckets).forEach(bucketKey => { - let bidsByBidder = groupBy(buckets[bucketKey], 'bidderCode'); - Object.keys(bidsByBidder).forEach(key => bids.push(bidsByBidder[key].reduce(getHighestCpm, getEmptyBid()))); - }); - // populate targeting keys for the remaining bids - return bids.map(bid => { - if (bid.adserverTargeting) { + function getTargetingMap(bid, keys) { + return keys.map(key => { return { - [bid.adUnitCode]: getTargetingMap(bid, standardKeys.filter( - key => typeof bid.adserverTargeting[key] !== 'undefined') - ) + [`${key}_${bid.bidderCode}`.substring(0, MAX_DFP_KEYLENGTH)]: [bid.adserverTargeting[key]] }; + }); + } + + targeting.isApntagDefined = function() { + if (window.apntag && utils.isFn(window.apntag.setKeywords)) { + return true; } - }).filter(bid => bid); // removes empty elements in array -} + }; -function getTargetingMap(bid, keys) { - return keys.map(key => { + function getEmptyBid(adUnitCode) { return { - [`${key}_${bid.bidderCode}`.substring(0, 20)]: [bid.adserverTargeting[key]] + adUnitCode: adUnitCode, + cpm: 0, + adserverTargeting: {}, + timeToRespond: 0 }; - }); -} - -targeting.isApntagDefined = function() { - if (window.apntag && utils.isFn(window.apntag.setKeywords)) { - return true; } -}; - -function getEmptyBid(adUnitCode) { - return { - adUnitCode: adUnitCode, - cpm: 0, - adserverTargeting: {}, - timeToRespond: 0 - }; + return targeting; } + +export const targeting = newTargeting(auctionManager); diff --git a/src/utils.js b/src/utils.js index 24d07723742..d5657845492 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,5 +1,7 @@ import { config } from './config'; import clone from 'just-clone'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; var CONSTANTS = require('./constants'); var _loggingChecked = false; @@ -572,8 +574,8 @@ export function flatten(a, b) { return a.concat(b); } -export function getBidRequest(id) { - return $$PREBID_GLOBAL$$._bidsRequested.map(bidSet => bidSet.bids.find(bid => bid.bidId === id)).find(bid => bid); +export function getBidRequest(id, bidsRequested) { + return find(bidsRequested.map(bidSet => find(bidSet.bids, bid => bid.bidId === id)), bid => bid); } export function getKeys(obj) { @@ -631,7 +633,7 @@ export function shuffle(array) { } export function adUnitsFilter(filter, bid) { - return filter.includes((bid && bid.placementCode) || (bid && bid.adUnitCode)); + return includes(filter, bid && bid.adUnitCode); } /** @@ -665,15 +667,8 @@ export function replaceAuctionPrice(str, cpm) { return str.replace(/\$\{AUCTION_PRICE\}/g, cpm); } -export function getBidderRequestAllAdUnits(bidder) { - return $$PREBID_GLOBAL$$._bidsRequested.find(request => request.bidderCode === bidder); -} - -export function getBidderRequest(bidder, adUnitCode) { - return $$PREBID_GLOBAL$$._bidsRequested.find(request => { - return request.bids - .filter(bid => bid.bidder === bidder && bid.placementCode === adUnitCode).length > 0; - }) || { start: null, requestId: null }; +export function timestamp() { + return new Date().getTime(); } export function cookiesAreEnabled() { @@ -784,17 +779,56 @@ export function isValidMediaTypes(mediaTypes) { const types = Object.keys(mediaTypes); - if (!types.every(type => SUPPORTED_MEDIA_TYPES.includes(type))) { + if (!types.every(type => includes(SUPPORTED_MEDIA_TYPES, type))) { return false; } if (mediaTypes.video && mediaTypes.video.context) { - return SUPPORTED_STREAM_TYPES.includes(mediaTypes.video.context); + return includes(SUPPORTED_STREAM_TYPES, mediaTypes.video.context); } return true; } +export function getBidderRequest(bidRequests, bidder, adUnitCode) { + return find(bidRequests, request => { + return request.bids + .filter(bid => bid.bidder === bidder && bid.adUnitCode === adUnitCode).length > 0; + }) || { start: null, requestId: null }; +} + +/** + * Returns the origin + */ +export function getOrigin() { + // IE10 does not have this property. https://gist.github.com/hbogs/7908703 + if (!window.location.origin) { + return window.location.protocol + '//' + window.location.hostname + (window.location.port ? ':' + window.location.port : ''); + } else { + return window.location.origin; + } +} + +const compareCodeAndSlot = (slot, adUnitCode) => slot.getAdUnitPath() === adUnitCode || slot.getSlotElementId() === adUnitCode; + +/** + * Returns filter function to match adUnitCode in slot + * @param {object} slot GoogleTag slot + * @return {function} filter function + */ +export function isAdUnitCodeMatchingSlot(slot) { + return (adUnitCode) => compareCodeAndSlot(slot, adUnitCode); +} + +/** + * Returns filter function to match adUnitCode in slot + * @param {string} adUnitCode AdUnit code + * @return {function} filter function + */ +export function isSlotMatchingAdUnitCode(adUnitCode) { + return (slot) => compareCodeAndSlot(slot, adUnitCode); +} + /** * Constructs warning message for when unsupported bidders are dropped from an adunit * @param {Object} adUnit ad unit from which the bidder is being dropped diff --git a/src/video.js b/src/video.js index 22255068cc0..8e0775a6d62 100644 --- a/src/video.js +++ b/src/video.js @@ -1,6 +1,7 @@ import { videoAdapters } from './adaptermanager'; import { getBidRequest, deepAccess, logError } from './utils'; import { config } from '../src/config'; +import includes from 'core-js/library/fn/array/includes'; const VIDEO_MEDIA_TYPE = 'video'; const OUTSTREAM = 'outstream'; @@ -13,7 +14,7 @@ export const videoAdUnit = adUnit => { const mediaTypes = deepAccess(adUnit, 'mediaTypes.video'); return mediaType || mediaTypes; }; -export const videoBidder = bid => videoAdapters.includes(bid.bidder); +export const videoBidder = bid => includes(videoAdapters, bid.bidder); export const hasNonVideoBidder = adUnit => adUnit.bids.filter(bid => !videoBidder(bid)).length; @@ -24,11 +25,12 @@ export const hasNonVideoBidder = adUnit => /** * Validate that the assets required for video context are present on the bid - * @param {VideoBid} bid video bid to validate - * @return {boolean} If object is valid + * @param {VideoBid} bid Video bid to validate + * @param {BidRequest[]} bidRequests All bid requests for an auction + * @return {Boolean} If object is valid */ -export function isValidVideoBid(bid) { - const bidRequest = getBidRequest(bid.adId); +export function isValidVideoBid(bid, bidRequests) { + const bidRequest = getBidRequest(bid.adId, bidRequests); const videoMediaType = bidRequest && deepAccess(bidRequest, 'mediaTypes.video'); @@ -37,11 +39,11 @@ export function isValidVideoBid(bid) { // if context not defined assume default 'instream' for video bids // instream bids require a vast url or vast xml content if (!bidRequest || (videoMediaType && context !== OUTSTREAM)) { - // xml-only video bids require prebid-cache to be enabled - if (!config.getConfig('usePrebidCache') && bid.vastXml && !bid.vastUrl) { + // xml-only video bids require a prebid cache url + if (!config.getConfig('cache.url') && bid.vastXml && !bid.vastUrl) { logError(` - This bid contains only vastXml and will not work when prebid-cache is disabled. - Try enabling prebid-cache with pbjs.setConfig({ usePrebidCache: true }); + This bid contains only vastXml and will not work when a prebid cache url is not specified. + Try enabling prebid cache with pbjs.setConfig({ cache: {url: "..."} }); `); return false; } diff --git a/src/videoCache.js b/src/videoCache.js index fe126fad6e0..2af980316fa 100644 --- a/src/videoCache.js +++ b/src/videoCache.js @@ -10,8 +10,7 @@ */ import { ajax } from './ajax'; - -const BASE_URL = 'https://prebid.adnxs.com/pbc/v1/cache' +import { config } from '../src/config'; /** * @typedef {object} CacheableUrlBid @@ -119,12 +118,12 @@ export function store(bids, done) { puts: bids.map(toStorageRequest) }; - ajax(BASE_URL, shimStorageCallback(done), JSON.stringify(requestData), { + ajax(config.getConfig('cache.url'), shimStorageCallback(done), JSON.stringify(requestData), { contentType: 'text/plain', withCredentials: true }); } export function getCacheUrl(id) { - return `${BASE_URL}?uuid=${id}`; + return `${config.getConfig('cache.url')}?uuid=${id}`; } diff --git a/test/fixtures/fixtures.js b/test/fixtures/fixtures.js index 8108da3c555..8dbbe265cca 100644 --- a/test/fixtures/fixtures.js +++ b/test/fixtures/fixtures.js @@ -317,7 +317,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '0x0', 'foobar': '0x0' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'appnexus', @@ -346,7 +349,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'appnexus', @@ -375,7 +381,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '728x90', 'foobar': '728x90' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'pagescience', @@ -403,7 +412,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'brightcom', @@ -430,7 +442,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'brealtime', @@ -458,7 +473,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'pubmatic', @@ -487,7 +505,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'rubicon', @@ -514,7 +535,10 @@ export function getBidResponses() { 'hb_pb': '10.00', 'hb_size': '300x600', 'foobar': '300x600' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 } ]; } @@ -1015,7 +1039,10 @@ export function getBidResponsesFromAPI() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'brealtime', @@ -1043,7 +1070,10 @@ export function getBidResponsesFromAPI() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'pubmatic', @@ -1072,7 +1102,10 @@ export function getBidResponsesFromAPI() { 'hb_pb': '10.00', 'hb_size': '300x250', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }, { 'bidderCode': 'rubicon', @@ -1099,7 +1132,10 @@ export function getBidResponsesFromAPI() { 'hb_pb': '10.00', 'hb_size': '300x600', 'foobar': '300x600' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 } ] } @@ -1110,7 +1146,7 @@ export function getBidResponsesFromAPI() { export function getAdServerTargeting() { return { '/19968336/header-bid-tag-0': { - 'foobar': '300x250', + 'foobar': '0x0,300x250,300x600', 'hb_size': '300x250', 'hb_pb': '10.00', 'hb_adid': '233bcbee889d46d', @@ -1179,11 +1215,7 @@ export function getTargetingKeys() { ], [ 'foobar', - '300x250' - ], - [ - 'foobar', - '300x250' + ['0x0', '300x250', '300x600'] ] ]; } @@ -1197,7 +1229,7 @@ export function getTargetingKeysBidLandscape() { 'appnexus' ], [ - 'hb_adid', + 'hb_adid_appnexus', '233bcbee889d46d' ], [ @@ -1210,11 +1242,7 @@ export function getTargetingKeysBidLandscape() { ], [ 'foobar', - '300x250' - ], - [ - 'foobar', - '300x250' + ['0x0', '300x250', '300x600'] ], [ 'hb_bidder_triplelift', @@ -1236,10 +1264,6 @@ export function getTargetingKeysBidLandscape() { 'hb_bidder_appnexus', 'appnexus' ], - [ - 'hb_adid_appnexus', - '233bcbee889d46d' - ], [ 'hb_pb_appnexus', '10.00' diff --git a/test/fixtures/video/adUnit.json b/test/fixtures/video/adUnit.json index 6d2b7c385ad..df55eb25d79 100644 --- a/test/fixtures/video/adUnit.json +++ b/test/fixtures/video/adUnit.json @@ -4,7 +4,7 @@ "mediaType": "video", "bids": [ { - "bidder": "appnexusAst", + "bidder": "appnexus", "params": { "placementId": "9333431", "video": { diff --git a/test/fixtures/video/bidRequest.json b/test/fixtures/video/bidRequest.json index 75f054611c4..f8306e27662 100644 --- a/test/fixtures/video/bidRequest.json +++ b/test/fixtures/video/bidRequest.json @@ -1,10 +1,10 @@ { "auctionStart": 1462918897459, - "bidderCode": "appnexusAst", + "bidderCode": "appnexus", "bidderRequestId": "2946b569352ef2", "bids": [ { - "bidder": "appnexusAst", + "bidder": "appnexus", "params": { "placementId": "9333431", "video": { diff --git a/test/fixtures/video/vastPayloadResponse.json b/test/fixtures/video/vastPayloadResponse.json index 9b621c21d30..7c388de41ed 100644 --- a/test/fixtures/video/vastPayloadResponse.json +++ b/test/fixtures/video/vastPayloadResponse.json @@ -1,8 +1,8 @@ { "adUnitCode": "video1", - "bidder": "appnexusAst", - "bidderCode": "appnexusAst", - "code": "appnexusAst", + "bidder": "appnexus", + "bidderCode": "appnexus", + "code": "appnexus", "dealId": "foo", "cpm": 0.1, "height": 480, diff --git a/test/fixtures/video/vastUrlResponse.json b/test/fixtures/video/vastUrlResponse.json index cba0798251d..f3b023dc7bb 100644 --- a/test/fixtures/video/vastUrlResponse.json +++ b/test/fixtures/video/vastUrlResponse.json @@ -1,8 +1,8 @@ { "adUnitCode": "video1", - "bidder": "appnexusAst", - "bidderCode": "appnexusAst", - "code": "appnexusAst", + "bidder": "appnexus", + "bidderCode": "appnexus", + "code": "appnexus", "dealId": "foo", "cpm": 0.1, "height": 480, diff --git a/test/pages/video.html b/test/pages/video.html index 8d28650cbfc..c6a72b6e26b 100644 --- a/test/pages/video.html +++ b/test/pages/video.html @@ -36,7 +36,7 @@ }, bids: [ { - bidder: 'appnexusAst', + bidder: 'appnexus', params: { placementId: '9333431', video: { diff --git a/test/spec/api_spec.js b/test/spec/api_spec.js index b3e2e0fc666..41fafb080ad 100755 --- a/test/spec/api_spec.js +++ b/test/spec/api_spec.js @@ -47,10 +47,6 @@ describe('Publisher API', function () { assert.isFunction($$PREBID_GLOBAL$$.setTargetingForGPTAsync); }); - it('should have function $$PREBID_GLOBAL$$.allBidsAvailable', function () { - assert.isFunction($$PREBID_GLOBAL$$.allBidsAvailable); - }); - it('should have function $$PREBID_GLOBAL$$.renderAd', function () { assert.isFunction($$PREBID_GLOBAL$$.renderAd); }); @@ -67,14 +63,6 @@ describe('Publisher API', function () { assert.isFunction($$PREBID_GLOBAL$$.addAdUnits); }); - it('should have function $$PREBID_GLOBAL$$.addCallback', function () { - assert.isFunction($$PREBID_GLOBAL$$.addCallback); - }); - - it('should have function $$PREBID_GLOBAL$$.removeCallback', function () { - assert.isFunction($$PREBID_GLOBAL$$.removeCallback); - }); - it('should have function $$PREBID_GLOBAL$$.aliasBidder', function () { assert.isFunction($$PREBID_GLOBAL$$.aliasBidder); }); diff --git a/test/spec/auctionmanager_spec.js b/test/spec/auctionmanager_spec.js new file mode 100644 index 00000000000..c773974d177 --- /dev/null +++ b/test/spec/auctionmanager_spec.js @@ -0,0 +1,861 @@ +import { auctionManager, newAuctionManager } from 'src/auctionManager'; +import { getKeyValueTargetingPairs } from 'src/auction'; +import CONSTANTS from 'src/constants.json'; +import { adjustBids } from 'src/auction'; +import * as auctionModule from 'src/auction'; +import { newBidder, registerBidder } from 'src/adapters/bidderFactory'; +import * as ajaxLib from 'src/ajax'; + +var assert = require('assert'); + +/* use this method to test individual files instead of the whole prebid.js project */ + +// TODO refactor to use the spec files +var utils = require('../../src/utils'); +var bidfactory = require('../../src/bidfactory'); +var fixtures = require('../fixtures/fixtures'); +var adaptermanager = require('src/adaptermanager'); +var events = require('src/events'); + +function timestamp() { + return new Date().getTime(); +} + +describe('auctionmanager.js', function () { + describe('getKeyValueTargetingPairs', function () { + var bid = {}; + var bidPriceCpm = 5.578; + var bidPbLg = 5.50; + var bidPbMg = 5.50; + var bidPbHg = 5.57; + var bidPbAg = 5.50; + + var adUnitCode = '12345'; + var bidderCode = 'appnexus'; + var size = '300x250'; + var adId = '1adId'; + + before(function () { + bid.cpm = bidPriceCpm; + bid.pbLg = bidPbLg; + bid.pbMg = bidPbMg; + bid.pbHg = bidPbHg; + bid.pbAg = bidPbAg; + + bid.height = 300; + bid.width = 250; + bid.adUnitCode = adUnitCode; + bid.getSize = function () { + return this.height + 'x' + this.width; + }; + bid.bidderCode = bidderCode; + bid.adId = adId; + }); + + it('No bidder level configuration defined - default', function () { + var expected = { + 'hb_bidder': bidderCode, + 'hb_adid': adId, + 'hb_pb': bidPbMg, + 'hb_size': size + }; + var response = getKeyValueTargetingPairs(bidderCode, bid, CONSTANTS.GRANULARITY_OPTIONS.MEDIUM); + assert.deepEqual(response, expected); + }); + + it('Custom configuration for all bidders', function () { + $$PREBID_GLOBAL$$.bidderSettings = + { + standard: { + adserverTargeting: [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + // change default here + return bidResponse.pbHg; + } + }, { + key: 'hb_size', + val: function (bidResponse) { + return bidResponse.size; + } + } + ] + + } + }; + + var expected = { + 'hb_bidder': bidderCode, + 'hb_adid': adId, + 'hb_pb': bidPbHg, + 'hb_size': size + }; + var response = getKeyValueTargetingPairs(bidderCode, bid, CONSTANTS.GRANULARITY_OPTIONS.MEDIUM); + assert.deepEqual(response, expected); + }); + + it('Custom configuration for one bidder', function () { + $$PREBID_GLOBAL$$.bidderSettings = + { + appnexus: { + adserverTargeting: [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + // change default here + return bidResponse.pbHg; + } + }, { + key: 'hb_size', + val: function (bidResponse) { + return bidResponse.size; + } + } + ] + + } + }; + + var expected = { + 'hb_bidder': bidderCode, + 'hb_adid': adId, + 'hb_pb': bidPbHg, + 'hb_size': size + }; + var response = getKeyValueTargetingPairs(bidderCode, bid); + assert.deepEqual(response, expected); + }); + + it('Custom configuration for one bidder - not matched', function () { + $$PREBID_GLOBAL$$.bidderSettings = + { + nonExistentBidder: { + adserverTargeting: [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + // change default here + return bidResponse.pbHg; + } + }, { + key: 'hb_size', + val: function (bidResponse) { + return bidResponse.size; + } + } + ] + + } + }; + + var expected = { + 'hb_bidder': bidderCode, + 'hb_adid': adId, + 'hb_pb': bidPbMg, + 'hb_size': size + }; + var response = getKeyValueTargetingPairs(bidderCode, bid, CONSTANTS.GRANULARITY_OPTIONS.MEDIUM); + assert.deepEqual(response, expected); + }); + + it('Custom bidCpmAdjustment for one bidder and inherit standard but doesn\'t use standard bidCpmAdjustment', function () { + $$PREBID_GLOBAL$$.bidderSettings = + { + appnexus: { + bidCpmAdjustment: function (bidCpm) { + return bidCpm * 0.7; + }, + }, + standard: { + bidCpmAdjustment: function (bidCpm) { + return 200; + }, + adserverTargeting: [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + // change default here + return 10.00; + } + } + ] + + } + }; + + var expected = { 'hb_bidder': bidderCode, 'hb_adid': adId, 'hb_pb': 10.0 }; + var response = getKeyValueTargetingPairs(bidderCode, bid); + assert.deepEqual(response, expected); + }); + + it('Standard bidCpmAdjustment changes the bid of any bidder', function () { + const bid = Object.assign({}, + bidfactory.createBid(2), + fixtures.getBidResponses()[5] + ); + + assert.equal(bid.cpm, 0.5); + + $$PREBID_GLOBAL$$.bidderSettings = + { + standard: { + bidCpmAdjustment: function (bidCpm) { + return bidCpm * 0.5; + } + } + }; + + adjustBids(bid) + assert.equal(bid.cpm, 0.25); + }); + + it('Custom bidCpmAdjustment AND custom configuration for one bidder and inherit standard settings', function () { + $$PREBID_GLOBAL$$.bidderSettings = + { + appnexus: { + bidCpmAdjustment: function (bidCpm) { + return bidCpm * 0.7; + }, + adserverTargeting: [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + // change default here + return 15.00; + } + } + ] + }, + standard: { + adserverTargeting: [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + // change default here + return 10.00; + }, + }, + { + key: 'hb_size', + val: function (bidResponse) { + return bidResponse.size; + } + } + ] + + } + }; + + var expected = { + 'hb_bidder': bidderCode, + 'hb_adid': adId, + 'hb_pb': 15.0, + 'hb_size': '300x250' + }; + var response = getKeyValueTargetingPairs(bidderCode, bid); + assert.deepEqual(response, expected); + }); + + it('sendStandardTargeting=false, and inherit custom', function () { + $$PREBID_GLOBAL$$.bidderSettings = + { + appnexus: { + sendStandardTargeting: false, + adserverTargeting: [ + { + key: 'hb_bidder', + val: function (bidResponse) { + return bidResponse.bidderCode; + } + }, { + key: 'hb_adid', + val: function (bidResponse) { + return bidResponse.adId; + } + }, { + key: 'hb_pb', + val: function (bidResponse) { + return bidResponse.pbHg; + } + } + ] + } + }; + + var expected = { + 'hb_bidder': bidderCode, + 'hb_adid': adId, + 'hb_pb': 5.57, + 'hb_size': '300x250' + }; + var response = getKeyValueTargetingPairs(bidderCode, bid); + assert.deepEqual(response, expected); + assert.equal(bid.sendStandardTargeting, false); + }); + + it('suppressEmptyKeys=true', function() { + $$PREBID_GLOBAL$$.bidderSettings = + { + standard: { + suppressEmptyKeys: true, + adserverTargeting: [ + { + key: 'aKeyWithAValue', + val: 42 + }, + { + key: 'aKeyWithAnEmptyValue', + val: '' + } + ] + } + }; + + var expected = { + 'aKeyWithAValue': 42 + }; + + var response = getKeyValueTargetingPairs(bidderCode, bid); + assert.deepEqual(response, expected); + }); + }); + + describe('adjustBids', () => { + it('should adjust bids if greater than zero and pass copy of bid object', () => { + const bid = Object.assign({}, + bidfactory.createBid(2), + fixtures.getBidResponses()[5] + ); + + assert.equal(bid.cpm, 0.5); + + $$PREBID_GLOBAL$$.bidderSettings = + { + brealtime: { + bidCpmAdjustment: function (bidCpm, bidObj) { + assert.deepEqual(bidObj, bid); + if (bidObj.adUnitCode === 'negative') { + return bidCpm * -0.5; + } + if (bidObj.adUnitCode === 'zero') { + return 0; + } + return bidCpm * 0.5; + }, + }, + standard: { + adserverTargeting: [ + ] + } + }; + + // negative + bid.adUnitCode = 'negative'; + adjustBids(bid) + assert.equal(bid.cpm, 0.5); + + // positive + bid.adUnitCode = 'normal'; + adjustBids(bid) + assert.equal(bid.cpm, 0.25); + + // zero + bid.adUnitCode = 'zero'; + adjustBids(bid) + assert.equal(bid.cpm, 0); + + // reset bidderSettings so we don't mess up further tests + $$PREBID_GLOBAL$$.bidderSettings = {}; + }); + }); + + describe('addBidResponse', () => { + let createAuctionStub; + let adUnits; + let adUnitCodes; + let spec; + let auction; + let ajaxStub; + const BIDDER_CODE = 'sampleBidder'; + let makeRequestsStub; + let bids = [{ + 'ad': 'creative', + 'cpm': '1.99', + 'width': 300, + 'height': 250, + 'bidderCode': BIDDER_CODE, + 'requestId': '4d0a6829338a07', + 'creativeId': 'id', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360 + }]; + + let bidRequests = [{ + 'bidderCode': BIDDER_CODE, + 'auctionId': '20882439e3238c', + 'bidderRequestId': '331f3cf3f1d9c8', + 'bids': [ + { + 'bidder': BIDDER_CODE, + 'params': { + 'placementId': 'id' + }, + 'adUnitCode': 'adUnit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4d0a6829338a07', + 'bidderRequestId': '331f3cf3f1d9c8', + 'auctionId': '20882439e3238c' + } + ], + 'auctionStart': 1505250713622, + 'timeout': 3000 + }]; + + before(() => { + makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); + makeRequestsStub.returns(bidRequests); + + ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder', function() { + return function(url, callback) { + const fakeResponse = sinon.stub(); + fakeResponse.returns('headerContent'); + callback.success('response body', { getResponseHeader: fakeResponse }); + } + }); + }); + + after(() => { + ajaxStub.restore(); + adaptermanager.makeBidRequests.restore(); + }); + + describe('when auction timeout is 3000', () => { + beforeEach(() => { + adUnits = [{ + code: 'adUnit-code', + bids: [ + {bidder: BIDDER_CODE, params: {placementId: 'id'}}, + ] + }]; + adUnitCodes = ['adUnit-code']; + auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 3000}); + createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + + spec = { + code: BIDDER_CODE, + isBidRequestValid: sinon.stub(), + buildRequests: sinon.stub(), + interpretResponse: sinon.stub(), + getUserSyncs: sinon.stub() + }; + }); + + afterEach(() => { + auctionModule.newAuction.restore(); + }); + + it('should return proper price bucket increments for dense mode when cpm is in range 0-3', () => { + bids[0].cpm = '1.99'; + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + auction.callBids(); + let registeredBid = auction.getBidsReceived().pop(); + assert.equal(registeredBid.pbDg, '1.99', '0 - 3 hits at to 1 cent increment'); + }); + + it('should return proper price bucket increments for dense mode when cpm is in range 3-8', () => { + bids[0].cpm = '4.39'; + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + auction.callBids(); + let registeredBid = auction.getBidsReceived().pop(); + assert.equal(registeredBid.pbDg, '4.35', '3 - 8 hits at 5 cent increment'); + }); + + it('should return proper price bucket increments for dense mode when cpm is in range 8-20', () => { + bids[0].cpm = '19.99'; + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + auction.callBids(); + let registeredBid = auction.getBidsReceived().pop(); + assert.equal(registeredBid.pbDg, '19.50', '8 - 20 hits at 50 cent increment'); + }); + + it('should return proper price bucket increments for dense mode when cpm is 20+', () => { + bids[0].cpm = '73.07'; + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + auction.callBids(); + let registeredBid = auction.getBidsReceived().pop(); + assert.equal(registeredBid.pbDg, '20.00', '20+ caps at 20.00'); + }); + + it('should place dealIds in adserver targeting', () => { + bids[0].dealId = 'test deal'; + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + auction.callBids(); + let registeredBid = auction.getBidsReceived().pop(); + assert.equal(registeredBid.adserverTargeting[`hb_deal`], 'test deal', 'dealId placed in adserverTargeting'); + }); + + it('should pass through default adserverTargeting sent from adapter', () => { + bids[0].adserverTargeting = {}; + bids[0].adserverTargeting.extra = 'stuff'; + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + auction.callBids(); + let registeredBid = auction.getBidsReceived().pop(); + assert.equal(registeredBid.adserverTargeting.hb_bidder, 'sampleBidder'); + assert.equal(registeredBid.adserverTargeting.extra, 'stuff'); + }); + + it('installs publisher-defined renderers on bids', () => { + let bidRequests = [{ + 'bidderCode': BIDDER_CODE, + 'auctionId': '20882439e3238c', + 'bidderRequestId': '331f3cf3f1d9c8', + 'bids': [ + { + 'bidder': BIDDER_CODE, + 'params': { + 'placementId': 'id' + }, + 'adUnitCode': 'adUnit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4d0a6829338a07', + 'bidderRequestId': '331f3cf3f1d9c8', + 'auctionId': '20882439e3238c', + 'renderer': { + url: 'renderer.js', + render: (bid) => bid + } + } + ], + 'auctionStart': 1505250713622, + 'timeout': 3000 + }]; + + makeRequestsStub.returns(bidRequests); + let bids1 = Object.assign({}, + bids[0], + { + bidderCode: BIDDER_CODE, + mediaType: 'video-outstream', + } + ); + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids1); + auction.callBids(); + const addedBid = auction.getBidsReceived().pop(); + assert.equal(addedBid.renderer.url, 'renderer.js'); + }); + }); + + describe('with auction timeout 20', () => { + let auction; + let adUnits; + let adUnitCodes; + let createAuctionStub; + let spec; + let getBidderRequestStub; + let eventsEmitSpy; + + beforeEach(() => { + adUnits = [{ + code: 'adUnit-code', + bids: [ + {bidder: BIDDER_CODE, params: {placementId: 'id'}}, + ] + }]; + adUnitCodes = ['adUnit-code']; + auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 20}); + createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + getBidderRequestStub = sinon.stub(utils, 'getBidderRequest'); + + let newBidRequest = Object.assign({}, bidRequests[0], {'start': 1000}); + getBidderRequestStub.returns(newBidRequest); + + spec = { + code: BIDDER_CODE, + isBidRequestValid: sinon.stub(), + buildRequests: sinon.stub(), + interpretResponse: sinon.stub(), + getUserSyncs: sinon.stub() + }; + eventsEmitSpy = sinon.spy(events, 'emit'); + }); + + afterEach(() => { + auctionModule.newAuction.restore(); + utils.getBidderRequest.restore(); + events.emit.restore(); + }); + + it('should emit BID_TIMEOUT for timed out bids', () => { + registerBidder(spec); + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + auction.callBids(); + assert.ok(eventsEmitSpy.calledWith(CONSTANTS.EVENTS.BID_TIMEOUT), 'emitted events BID_TIMEOUT'); + }); + }); + }); + + describe('addBidResponse', () => { + let createAuctionStub; + let adUnits; + let adUnitCodes; + let spec; + let spec1; + let auction; + let ajaxStub; + const BIDDER_CODE = 'sampleBidder'; + const BIDDER_CODE1 = 'sampleBidder1'; + + let makeRequestsStub; + let bids = [{ + 'ad': 'creative', + 'cpm': '1.99', + 'width': 300, + 'height': 250, + 'bidderCode': BIDDER_CODE, + 'requestId': '4d0a6829338a07', + 'creativeId': 'id', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360 + }]; + + let bids1 = [{ + 'ad': 'creative', + 'cpm': '1.99', + 'width': 300, + 'height': 250, + 'bidderCode': BIDDER_CODE1, + 'requestId': '5d0a6829338a07', + 'creativeId': 'id', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360 + }]; + + let bidRequests = [{ + 'bidderCode': BIDDER_CODE, + 'auctionId': '20882439e3238c', + 'bidderRequestId': '331f3cf3f1d9c8', + 'bids': [ + { + 'bidder': BIDDER_CODE, + 'params': { + 'placementId': 'id' + }, + 'adUnitCode': 'adUnit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4d0a6829338a07', + 'bidderRequestId': '331f3cf3f1d9c8', + 'auctionId': '20882439e3238c' + } + ], + 'auctionStart': 1505250713622, + 'timeout': 3000 + }, { + 'bidderCode': BIDDER_CODE1, + 'auctionId': '20882439e3238c', + 'bidderRequestId': '661f3cf3f1d9c8', + 'bids': [ + { + 'bidder': BIDDER_CODE1, + 'params': { + 'placementId': 'id' + }, + 'adUnitCode': 'adUnit-code-1', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '5d0a6829338a07', + 'bidderRequestId': '661f3cf3f1d9c8', + 'auctionId': '20882439e3238c' + } + ], + 'auctionStart': 1505250713623, + 'timeout': 3000 + }]; + + before(() => { + makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); + makeRequestsStub.returns(bidRequests); + + ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder', function() { + return function(url, callback) { + const fakeResponse = sinon.stub(); + fakeResponse.returns('headerContent'); + callback.success('response body', { getResponseHeader: fakeResponse }); + } + }); + }); + + after(() => { + ajaxStub.restore(); + adaptermanager.makeBidRequests.restore(); + }); + + beforeEach(() => { + adUnits = [{ + code: 'adUnit-code', + bids: [ + {bidder: BIDDER_CODE, params: {placementId: 'id'}}, + ] + }, { + code: 'adUnit-code-1', + bids: [ + {bidder: BIDDER_CODE1, params: {placementId: 'id'}}, + ] + }]; + adUnitCodes = ['adUnit-code', 'adUnit-code-1']; + auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 3000}); + createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + + spec = { + code: BIDDER_CODE, + isBidRequestValid: sinon.stub(), + buildRequests: sinon.stub(), + interpretResponse: sinon.stub(), + getUserSyncs: sinon.stub() + }; + + spec1 = { + code: BIDDER_CODE1, + isBidRequestValid: sinon.stub(), + buildRequests: sinon.stub(), + interpretResponse: sinon.stub(), + getUserSyncs: sinon.stub() + }; + }); + + afterEach(() => { + auctionModule.newAuction.restore(); + }); + + it('should not alter bid adID', () => { + registerBidder(spec); + registerBidder(spec1); + + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + + spec1.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec1.isBidRequestValid.returns(true); + spec1.interpretResponse.returns(bids1); + + auction.callBids(); + + const addedBid2 = auction.getBidsReceived().pop(); + assert.equal(addedBid2.adId, bids1[0].requestId); + const addedBid1 = auction.getBidsReceived().pop(); + assert.equal(addedBid1.adId, bids[0].requestId); + }); + + it('should not add banner bids that have no width or height', () => { + bids1[0].width = undefined; + bids1[0].height = undefined; + + registerBidder(spec); + registerBidder(spec1); + + spec.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec.isBidRequestValid.returns(true); + spec.interpretResponse.returns(bids); + + spec1.buildRequests.returns([{'id': 123, 'method': 'POST'}]); + spec1.isBidRequestValid.returns(true); + spec1.interpretResponse.returns(bids1); + + auction.callBids(); + + let length = auction.getBidsReceived().length; + const addedBid2 = auction.getBidsReceived().pop(); + assert.notEqual(addedBid2.adId, bids1[0].requestId); + assert.equal(length, 1); + }); + }); +}); diff --git a/test/spec/bidmanager_spec.js b/test/spec/bidmanager_spec.js deleted file mode 100644 index 967258a7fbc..00000000000 --- a/test/spec/bidmanager_spec.js +++ /dev/null @@ -1,684 +0,0 @@ -var assert = require('assert'); - -/* use this method to test individual files instead of the whole prebid.js project */ - -// TODO refactor to use the spec files -var utils = require('../../src/utils'); -var bidmanager = require('../../src/bidmanager'); -var bidfactory = require('../../src/bidfactory'); -var fixtures = require('../fixtures/fixtures'); - -function timestamp() { - return new Date().getTime(); -} - -describe('replaceTokenInString', function () { - it('should replace all given tokens in a String', function () { - var tokensToReplace = { - 'foo': 'bar', - 'zap': 'quux' - }; - - var output = utils.replaceTokenInString('hello %FOO%, I am %ZAP%', tokensToReplace, '%'); - assert.equal(output, 'hello bar, I am quux'); - }); - - it('should ignore tokens it does not see', function () { - var output = utils.replaceTokenInString('hello %FOO%', {}, '%'); - - assert.equal(output, 'hello %FOO%'); - }); -}); - -describe('bidmanager.js', function () { - describe('getKeyValueTargetingPairs', function () { - var bid = {}; - var bidPriceCpm = 5.578; - var bidPbLg = 5.50; - var bidPbMg = 5.50; - var bidPbHg = 5.57; - var bidPbAg = 5.50; - - var adUnitCode = '12345'; - var bidderCode = 'appnexus'; - var size = '300x250'; - var adId = '1adId'; - - before(function () { - bid.cpm = bidPriceCpm; - bid.pbLg = bidPbLg; - bid.pbMg = bidPbMg; - bid.pbHg = bidPbHg; - bid.pbAg = bidPbAg; - - bid.height = 300; - bid.width = 250; - bid.adUnitCode = adUnitCode; - bid.getSize = function () { - return this.height + 'x' + this.width; - }; - bid.bidderCode = bidderCode; - bid.adId = adId; - }); - - it('No bidder level configuration defined - default', function () { - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': bidPbMg, - 'hb_size': size - }; - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - }); - - it('Custom configuration for all bidders', function () { - $$PREBID_GLOBAL$$.bidderSettings = - { - standard: { - adserverTargeting: [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - // change default here - return bidResponse.pbHg; - } - }, { - key: 'hb_size', - val: function (bidResponse) { - return bidResponse.size; - } - } - ] - - } - }; - - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': bidPbHg, - 'hb_size': size - }; - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - }); - - it('Custom configuration for one bidder', function () { - $$PREBID_GLOBAL$$.bidderSettings = - { - appnexus: { - adserverTargeting: [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - // change default here - return bidResponse.pbHg; - } - }, { - key: 'hb_size', - val: function (bidResponse) { - return bidResponse.size; - } - } - ] - - } - }; - - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': bidPbHg, - 'hb_size': size - }; - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - }); - - it('Custom configuration for one bidder - not matched', function () { - $$PREBID_GLOBAL$$.bidderSettings = - { - nonExistentBidder: { - adserverTargeting: [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - // change default here - return bidResponse.pbHg; - } - }, { - key: 'hb_size', - val: function (bidResponse) { - return bidResponse.size; - } - } - ] - - } - }; - - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': bidPbMg, - 'hb_size': size - }; - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - }); - - it('Custom bidCpmAdjustment for one bidder and inherit standard but doesn\'t use standard bidCpmAdjustment', function () { - $$PREBID_GLOBAL$$.bidderSettings = - { - appnexus: { - bidCpmAdjustment: function (bidCpm) { - return bidCpm * 0.7; - }, - }, - standard: { - bidCpmAdjustment: function (bidCpm) { - return 200; - }, - adserverTargeting: [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - // change default here - return 10.00; - } - } - ] - - } - }; - - var expected = { 'hb_bidder': bidderCode, 'hb_adid': adId, 'hb_pb': 10.0 }; - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - }); - - it('Standard bidCpmAdjustment changes the bid of any bidder', function () { - const bid = Object.assign({}, - bidfactory.createBid(2), - fixtures.getBidResponses()[5] - ); - - assert.equal(bid.cpm, 0.5); - - $$PREBID_GLOBAL$$.bidderSettings = - { - standard: { - bidCpmAdjustment: function (bidCpm) { - return bidCpm * 0.5; - } - } - }; - - bidmanager.adjustBids(bid) - assert.equal(bid.cpm, 0.25); - }); - - it('Custom bidCpmAdjustment AND custom configuration for one bidder and inherit standard settings', function () { - $$PREBID_GLOBAL$$.bidderSettings = - { - appnexus: { - bidCpmAdjustment: function (bidCpm) { - return bidCpm * 0.7; - }, - adserverTargeting: [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - // change default here - return 15.00; - } - } - ] - }, - standard: { - adserverTargeting: [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - // change default here - return 10.00; - }, - }, - { - key: 'hb_size', - val: function (bidResponse) { - return bidResponse.size; - } - } - ] - - } - }; - - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': 15.0, - 'hb_size': '300x250' - }; - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - }); - - it('alwaysUseBid=true, sendStandardTargeting=false, and inherit custom', function () { - $$PREBID_GLOBAL$$.bidderSettings = - { - appnexus: { - alwaysUseBid: true, - sendStandardTargeting: false, - adserverTargeting: [ - { - key: 'hb_bidder', - val: function (bidResponse) { - return bidResponse.bidderCode; - } - }, { - key: 'hb_adid', - val: function (bidResponse) { - return bidResponse.adId; - } - }, { - key: 'hb_pb', - val: function (bidResponse) { - return bidResponse.pbHg; - } - } - ] - } - }; - - var expected = { - 'hb_bidder': bidderCode, - 'hb_adid': adId, - 'hb_pb': 5.57, - 'hb_size': '300x250' - }; - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - assert.equal(bid.alwaysUseBid, true); - assert.equal(bid.sendStandardTargeting, false); - }); - - it('suppressEmptyKeys=true', function() { - $$PREBID_GLOBAL$$.bidderSettings = - { - standard: { - suppressEmptyKeys: true, - adserverTargeting: [ - { - key: 'aKeyWithAValue', - val: 42 - }, - { - key: 'aKeyWithAnEmptyValue', - val: '' - } - ] - } - }; - - var expected = { - 'aKeyWithAValue': 42 - }; - - var response = bidmanager.getKeyValueTargetingPairs(bidderCode, bid); - assert.deepEqual(response, expected); - }); - }); - - describe('adjustBids', () => { - it('should adjust bids if greater than zero and pass copy of bid object', () => { - const bid = Object.assign({}, - bidfactory.createBid(2), - fixtures.getBidResponses()[5] - ); - - assert.equal(bid.cpm, 0.5); - - $$PREBID_GLOBAL$$.bidderSettings = - { - brealtime: { - bidCpmAdjustment: function (bidCpm, bidObj) { - assert.deepEqual(bidObj, bid); - if (bidObj.adUnitCode === 'negative') { - return bidCpm * -0.5; - } - if (bidObj.adUnitCode === 'zero') { - return 0; - } - return bidCpm * 0.5; - }, - }, - standard: { - adserverTargeting: [ - ] - } - }; - - // negative - bid.adUnitCode = 'negative'; - bidmanager.adjustBids(bid) - assert.equal(bid.cpm, 0.5); - - // positive - bid.adUnitCode = 'normal'; - bidmanager.adjustBids(bid) - assert.equal(bid.cpm, 0.25); - - // zero - bid.adUnitCode = 'zero'; - bidmanager.adjustBids(bid) - assert.equal(bid.cpm, 0); - - // reset bidderSettings so we don't mess up further tests - $$PREBID_GLOBAL$$.bidderSettings = {}; - }); - }); - - describe('addBidResponse', () => { - before(() => { - $$PREBID_GLOBAL$$.adUnits = fixtures.getAdUnits(); - }); - it('should return proper price bucket increments for dense mode', () => { - const bid = Object.assign({}, - bidfactory.createBid(2), - fixtures.getBidResponses()[5] - ); - - // 0 - 3 dollars - bid.cpm = '1.99'; - let expectedIncrement = '1.99'; - bidmanager.addBidResponse(bid.adUnitCode, bid); - // pop this bid because another test relies on global $$PREBID_GLOBAL$$._bidsReceived - let registeredBid = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(registeredBid.pbDg, expectedIncrement, '0 - 3 hits at to 1 cent increment'); - - // 3 - 8 dollars - bid.cpm = '4.39'; - expectedIncrement = '4.35'; - bidmanager.addBidResponse(bid.adUnitCode, bid); - registeredBid = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(registeredBid.pbDg, expectedIncrement, '3 - 8 hits at 5 cent increment'); - - // 8 - 20 dollars - bid.cpm = '19.99'; - expectedIncrement = '19.50'; - bidmanager.addBidResponse(bid.adUnitCode, bid); - registeredBid = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(registeredBid.pbDg, expectedIncrement, '8 - 20 hits at 50 cent increment'); - - // 20+ dollars - bid.cpm = '73.07'; - expectedIncrement = '20.00'; - bidmanager.addBidResponse(bid.adUnitCode, bid); - registeredBid = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(registeredBid.pbDg, expectedIncrement, '20+ caps at 20.00'); - }); - - it('should place dealIds in adserver targeting', () => { - const bid = Object.assign({}, - bidfactory.createBid(2), - fixtures.getBidResponses()[0] - ); - - bid.dealId = 'test deal'; - bidmanager.addBidResponse(bid.adUnitCode, bid); - const addedBid = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(addedBid.adserverTargeting[`hb_deal`], bid.dealId, 'dealId placed in adserverTargeting'); - }); - - it('should pass through default adserverTargeting sent from adapter', () => { - const bid = Object.assign({}, - bidfactory.createBid(2), - fixtures.getBidResponses()[0] - ); - - bid.adserverTargeting.extra = 'stuff'; - - bidmanager.addBidResponse(bid.adUnitCode, bid); - const addedBid = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(addedBid.adserverTargeting.hb_bidder, 'triplelift'); - assert.equal(addedBid.adserverTargeting.extra, 'stuff'); - }); - - it('should not alter bid adID', () => { - const bid1 = Object.assign({}, - bidfactory.createBid(2), - fixtures.getBidResponses()[1] - ); - const bid2 = Object.assign({}, - bidfactory.createBid(2), - fixtures.getBidResponses()[3] - ); - - bidmanager.addBidResponse(bid1.adUnitCode, Object.assign({}, bid1)); - bidmanager.addBidResponse(bid2.adUnitCode, Object.assign({}, bid2)); - - const addedBid2 = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(addedBid2.adId, bid2.adId); - const addedBid1 = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(addedBid1.adId, bid1.adId); - }); - - it('should not add banner bids that have no width or height', () => { - const bid = Object.assign({}, - bidfactory.createBid(1), - { - width: undefined, - height: undefined - } - ); - - bidmanager.addBidResponse('adUnitCode', bid); - - const addedBid = $$PREBID_GLOBAL$$._bidsReceived[$$PREBID_GLOBAL$$._bidsReceived.length - 1]; - - assert.notEqual(bid.adId, addedBid.adId); - }); - - it('should add banner bids that have no width or height but single adunit size', () => { - sinon.stub(utils, 'getBidderRequest', () => ({ - start: timestamp(), - bids: [{ - sizes: [[300, 250]], - }] - })); - - const bid = Object.assign({}, - bidfactory.createBid(1), - { - width: undefined, - height: undefined - } - ); - - bidmanager.addBidResponse('adUnitCode', bid); - - const addedBid = $$PREBID_GLOBAL$$._bidsReceived[$$PREBID_GLOBAL$$._bidsReceived.length - 1]; - - assert.equal(bid.adId, addedBid.adId); - assert.equal(addedBid.width, 300); - assert.equal(addedBid.height, 250); - - utils.getBidderRequest.restore(); - }); - - it('should not add native bids that do not have required assets', () => { - sinon.stub(utils, 'getBidRequest', () => ({ - start: timestamp(), - bidder: 'appnexusAst', - mediaTypes: { - native: { - title: {required: true}, - } - }, - })); - - const bid = Object.assign({}, - bidfactory.createBid(1), - { - bidderCode: 'appnexusAst', - mediaType: 'native', - native: {title: undefined} - } - ); - - const bidsRecCount = $$PREBID_GLOBAL$$._bidsReceived.length; - bidmanager.addBidResponse('adUnit-code', bid); - assert.equal(bidsRecCount, $$PREBID_GLOBAL$$._bidsReceived.length); - - utils.getBidRequest.restore(); - }); - - it('should add native bids that do have required assets', () => { - const bidRequest = () => ({ - start: timestamp(), - bidder: 'appnexusAst', - mediaTypes: { - native: { - title: {required: true}, - } - }, - }); - sinon.stub(utils, 'getBidRequest', bidRequest); - sinon.stub(utils, 'getBidderRequest', bidRequest); - - const bid = Object.assign({}, - bidfactory.createBid(1), - { - bidderCode: 'appnexusAst', - mediaType: 'native', - native: { - title: 'foo', - clickUrl: 'example.link' - } - } - ); - - const bidsRecCount = $$PREBID_GLOBAL$$._bidsReceived.length; - bidmanager.addBidResponse('adUnit-code', bid); - assert.equal(bidsRecCount + 1, $$PREBID_GLOBAL$$._bidsReceived.length); - - utils.getBidRequest.restore(); - utils.getBidderRequest.restore(); - }); - - it('installs publisher-defined renderers on bids', () => { - sinon.stub(utils, 'getBidderRequest', () => ({ - start: timestamp(), - bids: [{ - renderer: { - url: 'renderer.js', - render: (bid) => bid - } - }] - })); - - const bid = Object.assign({}, bidfactory.createBid(1), { - bidderCode: 'appnexusAst', - mediaType: 'video-outstream', - }); - - bidmanager.addBidResponse('adUnit-code', bid); - const addedBid = $$PREBID_GLOBAL$$._bidsReceived.pop(); - assert.equal(addedBid.renderer.url, 'renderer.js'); - - utils.getBidderRequest.restore(); - }); - - it('requires a renderer on outstream bids', () => { - const bidRequest = () => ({ - start: timestamp(), - bidder: 'appnexusAst', - mediaTypes: { - video: {context: 'outstream'} - }, - }); - - sinon.stub(utils, 'getBidRequest', bidRequest); - sinon.stub(utils, 'getBidderRequest', bidRequest); - - const bid = Object.assign({}, - bidfactory.createBid(1), - { - bidderCode: 'appnexusAst', - mediaType: 'video', - renderer: {render: () => true, url: 'render.js'}, - } - ); - - const bidsRecCount = $$PREBID_GLOBAL$$._bidsReceived.length; - bidmanager.addBidResponse('adUnit-code', bid); - assert.equal(bidsRecCount + 1, $$PREBID_GLOBAL$$._bidsReceived.length); - - utils.getBidRequest.restore(); - utils.getBidderRequest.restore(); - }); - }); -}); diff --git a/test/spec/config_spec.js b/test/spec/config_spec.js index e99e739d630..342319b472f 100644 --- a/test/spec/config_spec.js +++ b/test/spec/config_spec.js @@ -10,16 +10,19 @@ let setDefaults; describe('config API', () => { let logErrorSpy; + let logWarnSpy; beforeEach(() => { const config = newConfig(); getConfig = config.getConfig; setConfig = config.setConfig; setDefaults = config.setDefaults; logErrorSpy = sinon.spy(utils, 'logError'); + logWarnSpy = sinon.spy(utils, 'logWarn'); }); afterEach(() => { utils.logError.restore(); + utils.logWarn.restore(); }); it('setConfig is a function', () => { @@ -59,34 +62,16 @@ describe('config API', () => { expect(getConfig('debug')).to.be.true; }); - // remove test when @deprecated $$PREBID_GLOBAL$$.logging removed - it('gets legacy logging in deprecation window', () => { - $$PREBID_GLOBAL$$.logging = false; - expect(getConfig('debug')).to.equal(false); - }); - it('sets bidderTimeout', () => { setConfig({ bidderTimeout: 1000 }); expect(getConfig('bidderTimeout')).to.be.equal(1000); }); - // remove test when @deprecated $$PREBID_GLOBAL$$.bidderTimeout removed - it('gets legacy bidderTimeout in deprecation window', () => { - $$PREBID_GLOBAL$$.bidderTimeout = 5000; - expect(getConfig('bidderTimeout')).to.equal(5000); - }); - it('gets user-defined publisherDomain', () => { setConfig({ publisherDomain: 'fc.kahuna' }); expect(getConfig('publisherDomain')).to.equal('fc.kahuna'); }); - // remove test when @deprecated $$PREBID_GLOBAL$$.publisherDomain removed - it('gets legacy publisherDomain in deprecation window', () => { - $$PREBID_GLOBAL$$.publisherDomain = 'ad.example.com'; - expect(getConfig('publisherDomain')).to.equal('ad.example.com'); - }); - it('gets default userSync config', () => { const DEFAULT_USERSYNC = { syncEnabled: true, @@ -169,4 +154,15 @@ describe('config API', () => { const error = 'Prebid Error: no value passed to `setPriceGranularity()`'; assert.ok(logErrorSpy.calledWith(error), 'expected error was logged'); }); + + it('should log a warning on invalid values', () => { + setConfig({ bidderSequence: 'unrecognized sequence' }); + expect(logWarnSpy.calledOnce).to.equal(true); + }); + + it('should not log warnings when given recognized values', () => { + setConfig({ bidderSequence: 'fixed' }); + setConfig({ bidderSequence: 'random' }); + expect(logWarnSpy.called).to.equal(false); + }); }); diff --git a/test/spec/e2e/gpt-examples/gpt_outstream.html b/test/spec/e2e/gpt-examples/gpt_outstream.html index 2230248886b..42ba48c98e7 100644 --- a/test/spec/e2e/gpt-examples/gpt_outstream.html +++ b/test/spec/e2e/gpt-examples/gpt_outstream.html @@ -45,7 +45,7 @@ mediaType: 'video-outstream', bids: [ { - bidder: 'appnexusAst', + bidder: 'appnexus', params: { placementId: '5768085', video: { @@ -62,7 +62,7 @@ mediaType: 'video-outstream', bids: [ { - bidder: 'appnexusAst', + bidder: 'appnexus', params: { placementId: '5768085', video: { diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index edb9958ae66..4754e4d1fa5 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -1,12 +1,21 @@ +const { userSync } = require('../../../src/userSync'); +const { config } = require('../../../src/config'); + const { expect } = require('chai'); -const utils = require('../../../src/utils'); -const { isBidRequestValid, buildRequests, interpretResponse, getUserSyncs } = require('../../../modules/33acrossBidAdapter'); + +const { + isBidRequestValid, + buildRequests, + interpretResponse, + getUserSyncs +} = require('../../../modules/33acrossBidAdapter'); describe('33acrossBidAdapter:', function () { const BIDDER_CODE = '33across'; const SITE_ID = 'pub1234'; const PRODUCT_ID = 'product1'; const END_POINT = 'https://ssc.33across.com/api/v1/hb'; + const SYNC_ENDPOINT = 'https://de.tynt.com/deb/v2?m=xch'; beforeEach(function() { this.bidRequests = [ @@ -21,12 +30,12 @@ describe('33acrossBidAdapter:', function () { adUnitCode: 'div-id', requestId: 'r1', sizes: [ - [300, 250], - [728, 90] + [ 300, 250 ], + [ 728, 90 ] ], transactionId: 't1' } - ] + ]; this.sandbox = sinon.sandbox.create(); }); @@ -113,7 +122,7 @@ describe('33acrossBidAdapter:', function () { describe('buildRequests:', function() { it('returns corresponding server requests for each valid bidRequest', function() { const ttxRequest = { - imp: [{ + imp: [ { banner: { format: [ { @@ -133,7 +142,7 @@ describe('33acrossBidAdapter:', function () { prod: PRODUCT_ID } } - }], + } ], site: { id: SITE_ID }, @@ -149,23 +158,19 @@ describe('33acrossBidAdapter:', function () { } } const builtServerRequests = buildRequests(this.bidRequests); - expect(builtServerRequests).to.deep.equal([serverRequest]); + expect(builtServerRequests).to.deep.equal([ serverRequest ]); expect(builtServerRequests.length).to.equal(1); }); - it('returns corresponding server requests for each valid test bidRequest', function() { - delete this.bidRequests[0].params.siteId; - this.bidRequests[0].params.site = { - id: SITE_ID, - page: 'http://test-url.com' - } - this.bidRequests[0].params.customHeaders = { - foo: 'bar' - }; - this.bidRequests[0].params.url = '//staging-ssc.33across.com/api/v1/hb'; + it('returns corresponding test server requests for each valid bidRequest', function() { + this.sandbox.stub(config, 'getConfig', () => { + return { + 'url': 'https://foo.com/hb/' + } + }); const ttxRequest = { - imp: [{ + imp: [ { banner: { format: [ { @@ -185,28 +190,24 @@ describe('33acrossBidAdapter:', function () { prod: PRODUCT_ID } } - }], + } ], site: { - id: SITE_ID, - page: 'http://test-url.com' + id: SITE_ID }, id: 'b1' }; const serverRequest = { method: 'POST', - url: '//staging-ssc.33across.com/api/v1/hb', + url: 'https://foo.com/hb/', data: JSON.stringify(ttxRequest), options: { contentType: 'application/json', - withCredentials: false, - customHeaders: { - foo: 'bar' - } + withCredentials: false } }; const builtServerRequests = buildRequests(this.bidRequests); - expect(builtServerRequests).to.deep.equal([serverRequest]); + expect(builtServerRequests).to.deep.equal([ serverRequest ]); expect(builtServerRequests.length).to.equal(1); }); @@ -216,6 +217,46 @@ describe('33acrossBidAdapter:', function () { }); describe('interpretResponse', function() { + beforeEach(function() { + this.ttxRequest = { + imp: [ { + banner: { + format: [ + { + w: 300, + h: 250, + ext: {} + }, + { + w: 728, + h: 90, + ext: {} + } + ] + }, + ext: { + ttx: { + prod: PRODUCT_ID + } + } + } ], + site: { + id: SITE_ID, + page: 'http://test-url.com' + }, + id: 'b1' + }; + this.serverRequest = { + method: 'POST', + url: '//staging-ssc.33across.com/api/v1/hb', + data: JSON.stringify(this.ttxRequest), + options: { + contentType: 'application/json', + withCredentials: false + } + }; + }); + context('when exactly one bid is returned', function() { it('interprets and returns the single bid response', function() { const serverResponse = { @@ -224,7 +265,7 @@ describe('33acrossBidAdapter:', function () { id: 'b1', seatbid: [ { - bid: [{ + bid: [ { id: '1', adm: '

I am an ad

', ext: { @@ -235,7 +276,7 @@ describe('33acrossBidAdapter:', function () { h: 250, w: 300, price: 0.0938 - }] + } ] } ] }; @@ -253,7 +294,7 @@ describe('33acrossBidAdapter:', function () { netRevenue: true } - expect(interpretResponse({body: serverResponse})).to.deep.equal([bidResponse]); + expect(interpretResponse({ body: serverResponse }, this.serverRequest)).to.deep.equal([ bidResponse ]); }); }); @@ -266,7 +307,7 @@ describe('33acrossBidAdapter:', function () { seatbid: [] }; - expect(interpretResponse({body: serverResponse})).to.deep.equal([]); + expect(interpretResponse({ body: serverResponse }, this.serverRequest)).to.deep.equal([]); }); }); @@ -278,7 +319,7 @@ describe('33acrossBidAdapter:', function () { id: 'b1', seatbid: [ { - bid: [{ + bid: [ { id: '1', adm: '

I am an ad

', ext: { @@ -305,7 +346,7 @@ describe('33acrossBidAdapter:', function () { ] }, { - bid: [{ + bid: [ { id: '3', adm: '

I am an ad

', ext: { @@ -316,7 +357,7 @@ describe('33acrossBidAdapter:', function () { h: 250, w: 300, price: 0.0938 - }] + } ] } ] }; @@ -334,109 +375,46 @@ describe('33acrossBidAdapter:', function () { netRevenue: true } - expect(interpretResponse({body: serverResponse})).to.deep.equal([bidResponse]); + expect(interpretResponse({ body: serverResponse }, this.serverRequest)).to.deep.equal([ bidResponse ]); }); }); - }); - - describe('getUserSyncs', function() { - beforeEach(function() { - this.ttxBids = [ - { - params: { - siteId: 'id1', - productId: 'p1' - } - }, - { - params: { - siteId: 'id2', - productId: 'p1' - } - } - ]; - this.testTTXBids = [ - { - params: { - site: { id: 'id1' }, - productId: 'p1', - syncUrl: 'https://staging-de.tynt.com/deb/v2?m=xch' - } - }, - { - params: { - site: { id: 'id2' }, - productId: 'p1', - syncUrl: 'https://staging-de.tynt.com/deb/v2?m=xch' - } + context('and register user sync', function() { + it('via the production endpoint', function() { + const spy = this.sandbox.spy(userSync, 'registerSync'); + const serverResponse = { + cur: 'USD', + ext: {}, + id: 'b1', + seatbid: [] } - ]; + interpretResponse({ body: serverResponse }, this.serverRequest); + const syncUrl = `${SYNC_ENDPOINT}&id=${this.ttxRequest.site.id}`; - this.syncs = [ - { - type: 'iframe', - url: 'https://de.tynt.com/deb/v2?m=xch&id=id1' - }, - { - type: 'iframe', - url: 'https://de.tynt.com/deb/v2?m=xch&id=id2' - }, - ]; - - this.testSyncs = [ - { - type: 'iframe', - url: 'https://staging-de.tynt.com/deb/v2?m=xch&id=id1' - }, - { - type: 'iframe', - url: 'https://staging-de.tynt.com/deb/v2?m=xch&id=id2' - }, - ]; - }); - - context('when iframe is not enabled', function() { - it('returns empty sync array', function() { - this.sandbox.stub(utils, 'getBidderRequestAllAdUnits', () => ( - { - bids: this.ttxBids - } - )); - const syncOptions = {}; - expect(getUserSyncs(syncOptions)).to.deep.equal([]); + const registerSyncCalled = spy.calledWith('iframe', '33across', syncUrl); + expect(registerSyncCalled).to.be.true; }); - }); - context('when iframe is enabled', function() { - it('returns sync array equal to number of bids for ttx', function() { - this.sandbox.stub(utils, 'getBidderRequestAllAdUnits', () => ( - { - bids: this.ttxBids - } - )); + it('via the test endpoint', function() { + const spy = this.sandbox.spy(userSync, 'registerSync'); - const syncOptions = { - iframeEnabled: true - }; - const syncs = getUserSyncs(syncOptions); - expect(syncs.length).to.equal(this.ttxBids.length); - expect(syncs).to.deep.equal(this.syncs); - }); - - it('returns sync array equal to number of test bids for ttx', function() { - this.sandbox.stub(utils, 'getBidderRequestAllAdUnits', () => ( - { - bids: this.testTTXBids + this.sandbox.stub(config, 'getConfig', () => { + return { + 'syncUrl': 'https://foo.com/deb/v2?m=xch' } - )); + }); - const syncOptions = { - iframeEnabled: true - }; - const syncs = getUserSyncs(syncOptions); - expect(syncs.length).to.equal(this.testTTXBids.length); - expect(syncs).to.deep.equal(this.testSyncs); + const serverResponse = { + cur: 'USD', + ext: {}, + id: 'b1', + seatbid: [] + } + interpretResponse({ body: serverResponse }, this.serverRequest); + const syncUrl = `https://foo.com/deb/v2?m=xch&id=${this.ttxRequest.site.id}`; + + const registerSyncCalled = spy.calledWith('iframe', '33across', syncUrl); + expect(registerSyncCalled).to.be.true; }); }); }); diff --git a/test/spec/modules/aardvarkBidAdapter_spec.js b/test/spec/modules/aardvarkBidAdapter_spec.js deleted file mode 100644 index 12a47fc946d..00000000000 --- a/test/spec/modules/aardvarkBidAdapter_spec.js +++ /dev/null @@ -1,240 +0,0 @@ -describe('aardvark adapter tests', function () { - const expect = require('chai').expect; - const Adapter = require('modules/aardvarkBidAdapter'); - const bidmanager = require('src/bidmanager'); - const adloader = require('src/adloader'); - const constants = require('src/constants.json'); - - var aardvark, - sandbox, - bidsRequestedOriginal; - - const bidderRequest = { - bidderCode: 'aardvark', - bids: [ - { - bidId: 'bidId1', - bidder: 'aardvark', - placementCode: 'foo', - sizes: [[728, 90]], - rtkid: 1, - params: { - ai: 'AH5S', - sc: 'BirH' - } - }, - { - bidId: 'bidId2', - bidder: 'aardvark', - placementCode: 'bar', - sizes: [[300, 600]], - rtkid: 1, - params: { - ai: 'AH5S', - sc: '661h' - } - } - ] - }, - - bidderRequestCustomHost = { - bidderCode: 'aardvark', - bids: [ - { - bidId: 'bidId1', - bidder: 'aardvark', - placementCode: 'foo', - sizes: [[728, 90]], - rtkid: 1, - params: { - ai: 'AH5S', - sc: 'BirH', - host: 'custom.server.com' - } - }, - { - bidId: 'bidId2', - bidder: 'aardvark', - placementCode: 'bar', - sizes: [[300, 600]], - rtkid: 1, - params: { - ai: 'AH5S', - sc: '661h', - host: 'custom.server.com' - } - } - ] - }, - - // respond - bidderResponse = [ - { - 'adm': '
', - 'cpm': 0.39440, - 'ex': '', - 'height': '90', - 'id': 'BirH', - 'nurl': '', - 'width': '728', - 'cid': 'bidId1' - }, - { - 'adm': '
', - 'cpm': 0.03485, - 'ex': '', - 'height': '600', - 'id': '661h', - 'nurl': '', - 'width': '300', - 'cid': 'bidId2' - } - ]; - - beforeEach(() => { - aardvark = new Adapter(); - sandbox = sinon.sandbox.create(); - bidsRequestedOriginal = $$PREBID_GLOBAL$$._bidsRequested; - $$PREBID_GLOBAL$$._bidsRequested = []; - }); - - afterEach(() => { - sandbox.restore(); - - $$PREBID_GLOBAL$$._bidsRequested = bidsRequestedOriginal; - }); - - describe('callBids', () => { - beforeEach(() => { - sandbox.stub(adloader, 'loadScript'); - aardvark.callBids(bidderRequest); - }); - it('should load script', () => { - sinon.assert.calledOnce(adloader.loadScript); - expect(adloader.loadScript.firstCall.args[0]).to.eql( - '//thor.rtk.io/AH5S/BirH_661h/aardvark/?jsonp=$$PREBID_GLOBAL$$.aardvarkResponse&rtkreferer=localhost:9876&BirH=bidId1&661h=bidId2'); - }); - }); - - describe('callBids with custom host', () => { - beforeEach(() => { - sandbox.stub(adloader, 'loadScript'); - aardvark.callBids(bidderRequestCustomHost); - }); - it('should load script', () => { - sinon.assert.calledOnce(adloader.loadScript); - expect(adloader.loadScript.firstCall.args[0]).to.eql( - '//custom.server.com/AH5S/BirH_661h/aardvark/?jsonp=$$PREBID_GLOBAL$$.aardvarkResponse&rtkreferer=localhost:9876&BirH=bidId1&661h=bidId2'); - }); - }); - - describe('aardvarkResponse', () => { - it('should exist and be a function', () => { - expect($$PREBID_GLOBAL$$.aardvarkResponse).to.exist.and.to.be.a('function'); - }); - }); - - describe('add empty bids if no bid returned', () => { - let firstBid; - let secondBid; - - beforeEach(() => { - sandbox.stub(bidmanager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - aardvark.callBids(bidderRequest); - - $$PREBID_GLOBAL$$.aardvarkResponse([]); - - firstBid = bidmanager.addBidResponse.firstCall.args[1]; - secondBid = bidmanager.addBidResponse.secondCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledTwice(bidmanager.addBidResponse); - }); - - it('should have an error statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(constants.STATUS.NO_BID); - expect(secondBid.getStatusCode()).to.eql(constants.STATUS.NO_BID); - }); - - it('should include bid request bidId as the adId', () => { - expect(firstBid).to.have.property('adId', 'bidId1'); - expect(secondBid).to.have.property('adId', 'bidId2'); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidmanager.addBidResponse.firstCall.args[0]; - let secondPlacementCode = bidmanager.addBidResponse.secondCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - expect(secondPlacementCode).to.eql('bar'); - }); - - it('should add the bidder code to the bid object', () => { - expect(firstBid).to.have.property('bidderCode', 'aardvark'); - expect(secondBid).to.have.property('bidderCode', 'aardvark'); - }); - }); - - describe('add bids to the manager', () => { - let firstBid; - let secondBid; - - beforeEach(() => { - sandbox.stub(bidmanager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - aardvark.callBids(bidderRequest); - - $$PREBID_GLOBAL$$.aardvarkResponse(bidderResponse); - firstBid = bidmanager.addBidResponse.firstCall.args[1]; - secondBid = bidmanager.addBidResponse.secondCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledTwice(bidmanager.addBidResponse); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidmanager.addBidResponse.firstCall.args[0]; - let secondPlacementCode = bidmanager.addBidResponse.secondCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - expect(secondPlacementCode).to.eql('bar'); - }); - - it('should include bid request bidId as the adId', () => { - expect(firstBid).to.have.property('adId', 'bidId1'); - expect(secondBid).to.have.property('adId', 'bidId2'); - }); - - it('should have a good statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(constants.STATUS.GOOD); - expect(secondBid.getStatusCode()).to.eql(constants.STATUS.GOOD); - }); - - it('should add the CPM to the bid object', () => { - expect(firstBid).to.have.property('cpm', 0.39440); - expect(secondBid).to.have.property('cpm', 0.03485); - }); - - it('should add the bidder code to the bid object', () => { - expect(firstBid).to.have.property('bidderCode', 'aardvark'); - expect(secondBid).to.have.property('bidderCode', 'aardvark'); - }); - - it('should include the ad to the bid object', () => { - expect(firstBid).to.have.property('ad'); - expect(secondBid).to.have.property('ad'); - }); - - it('should include the size to the bid object', () => { - expect(firstBid).to.have.property('width', 728); - expect(firstBid).to.have.property('height', 90); - expect(secondBid).to.have.property('width', 300); - expect(secondBid).to.have.property('height', 600); - }); - }); -}); diff --git a/test/spec/modules/adbladeBidAdapter_spec.js b/test/spec/modules/adbladeBidAdapter_spec.js deleted file mode 100644 index ec3c9f6b23e..00000000000 --- a/test/spec/modules/adbladeBidAdapter_spec.js +++ /dev/null @@ -1,206 +0,0 @@ -import {expect} from 'chai'; -import Adapter from '../../../modules/adbladeBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; - -describe('adblade adapter', () => { - 'use strict'; - - let bidsRequestedOriginal; - let adapter; - let sandbox; - - const bidderRequest = { - bidderCode: 'adblade', - bids: [ - { - bidId: 'bidId1', - bidder: 'adblade', - placementCode: 'foo', - sizes: [[728, 90]], - params: { - partnerId: 1, - } - } - ] - }; - - beforeEach(() => { - bidsRequestedOriginal = $$PREBID_GLOBAL$$._bidsRequested; - $$PREBID_GLOBAL$$._bidsRequested = []; - - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - - $$PREBID_GLOBAL$$._bidsRequested = bidsRequestedOriginal; - }); - - describe('sizes', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - }); - - let bidderRequest = { - bidderCode: 'adblade', - bids: [ - { - bidId: 'bidId1', - bidder: 'adblade', - placementCode: 'foo', - sizes: [[728, 90], [300, 250]], - params: { - partnerId: 1, - } - } - ] - }; - - it('array of arrays', () => { - adapter.callBids(bidderRequest); - sinon.assert.calledTwice(adLoader.loadScript); - - expect(adLoader.loadScript.firstCall.args[0]).to.include('%22banner%22%3A%7B%22w%22%3A728%2C%22h%22%3A90%7D%2C'); // banner:{w:728, h:90} - expect(adLoader.loadScript.firstCall.args[0]).to.include('adblade.com'); - expect(adLoader.loadScript.firstCall.args[0]).to.include('prebidjs'); - - expect(adLoader.loadScript.secondCall.args[0]).to.include('%22banner%22%3A%7B%22w%22%3A300%2C%22h%22%3A250%7D%2C'); // banner:{w:300, h:250} - expect(adLoader.loadScript.secondCall.args[0]).to.include('adblade.com'); - expect(adLoader.loadScript.secondCall.args[0]).to.include('prebidjs'); - }); - - it('array of strings', () => { - bidderRequest.bids[0].sizes = [728, 90]; - adapter.callBids(bidderRequest); - sinon.assert.calledOnce(adLoader.loadScript); - - expect(adLoader.loadScript.firstCall.args[0]).to.include('%22banner%22%3A%7B%22w%22%3A728%2C%22h%22%3A90%7D%2C'); // banner:{w:728, h:90} - expect(adLoader.loadScript.firstCall.args[0]).to.include('adblade.com'); - expect(adLoader.loadScript.firstCall.args[0]).to.include('prebidjs'); - }); - }); - - describe('callBids', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(bidderRequest); - }); - - it('should load script', () => { - sinon.assert.calledOnce(adLoader.loadScript); - - expect(adLoader.loadScript.firstCall.args[0]).to.include('adblade.com'); - expect(adLoader.loadScript.firstCall.args[0]).to.include('prebidjs'); - }); - }); - - describe('adbladeResponse', () => { - it('should exist and be a function', () => { - expect($$PREBID_GLOBAL$$.adbladeResponse).to.exist.and.to.be.a('function'); - }); - }); - - describe('add bids to the manager', () => { - let firstBid; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // respond - let bidderReponse = { - 'cur': 'USD', - 'id': '03a9404f-7b39-4d04-b50b-6459b9aa3ffa', - 'seatbid': [ - { - 'seat': '1', - 'bid': [ - { - 'nurl': 'http://example.com', - 'crid': '20063', - 'adomain': [ - 'www.adblade.com' - ], - 'price': 3, - 'w': 728, - 'h': 90, - 'id': '1', - 'adm': '
', - 'impid': 'bidId1', - 'cid': '99' - } - ] - } - ] - }; - $$PREBID_GLOBAL$$.adbladeResponse(bidderReponse); - - firstBid = bidManager.addBidResponse.firstCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledOnce(bidManager.addBidResponse); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidManager.addBidResponse.firstCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - }); - - it('should have a good statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(1); - }); - - it('should add the CPM to the bid object', () => { - expect(firstBid).to.have.property('cpm', 3); - }); - - it('should include the ad to the bid object', () => { - expect(firstBid).to.have.property('ad'); - }); - - it('should include the size to the bid object', () => { - expect(firstBid).to.have.property('width', 728); - expect(firstBid).to.have.property('height', 90); - }); - }); - - describe('add empty bids if no bid returned', () => { - let firstBid; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // respond - let bidderReponse = {}; - $$PREBID_GLOBAL$$.adbladeResponse(bidderReponse); - - firstBid = bidManager.addBidResponse.firstCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledOnce(bidManager.addBidResponse); - }); - - it('should have an error statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(2); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidManager.addBidResponse.firstCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - }); - - it('should add the bidder code to the bid object', () => { - expect(firstBid).to.have.property('bidderCode', 'adblade'); - }); - }); -}); diff --git a/test/spec/modules/adbundBidAdapter_spec.js b/test/spec/modules/adbundBidAdapter_spec.js deleted file mode 100644 index da9b2e2e9b9..00000000000 --- a/test/spec/modules/adbundBidAdapter_spec.js +++ /dev/null @@ -1,94 +0,0 @@ -import { expect } from 'chai'; -import Adapter from '../../../modules/adbundBidAdapter'; -import bidManager from 'src/bidmanager'; -import CONSTANTS from 'src/constants.json'; - -describe('adbund adapter tests', function () { - let sandbox; - let adapter; - let server; - - const request = { - bidderCode: 'adbund', - bids: [{ - bidder: 'adbund', - params: { - sid: '110238', - bidfloor: 0.036 - }, - placementCode: 'adbund', - sizes: [[300, 250]], - bidId: 'adbund_bidId', - bidderRequestId: 'adbund_bidderRequestId', - requestId: 'adbund_requestId' - }] - }; - - const response = { - bidderCode: 'adbund', - cpm: 1.06, - height: 250, - width: 300 - }; - - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('adbund callBids validation', () => { - beforeEach(() => { - adapter = new Adapter(); - }); - - afterEach(() => { - }); - - it('Valid bid-request', () => { - let bidderRequest; - - sandbox.stub(adapter, 'callBids'); - adapter.callBids(request); - - bidderRequest = adapter.callBids.getCall(0).args[0]; - - expect(bidderRequest).to.have.property('bids') - .that.is.an('array') - .with.lengthOf(1); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .to.have.property('bidder', 'adbund'); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('sizes') - .that.is.an('array') - .with.lengthOf(1) - .that.deep.equals(request.bids[0].sizes); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('params') - .to.have.property('bidfloor', 0.036); - }); - - it('Valid bid-response', () => { - var bidderResponse; - - sandbox.stub(bidManager, 'addBidResponse'); - adapter.callBids(request); - bidderResponse = bidManager.addBidResponse.getCall(0) || - bidManager.addBidResponse.getCall(1); - - if (bidderResponse && bidderResponse.args && bidderResponse.args[1]) { - bidderResponse = bidderResponse.args[1]; - expect(bidderResponse.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bidderResponse.bidderCode).to.equal(response.bidderCode); - expect(bidderResponse.width).to.equal(response.width); - expect(bidderResponse.height).to.equal(response.height); - expect(bidderResponse.cpm).to.equal(response.cpm); - } - }); - }); -}); diff --git a/test/spec/modules/adformBidAdapter_spec.js b/test/spec/modules/adformBidAdapter_spec.js deleted file mode 100644 index fa137110ba8..00000000000 --- a/test/spec/modules/adformBidAdapter_spec.js +++ /dev/null @@ -1,198 +0,0 @@ -import { assert } from 'chai'; -import * as utils from 'src/utils'; -import adLoader from 'src/adloader'; -import bidManager from 'src/bidmanager'; -import AdformAdapter from 'modules/adformBidAdapter'; - -describe('Adform adapter', () => { - let _adformAdapter, sandbox; - - describe('request', () => { - it('should create callback method on PREBID_GLOBAL', () => { - assert.typeOf($$PREBID_GLOBAL$$._adf_callback, 'function'); - }); - - it('should pass multiple bids via single request', () => { - const _request = adLoader.loadScript; - - assert(_request.calledOnce); - assert.lengthOf(_request.args[0], 1); - assert.lengthOf(parseUrl(_request.args[0][0]).items, 3); - }); - - it('should handle global request parameters', () => { - const _request = parseUrl(adLoader.loadScript.args[0][0]); - const _query = _request.query; - - assert.equal(_request.path, '//newdomain/adx'); - assert.equal(_query.callback.split('.')[1], '_adf_callback'); - assert.equal(_query.tid, 145); - assert.equal(_query.rp, 4); - assert.equal(_query.fd, 1); - assert.equal(_query.auctionId, '4db6ddaa-ec86-459e-99aa-f7ffe940c473'); - assert.equal(_query.url, encodeURIComponent('some// there')); - }); - - it('should correctly form bid items', () => { - const _items = parseUrl(adLoader.loadScript.args[0][0]).items; - - assert.deepEqual(_items[0], { mid: '1', transactionId: 'transactionId' }); - assert.deepEqual(_items[1], { mid: '2', someVar: 'someValue', transactionId: 'transactionId' }); - assert.deepEqual(_items[2], { mid: '3', pdom: 'home', transactionId: 'transactionId' }); - }); - }); - - describe('response callback', () => { - it('should create bid response item for every requested item', () => { - assert(bidManager.addBidResponse.calledThrice); - }); - - it('should correctly form bid response object', () => { - const _bid = bidManager.addBidResponse.firstCall.args; - const _bidObject = _bid[1]; - - assert.equal(_bid[0], 'code-1'); - assert.equal(_bidObject.statusMessage, 'Bid available'); - assert.equal(_bidObject.bidderCode, 'adform'); - assert.equal(_bidObject.cpm, 1.1); - assert.equal(_bidObject.cur, 'EUR'); - assert.equal(_bidObject.ad, ''); - assert.equal(_bidObject.width, 90); - assert.equal(_bidObject.height, 90); - assert.equal(_bidObject.dealId, 'deal-1'); - assert.equal(_bidObject.transactionId, 'transactionId'); - }); - - it('should correctly form empty bid response object', () => { - const _bid = bidManager.addBidResponse.secondCall.args; - const _bidObject = _bid[1]; - - assert.equal(_bid[0], 'code-2'); - assert.equal(_bidObject.statusMessage, 'Bid returned empty or error response'); - assert.equal(_bidObject.bidderCode, 'adform'); - }); - - it('should filter out item which does not fit required size', () => { - const _bid = bidManager.addBidResponse.thirdCall.args; - const _bidObject = _bid[1]; - - assert.equal(_bid[0], 'code-3'); - assert.equal(_bidObject.statusMessage, 'Bid returned empty or error response'); - assert.equal(_bidObject.bidderCode, 'adform'); - }); - - it('should correctly set bid response adId', () => { - const addResponse = bidManager.addBidResponse; - assert.equal('abc', addResponse.getCall(0).args[1].adId); - assert.equal('123', addResponse.getCall(1).args[1].adId); - assert.equal('a1b', addResponse.getCall(2).args[1].adId); - }); - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - $$PREBID_GLOBAL$$._adf_callback([ - { - response: 'banner', - width: 90, - height: 90, - banner: '', - win_bid: 1.1, - win_cur: 'EUR', - deal_id: 'deal-1' - }, - {}, - { - response: 'banner', - width: 50, - height: 50, - banner: '' - } - ]); - }); - }); - - beforeEach(() => { - var transactionId = 'transactionId'; - _adformAdapter = new AdformAdapter(); - utils.getUniqueIdentifierStr = () => 'callback'; - sandbox = sinon.sandbox.create(); - sandbox.stub(adLoader, 'loadScript'); - _adformAdapter.callBids({ - bidderRequestId: '1a2b3c', - requestId: '4db6ddaa-ec86-459e-99aa-f7ffe940c473', - bids: [ - { - bidId: 'abc', - placementCode: 'code-1', - sizes: [ [ 100, 100], [ 90, 90 ] ], - params: { - mid: 1, - url: 'some// there' - }, - adxDomain: 'newdomain', - tid: 45, - transactionId: transactionId - }, - { - bidId: '123', - placementCode: 'code-2', - sizes: [ [ 100, 100] ], - params: { - mid: 2, - tid: 145, - someVar: 'someValue' - }, - transactionId: transactionId - }, - { - bidId: 'a1b', - placementCode: 'code-3', - sizes: [ [ 50, 40], [ 40, 50 ] ], - params: { - mid: 3, - pdom: 'home' - }, - transactionId: transactionId - } - ]}); - }); - - afterEach(() => { - sandbox.restore(); - }); -}); - -function parseUrl(url) { - const parts = url.split('/'); - const query = parts.pop().split('&'); - return { - path: parts.join('/'), - items: query - .filter((i) => !~i.indexOf('=')) - .map((i) => fromBase64(i) - .split('&') - .reduce(toObject, {})), - query: query - .filter((i) => ~i.indexOf('=')) - .map((i) => i.replace('?', '')) - .reduce(toObject, {}) - }; -} - -function fromBase64(input) { - const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'.split(''); - let bc = 0, bs, buffer, idx = 0, output = ''; - for (; buffer = input.charAt(idx++); - ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer, - bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0 - ) { - buffer = chars.indexOf(buffer); - } - return output; -} - -function toObject(cache, string) { - const keyValue = string.split('='); - cache[keyValue[0]] = keyValue[1]; - return cache; -} diff --git a/test/spec/modules/admixerBidAdapter_spec.js b/test/spec/modules/admixerBidAdapter_spec.js deleted file mode 100644 index 0b66f8a9469..00000000000 --- a/test/spec/modules/admixerBidAdapter_spec.js +++ /dev/null @@ -1,244 +0,0 @@ -var chai = require('chai'); -var Adapter = require('modules/admixerBidAdapter')(); -var Ajax = require('src/ajax'); -var bidmanager = require('src/bidmanager.js'); -var CONSTANTS = require('src/constants.json'); - -describe('Admixer adapter', function () { - var validData_1 = { - bids: [ - { - bidder: 'admixer', - bidId: 'bid_id', - params: {zone: 'zone_id'}, - placementCode: 'ad-unit-1', - sizes: [[300, 250], [300, 600]] - } - ] - }; - var validData_2 = { - bids: [ - { - bidder: 'admixer', - bidId: 'bid_id', - params: {zone: 'zone_id'}, - placementCode: 'ad-unit-1', - sizes: [300, 250] - } - ] - }; - var invalidData = { - bids: [ - { - bidder: 'admixer', - bidId: 'bid_id', - params: {}, - placementCode: 'ad-unit-1', - sizes: [[300, 250], [300, 600]] - } - ] - }; - var validVideoData_1 = { - bids: [ - { - mediaType: 'video', - bidder: 'admixer', - bidId: 'bid_id', - params: {zone: 'zone_id'}, - placementCode: 'ad-unit-1', - sizes: [[300, 250], [300, 600]] - } - ] - }; - var validVideoData_2 = { - bids: [ - { - mediaType: 'video', - bidder: 'admixer', - bidId: 'bid_id', - params: {zone: 'zone_id'}, - placementCode: 'ad-unit-1', - sizes: [300, 250] - } - ] - }; - var validVideoData_3 = { - bids: [ - { - mediaType: 'video', - bidder: 'admixer', - bidId: 'bid_id', - params: {zone: 'zone_id', video: {skippable: true}}, - placementCode: 'ad-unit-1', - sizes: [300, 250] - } - ] - }; - var invalidVideoData = { - bids: [ - { - mediaType: 'video', - bidder: 'admixer', - bidId: 'bid_id', - params: {}, - placementCode: 'ad-unit-1', - sizes: [[300, 250], [300, 600]] - } - ] - }; - var responseWithAd = JSON.stringify({ - 'result': { - 'cpm': 2.2, - 'ad': '
response ad
', - 'width': 300, - 'height': 250 - }, - 'callback_uid': 'ad-unit-1' - }); - var responseWithoutAd = JSON.stringify({ - 'result': { - 'cpm': 0, - 'ad': '', - 'width': 0, - 'height': 0 - }, - 'callback_uid': 'ad-unit-1' - }); - var responseWithVideoAd = JSON.stringify({ - 'result': { - 'cpm': 2.2, - 'vastUrl': 'http://inv-nets.admixer.net/vastxml.aspx?req=9d651544-daf4-48ed-ae0c-38a60a4e1920&vk=e914f026449e49aeb6eea07b9642a2ce', - 'width': 300, - 'height': 250 - }, - 'callback_uid': 'ad-unit-1' - }); - var responseWithoutVideoAd = JSON.stringify({ - 'result': { - 'cpm': 0, - 'vastUrl': '', - 'width': 0, - 'height': 0 - }, - 'callback_uid': 'ad-unit-1' - }); - var responseEmpty = ''; - var invUrl = '//inv-nets.admixer.net/prebid.aspx'; - var invVastUrl = '//inv-nets.admixer.net/videoprebid.aspx'; - var validJsonParams = { - zone: 'zone_id', - callback_uid: 'ad-unit-1', - sizes: '300x250-300x600' - }; - var validJsonVideoParams = { - zone: 'zone_id', - callback_uid: 'ad-unit-1', - sizes: '300x250-300x600', - skippable: true - }; - describe('bid request with valid data', function () { - var stubAjax; - beforeEach(function () { - stubAjax = sinon.stub(Ajax, 'ajax'); - }); - - afterEach(function () { - stubAjax.restore(); - }); - it('display: bid request should be called. sizes style -> [[],[]]', function () { - Adapter.callBids(validData_1); - sinon.assert.calledOnce(stubAjax); - }); - it('video: bid request should be called. sizes style -> [[],[]]', function () { - Adapter.callBids(validVideoData_1); - sinon.assert.calledOnce(stubAjax); - }); - it('display: bid request should be called. sizes style -> []', function () { - Adapter.callBids(validData_2); - sinon.assert.calledOnce(stubAjax); - }); - it('video: bid request should be called. sizes style -> []', function () { - Adapter.callBids(validVideoData_2); - sinon.assert.calledOnce(stubAjax); - }); - it('display: ajax params should be matched', function () { - Adapter.callBids(validData_1); - sinon.assert.calledWith(stubAjax, sinon.match(invUrl, function () { - }, validJsonParams, {method: 'GET'})); - }); - it('video: ajax params should be matched', function () { - Adapter.callBids(validVideoData_3); - sinon.assert.calledWith(stubAjax, sinon.match(invVastUrl, function () { - }, validJsonVideoParams, {method: 'GET'})); - }); - }); - describe('bid request with invalid data', function () { - var addBidResponse, stubAjax; - beforeEach(function () { - addBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - stubAjax = sinon.stub(Ajax, 'ajax'); - }); - - afterEach(function () { - addBidResponse.restore(); - stubAjax.restore(); - }); - it('display: ajax shouldn\'t be called', function () { - Adapter.callBids(invalidData); - sinon.assert.notCalled(stubAjax); - }); - it('video: ajax shouldn\'t be called', function () { - Adapter.callBids(invalidVideoData); - sinon.assert.notCalled(stubAjax); - }); - it('display: bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID + '"', function () { - Adapter.callBids(invalidData); - expect(addBidResponse.firstCall.args[1].getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(addBidResponse.firstCall.args[1].bidderCode).to.equal('admixer'); - }); - it('video: bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID + '"', function () { - Adapter.callBids(invalidVideoData); - expect(addBidResponse.firstCall.args[1].getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(addBidResponse.firstCall.args[1].bidderCode).to.equal('admixer'); - }); - }); - describe('bid response', function () { - var addBidResponse; - beforeEach(function () { - addBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - }); - afterEach(function () { - addBidResponse.restore(); - }); - it('display: response with ad. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.GOOD + '"', function () { - Adapter.responseCallback(responseWithAd); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(arg.bidderCode).to.equal('admixer'); - }); - it('video: response with ad. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.GOOD + '"', function () { - Adapter.responseCallback(responseWithVideoAd); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(arg.bidderCode).to.equal('admixer'); - }); - it('display: response without ad. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID, function () { - Adapter.responseCallback(responseWithoutAd); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(arg.bidderCode).to.equal('admixer'); - }); - it('video: response without ad. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID, function () { - Adapter.responseCallback(responseWithoutVideoAd); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(arg.bidderCode).to.equal('admixer'); - }); - it('display/video: response empty. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID, function () { - Adapter.responseCallback(responseEmpty); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(arg.bidderCode).to.equal('admixer'); - }); - }); -}); diff --git a/test/spec/modules/adsupplyBidAdapter_spec.js b/test/spec/modules/adsupplyBidAdapter_spec.js deleted file mode 100644 index b1bc0bf17f1..00000000000 --- a/test/spec/modules/adsupplyBidAdapter_spec.js +++ /dev/null @@ -1,359 +0,0 @@ -describe('adsupply adapter tests', function () { - const expect = require('chai').expect; - - const AdSupplyAdapter = require('../../../modules/adsupplyBidAdapter'); - const adloader = require('../../../src/adloader'); - const bidmanager = require('../../../src/bidmanager'); - const CONSTANTS = require('../../../src/constants.json'); - let adsupplyAdapter = new AdSupplyAdapter(); - - beforeEach(() => { - $$PREBID_GLOBAL$$._bidsRequested = []; - }); - - it('adsupply response handler should exist and be a function', function () { - expect($$PREBID_GLOBAL$$.adSupplyResponseHandler).to.exist.and.to.be.a('function'); - }); - - it('two requests are sent to adsupply engine', function () { - let stubLoadScript = sinon.stub(adloader, 'loadScript'); - - let request = { - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - zoneId: 111, - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }, - { - placementCode: 'pc2', - bidder: 'adsupply', - bidId: 'bidId2', - params: { - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - zoneId: 222, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - - adsupplyAdapter.callBids(request); - - sinon.assert.calledTwice(stubLoadScript); - - adloader.loadScript.restore(); - }); - - it('zoneId is not a number and not specified', function () { - let stubLoadScript = sinon.stub(adloader, 'loadScript'); - - let request = { - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - zoneId: '111', - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }, - { - placementCode: 'pc2', - bidder: 'adsupply', - bidId: 'bidId2', - params: { - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - - adsupplyAdapter.callBids(request); - - sinon.assert.notCalled(stubLoadScript); - - adloader.loadScript.restore(); - }); - - it('siteId is empty and not specified', function () { - let stubLoadScript = sinon.stub(adloader, 'loadScript'); - - let request = { - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - zoneId: 111, - siteId: '', - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - endpointUrl: 'engine.4dsply.com' - } - }, - { - placementCode: 'pc2', - bidder: 'adsupply', - bidId: 'bidId2', - params: { - zoneId: 222, - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - - adsupplyAdapter.callBids(request); - - sinon.assert.notCalled(stubLoadScript); - - adloader.loadScript.restore(); - }); - - it('endpointUrl is empty and not specified', function () { - let stubLoadScript = sinon.stub(adloader, 'loadScript'); - - let request = { - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - zoneId: 111, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: '' - } - }, - { - placementCode: 'pc2', - bidder: 'adsupply', - bidId: 'bidId2', - params: { - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - zoneId: 222, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - } - }] - }; - - adsupplyAdapter.callBids(request); - - sinon.assert.notCalled(stubLoadScript); - - adloader.loadScript.restore(); - }); - - it('clientId is empty and not specified', function () { - let stubLoadScript = sinon.stub(adloader, 'loadScript'); - - let request = { - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - clientId: '', - zoneId: 111, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }, - { - placementCode: 'pc2', - bidder: 'adsupply', - bidId: 'bidId2', - params: { - zoneId: 222, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - - adsupplyAdapter.callBids(request); - - sinon.assert.notCalled(stubLoadScript); - - adloader.loadScript.restore(); - }); - - it('parameters are missed', function () { - let stubLoadScript = sinon.stub(adloader, 'loadScript'); - - let request = { - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1' - }] - }; - - adsupplyAdapter.callBids(request); - - sinon.assert.notCalled(stubLoadScript); - - adloader.loadScript.restore(); - }); - - it('Parameters added to the request url', function () { - let stubLoadScript = sinon.stub(adloader, 'loadScript'); - - let request = { - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - zoneId: 111, - clientId: 'g32db6906-55f4-42b1-a7d2-7dfaddce96fd', - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - - adsupplyAdapter.callBids(request); - - var requestUrl = stubLoadScript.getCall(0).args[0]; - expect(requestUrl).to.contain('111'); - expect(requestUrl).to.contain('0ab16161-a1de-4683-8837-c420bd4387c0'); - expect(requestUrl).to.contain('engine.4dsply.com'); - expect(requestUrl).to.contain('&hbt=1'); - expect(requestUrl).to.contain('g32db6906-55f4-42b1-a7d2-7dfaddce96fd'); - - adloader.loadScript.restore(); - }); - - it('Response handler invalid data', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - // adapter needs to be called, in order for the stub to register. - new AdSupplyAdapter(); - - // bidId is not valid - $$PREBID_GLOBAL$$.adSupplyResponseHandler(null); - - // bidRequest object is not found - $$PREBID_GLOBAL$$.adSupplyResponseHandler('bidId1'); - - let clientId = 'g5d384afa-c050-4bac-b202-dab8fb06e381'; - // Zone property is not found - let bidderRequest = { - bidderCode: 'adsupply', - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - clientId: clientId, - zoneId: 111, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - $$PREBID_GLOBAL$$.adSupplyResponseHandler('bidId1'); - - // Media is not found - window[clientId] = window[clientId] || {}; - window[clientId]['b111'] = window[clientId]['b111'] || {}; - $$PREBID_GLOBAL$$.adSupplyResponseHandler('bidId1'); - - sinon.assert.notCalled(stubAddBidResponse); - - $$PREBID_GLOBAL$$._bidsRequested.pop(); - bidmanager.addBidResponse.restore(); - }); - - it('No Fill response', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - // adapter needs to be called, in order for the stub to register. - new AdSupplyAdapter(); - - let clientId = 'g5d384afa-c050-4bac-b202-dab8fb06e381'; - // Zone property is not found - let bidderRequest = { - bidderCode: 'adsupply', - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - clientId: clientId, - zoneId: 111, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - window[clientId] = window[clientId] || {}; - window[clientId]['b111'] = window[clientId]['b111'] || {}; - window[clientId]['b111'].Media = { width: 300 }; - $$PREBID_GLOBAL$$.adSupplyResponseHandler('bidId1'); - - sinon.assert.calledOnce(stubAddBidResponse); - - let bidPlacementCode = stubAddBidResponse.getCall(0).args[0]; - let bidResponse = stubAddBidResponse.getCall(0).args[1]; - expect(bidPlacementCode).to.equal('pc1'); - expect(bidResponse.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(bidResponse.bidderCode).to.equal('adsupply'); - - $$PREBID_GLOBAL$$._bidsRequested.pop(); - bidmanager.addBidResponse.restore(); - }); - - it('Fill response', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - // adapter needs to be called, in order for the stub to register. - new AdSupplyAdapter(); - - let clientId = 'g5d384afa-c050-4bac-b202-dab8fb06e381'; - // Zone property is not found - let bidderRequest = { - bidderCode: 'adsupply', - bids: [{ - placementCode: 'pc1', - bidder: 'adsupply', - bidId: 'bidId1', - params: { - clientId: clientId, - zoneId: 111, - siteId: '0ab16161-a1de-4683-8837-c420bd4387c0', - endpointUrl: 'engine.4dsply.com' - } - }] - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - window[clientId] = window[clientId] || {}; - window[clientId]['b111'] = window[clientId]['b111'] || {}; - window[clientId]['b111'].Media = { Width: 300, Height: 250, Url: '/Redirect.engine', Ecpm: 0.0012 }; - $$PREBID_GLOBAL$$.adSupplyResponseHandler('bidId1'); - - sinon.assert.calledOnce(stubAddBidResponse); - - let bidPlacementCode = stubAddBidResponse.getCall(0).args[0]; - let bidResponse = stubAddBidResponse.getCall(0).args[1]; - expect(bidPlacementCode).to.equal('pc1'); - expect(bidResponse.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bidResponse.bidderCode).to.equal('adsupply'); - - $$PREBID_GLOBAL$$._bidsRequested.pop(); - bidmanager.addBidResponse.restore(); - }); -}); diff --git a/test/spec/modules/adxcgAnalyticsAdapter_spec.js b/test/spec/modules/adxcgAnalyticsAdapter_spec.js index 790a39789b2..179b806da48 100644 --- a/test/spec/modules/adxcgAnalyticsAdapter_spec.js +++ b/test/spec/modules/adxcgAnalyticsAdapter_spec.js @@ -20,7 +20,7 @@ describe('adxcg analytics adapter', () => { describe('track', () => { it('builds and sends auction data', () => { - let auctionTimestamp = 42; + let auctionTimestamp = 1496510254313; let initOptions = { publisherId: '42' }; @@ -32,6 +32,21 @@ describe('adxcg analytics adapter', () => { ad: 'adContent' }; + let bidTimeoutArgsV1 = [ + { + bidId: '2baa51527bd015', + bidder: 'bidderOne', + adUnitCode: '/19968336/header-bid-tag-0', + auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' + }, + { + bidId: '6fe3b4c2c23092', + bidder: 'bidderTwo', + adUnitCode: '/19968336/header-bid-tag-0', + auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' + } + ]; + adaptermanager.registerAnalyticsAdapter({ code: 'adxcg', adapter: adxcgAnalyticsAdapter @@ -42,11 +57,21 @@ describe('adxcg analytics adapter', () => { options: initOptions }); + // Step 1: Send auction init event events.emit(constants.EVENTS.AUCTION_INIT, { timestamp: auctionTimestamp }); + + // Step 2: Send bid requested event events.emit(constants.EVENTS.BID_REQUESTED, bidRequest); + + // Step 3: Send bid response event events.emit(constants.EVENTS.BID_RESPONSE, bidResponse); + + // Step 4: Send bid time out event + events.emit(constants.EVENTS.BID_TIMEOUT, bidTimeoutArgsV1); + + // Step 5: Send auction end event events.emit(constants.EVENTS.AUCTION_END, {}); expect(requests.length).to.equal(1); @@ -61,8 +86,12 @@ describe('adxcg analytics adapter', () => { expect(auctionEventData.bidResponses[0]).to.not.have.property('ad'); expect(auctionEventData.initOptions).to.deep.equal(initOptions); + expect(auctionEventData.auctionTimestamp).to.equal(auctionTimestamp); + expect(auctionEventData.bidTimeout).to.deep.equal(['bidderOne', 'bidderTwo']); + + // Step 6: Send auction bid won event events.emit(constants.EVENTS.BID_WON, { adId: 'adIdData', ad: 'adContent' diff --git a/test/spec/modules/adyoulikeBidAdapter_spec.js b/test/spec/modules/adyoulikeBidAdapter_spec.js deleted file mode 100644 index 05c112c2a99..00000000000 --- a/test/spec/modules/adyoulikeBidAdapter_spec.js +++ /dev/null @@ -1,314 +0,0 @@ -import { expect } from 'chai'; -import { parse } from '../../../src/url'; -import AdyoulikAdapter from '../../../modules/adyoulikeBidAdapter'; -import bidmanager from 'src/bidmanager'; -import { STATUS } from 'src/constants'; - -describe('Adyoulike Adapter', () => { - const endpoint = 'http://hb-api.omnitagjs.com/hb-api/prebid'; - const canonicalUrl = 'http://canonical.url/?t=%26'; - const bidderCode = 'adyoulike'; - const bidRequestWithEmptyPlacement = { - 'bidderCode': 'adyoulike', - 'bids': [ - { - 'bidId': 'bid_id_0', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-0', - 'params': {}, - 'sizes': '300x250' - } - ], - }; - const bidRequestWithEmptySizes = { - 'bidderCode': 'adyoulike', - 'bids': [ - { - 'bidId': 'bid_id_0', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-0', - 'params': { - 'placement': 'placement_0' - }, - 'transactionId': 'bid_id_0_transaction_id' - } - ], - }; - const bidRequestWithSinglePlacement = { - 'bidderCode': 'adyoulike', - 'bids': [ - { - 'bidId': 'bid_id_0', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-0', - 'params': { - 'placement': 'placement_0' - }, - 'sizes': '300x250', - 'transactionId': 'bid_id_0_transaction_id' - } - ], - }; - const bidRequestMultiPlacements = { - 'bidderCode': 'adyoulike', - 'bids': [ - { - 'bidId': 'bid_id_0', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-0', - 'params': { - 'placement': 'placement_0' - }, - 'sizes': '300x250', - 'transactionId': 'bid_id_0_transaction_id' - }, - { - 'bidId': 'bid_id_1', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-1', - 'params': { - 'placement': 'placement_1' - }, - 'sizes': [[300, 600]], - 'transactionId': 'bid_id_1_transaction_id' - }, - { - 'bidId': 'bid_id_2', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-2', - 'params': {}, - 'sizes': '300x400', - 'transactionId': 'bid_id_2_transaction_id' - }, - { - 'bidId': 'bid_id_3', - 'bidder': 'adyoulike', - 'placementCode': 'adunit/hb-3', - 'params': { - 'placement': 'placement_3' - }, - 'transactionId': 'bid_id_3_transaction_id' - } - ], - }; - - const responseWithEmptyPlacement = [ - { - 'Placement': 'placement_0' - } - ]; - const responseWithSinglePlacement = [ - { - 'Placement': 'placement_0', - 'Banner': 'placement_0', - 'Price': 0.5 - } - ]; - const responseWithMultiplePlacements = [ - { - 'Placement': 'placement_0', - 'Banner': 'placement_0', - 'Price': 0.5 - }, - { - 'Placement': 'placement_1', - 'Banner': 'placement_1', - 'Price': 0.6 - } - ]; - - let adapter; - - beforeEach(() => { - adapter = new AdyoulikAdapter(); - }); - - describe('adapter public API', () => { - const adapter = new AdyoulikAdapter(); - - it('setBidderCode', () => { - expect(adapter.setBidderCode).to.be.a('function'); - }); - it('callBids', () => { - expect(adapter.setBidderCode).to.be.a('function'); - }); - }); - - describe('request function', () => { - let requests; - let xhr; - let addBidResponse; - let canonicalQuery; - - beforeEach(() => { - requests = []; - - xhr = sinon.useFakeXMLHttpRequest(); - xhr.onCreate = request => requests.push(request); - - addBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - let canonical = document.createElement('link'); - canonical.rel = 'canonical'; - canonical.href = canonicalUrl; - canonicalQuery = sinon.stub(window.top.document.head, 'querySelector'); - canonicalQuery.withArgs('link[rel="canonical"][href]').returns(canonical); - }); - - afterEach(() => { - xhr.restore(); - bidmanager.addBidResponse.restore(); - canonicalQuery.restore(); - }); - - it('requires placement request', () => { - adapter.callBids(bidRequestWithEmptyPlacement); - expect(requests).to.be.empty; - expect(addBidResponse.calledOnce).to.equal(false); - }); - - it('requires sizes in request', () => { - adapter.callBids(bidRequestWithEmptySizes); - expect(requests).to.be.empty; - expect(addBidResponse.calledOnce).to.equal(false); - }); - - it('sends bid request to endpoint with single placement', () => { - adapter.callBids(bidRequestWithSinglePlacement); - expect(requests[0].url).to.contain(endpoint); - expect(requests[0].method).to.equal('POST'); - - expect(requests[0].url).to.contains('CanonicalUrl=' + encodeURIComponent(canonicalUrl)); - - let body = JSON.parse(requests[0].requestBody); - expect(body.Version).to.equal('0.2'); - expect(body.Placements).deep.equal(['placement_0']); - expect(body.PageRefreshed).to.equal(false); - expect(body.TransactionIds).deep.equal({'placement_0': 'bid_id_0_transaction_id'}); - }); - - it('sends bid request to endpoint with single placement without canonical', () => { - canonicalQuery.restore(); - - adapter.callBids(bidRequestWithSinglePlacement); - expect(requests[0].url).to.contain(endpoint); - expect(requests[0].method).to.equal('POST'); - - expect(requests[0].url).to.not.contains('CanonicalUrl=' + encodeURIComponent(canonicalUrl)); - - let body = JSON.parse(requests[0].requestBody); - expect(body.Version).to.equal('0.2'); - expect(body.Placements).deep.equal(['placement_0']); - expect(body.PageRefreshed).to.equal(false); - expect(body.TransactionIds).deep.equal({'placement_0': 'bid_id_0_transaction_id'}); - }); - - it('sends bid request to endpoint with multiple placements', () => { - adapter.callBids(bidRequestMultiPlacements); - expect(requests[0].url).to.contain(endpoint); - expect(requests[0].method).to.equal('POST'); - - expect(requests[0].url).to.contains('CanonicalUrl=' + encodeURIComponent(canonicalUrl)); - - let body = JSON.parse(requests[0].requestBody); - expect(body.Version).to.equal('0.2'); - expect(body.Placements).deep.equal(['placement_0', 'placement_1']); - expect(body.PageRefreshed).to.equal(false); - expect(body.TransactionIds).deep.equal({'placement_0': 'bid_id_0_transaction_id', 'placement_1': 'bid_id_1_transaction_id'}); - }); - }); - - describe('response function', () => { - let server; - let addBidResponse; - - beforeEach(() => { - server = sinon.fakeServer.create(); - addBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - }); - - afterEach(() => { - server.restore(); - bidmanager.addBidResponse.restore(); - }); - - it('invalid json', () => { - server.respondWith('{'); - adapter.callBids(bidRequestWithSinglePlacement); - server.respond(); - - expect(addBidResponse.calledOnce).to.equal(true); - expect(addBidResponse.args[0]).to.have.lengthOf(2); - expect(addBidResponse.args[0][1].getStatusCode()).to.equal(STATUS.NO_BID); - expect(addBidResponse.args[0][1].bidderCode).to.equal(bidderCode); - }); - - it('receive reponse with empty placement', () => { - server.respondWith(JSON.stringify(responseWithEmptyPlacement)); - adapter.callBids(bidRequestWithSinglePlacement); - server.respond(); - - expect(addBidResponse.calledOnce).to.equal(true); - expect(addBidResponse.args[0]).to.have.lengthOf(2); - expect(addBidResponse.args[0][1].getStatusCode()).to.equal(STATUS.NO_BID); - expect(addBidResponse.args[0][1].bidderCode).to.equal(bidderCode); - }); - - it('receive reponse with single placement', () => { - server.respondWith(JSON.stringify(responseWithSinglePlacement)); - adapter.callBids(bidRequestWithSinglePlacement); - server.respond(); - - expect(addBidResponse.calledOnce).to.equal(true); - expect(addBidResponse.args[0]).to.have.lengthOf(2); - expect(addBidResponse.args[0][1].getStatusCode()).to.equal(STATUS.GOOD); - expect(addBidResponse.args[0][1].cpm).to.equal(0.5); - expect(addBidResponse.args[0][1].ad).to.equal('placement_0'); - expect(addBidResponse.args[0][1].width).to.equal(300); - expect(addBidResponse.args[0][1].height).to.equal(250); - }); - - it('receive reponse with multiple placement', () => { - server.respondWith(JSON.stringify(responseWithMultiplePlacements)); - adapter.callBids(bidRequestMultiPlacements); - server.respond(); - - expect(addBidResponse.calledTwice).to.equal(true); - - expect(addBidResponse.args[0]).to.have.lengthOf(2); - expect(addBidResponse.args[0][1].getStatusCode()).to.equal(STATUS.GOOD); - expect(addBidResponse.args[0][1].bidderCode).to.equal(bidderCode); - expect(addBidResponse.args[0][1].cpm).to.equal(0.5); - expect(addBidResponse.args[0][1].ad).to.equal('placement_0'); - expect(addBidResponse.args[0][1].width).to.equal(300); - expect(addBidResponse.args[0][1].height).to.equal(250); - - expect(addBidResponse.args[1]).to.have.lengthOf(2); - expect(addBidResponse.args[1][1].getStatusCode()).to.equal(STATUS.GOOD); - expect(addBidResponse.args[1][1].bidderCode).to.equal(bidderCode); - expect(addBidResponse.args[1][1].cpm).to.equal(0.6); - expect(addBidResponse.args[1][1].ad).to.equal('placement_1'); - expect(addBidResponse.args[1][1].width).to.equal(300); - expect(addBidResponse.args[1][1].height).to.equal(600); - }); - - it('receive reponse with invalid placement number', () => { - server.respondWith(JSON.stringify(responseWithSinglePlacement)); - adapter.callBids(bidRequestMultiPlacements); - server.respond(); - - expect(addBidResponse.calledTwice).to.equal(true); - - expect(addBidResponse.args[0]).to.have.lengthOf(2); - expect(addBidResponse.args[0][1].getStatusCode()).to.equal(STATUS.GOOD); - expect(addBidResponse.args[0][1].bidderCode).to.equal(bidderCode); - expect(addBidResponse.args[0][1].cpm).to.equal(0.5); - expect(addBidResponse.args[0][1].ad).to.equal('placement_0'); - expect(addBidResponse.args[0][1].width).to.equal(300); - expect(addBidResponse.args[0][1].height).to.equal(250); - - expect(addBidResponse.args[1]).to.have.lengthOf(2); - expect(addBidResponse.args[1][1].getStatusCode()).to.equal(STATUS.NO_BID); - }); - }); -}); diff --git a/test/spec/modules/aerservBidAdapter_spec.js b/test/spec/modules/aerservBidAdapter_spec.js deleted file mode 100644 index be0f6393063..00000000000 --- a/test/spec/modules/aerservBidAdapter_spec.js +++ /dev/null @@ -1,213 +0,0 @@ -import {expect} from 'chai'; -import AerServAdapter from 'modules/aerservBidAdapter'; -import bidmanager from 'src/bidmanager'; - -const BASE_REQUEST = JSON.stringify({ - bidderCode: 'aerserv', - requestId: 'a595eff7-d5a3-40f8-971c-5b4ef244ec53', - bidderRequestId: '1f8c8c03de01f9', - bids: [ - { - bidder: 'aerserv', - params: { - plc: '480', - }, - placementCode: 'adunit-1', - transactionId: 'a0e033af-f50c-4a7e-aeed-c01c5f709848', - sizes: [[300, 250], [300, 600]], - bidId: '2f4a69463b3bc9', - bidderRequestId: '1f8c8c03de01f9', - requestId: 'a595eff7-d5a3-40f8-971c-5b4ef244ec53' - } - ] -}); - -describe('AerServ Adapter', () => { - let adapter; - let bidmanagerStub; - - beforeEach(() => { - adapter = new AerServAdapter(); - bidmanagerStub = sinon.stub(bidmanager, 'addBidResponse'); - }); - - afterEach(() => { - bidmanager.addBidResponse.restore(); - }); - - describe('callBids()', () => { - let xhr; - let requests; - - beforeEach(() => { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = request => requests.push(request); - }); - - afterEach(() => { - xhr.restore(); - }); - - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - - it('should not add bid responses with no bids to call', () => { - adapter.callBids({}); - - sinon.assert.notCalled(bidmanager.addBidResponse); - }); - - it('requires plc parameter to make request', () => { - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0].params = {}; - adapter.callBids(bidRequest); - expect(requests).to.be.empty; - }); - - it('sends requests to normal endpoint for non-video requests', () => { - adapter.callBids(JSON.parse(BASE_REQUEST)); - expect(requests.length).to.equal(1); - expect(requests[0].url).to.include('/as/json/pbjs/v1'); - }); - - it('sends requests to video endpoint for video requests', () => { - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0]['mediaType'] = 'video'; - bidRequest.bids[0]['video'] = {}; - adapter.callBids(bidRequest); - expect(requests[0].url).to.include('/as/json/pbjsvast/v1'); - }); - - it('properly adds video parameters to the request', () => { - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0]['mediaType'] = 'video'; - bidRequest.bids[0].params['video'] = { videoParam: 'videoValue' }; - adapter.callBids(bidRequest); - expect(requests[0].url).to.include('videoParam=videoValue'); - }); - - it('parses the first size for video requests', () => { - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0]['mediaType'] = 'video'; - adapter.callBids(bidRequest); - expect(requests[0].url).to.include('vpw=300'); - expect(requests[0].url).to.include('vph=250'); - }); - - it('sends requests to production by default', () => { - adapter.callBids(JSON.parse(BASE_REQUEST)); - expect(requests[0].url).to.include('//ads.aerserv.com'); - }); - - it('sends requests to the specified endpoint when \'env\' is provided', () => { - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0].params['env'] = 'dev'; - adapter.callBids(bidRequest); - expect(requests[0].url).to.include('//dev-ads.aerserv.com'); - }); - }); - - describe('response handling', () => { - let server; - - beforeEach(() => { - server = sinon.fakeServer.create(); - }); - - afterEach(() => { - server.restore(); - }); - - it('responds with an empty bid without required parameters', () => { - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0].params = {}; - adapter.callBids(bidRequest); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(2); - }); - - it('responds with an empty bid on empty response', () => { - server.respondWith(''); - - adapter.callBids(JSON.parse(BASE_REQUEST)); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(2); - }); - - it('responds with an empty bid on un-parseable JSON response', () => { - server.respondWith('{\"bad\":\"json}'); - - adapter.callBids(JSON.parse(BASE_REQUEST)); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(2); - }); - - it('responds with a valid bid returned ad', () => { - server.respondWith(JSON.stringify({cpm: 5, w: 320, h: 50, adm: 'sweet ad markup'})); - adapter.callBids(JSON.parse(BASE_REQUEST)); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(1); - }); - - it('responds with a valid bid from returned ad', () => { - server.respondWith(JSON.stringify({cpm: 5, w: 320, h: 50, vastUrl: 'sweet URL where VAST is at'})); - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0]['mediaType'] = 'video'; - bidRequest.bids[0]['video'] = {}; - adapter.callBids(bidRequest); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(1); - }); - - it('responds with empty bid if response has no ad', () => { - server.respondWith(JSON.stringify({error: 'no ads'})); - adapter.callBids(JSON.parse(BASE_REQUEST)); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(2); - }); - - // things that should never occur - it('responds with empty bid if response has 0 or below cpm', () => { - server.respondWith(JSON.stringify({cpm: 0, w: 320, h: 50, adm: 'sweet ad markup'})); - adapter.callBids(JSON.parse(BASE_REQUEST)); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(2); - }); - - it('responds with empty bid if response has no markup', () => { - server.respondWith(JSON.stringify({cpm: 5.0, w: 320, h: 50})); - adapter.callBids(JSON.parse(BASE_REQUEST)); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(2); - }); - - it('responds with an empty bid if response has no video markup', () => { - server.respondWith(JSON.stringify({cpm: 5, w: 320, h: 50})); - let bidRequest = JSON.parse(BASE_REQUEST); - bidRequest.bids[0]['mediaType'] = 'video'; - bidRequest.bids[0]['video'] = {}; - adapter.callBids(bidRequest); - server.respond(); - let bid = bidmanagerStub.getCall(0).args[1]; - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bid.getStatusCode()).to.equal(2); - }); - }); -}); diff --git a/test/spec/modules/appnexusAstBidAdapter_spec.js b/test/spec/modules/appnexusAstBidAdapter_spec.js deleted file mode 100644 index 660ecfc507a..00000000000 --- a/test/spec/modules/appnexusAstBidAdapter_spec.js +++ /dev/null @@ -1,428 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/appnexusAstBidAdapter'; -import { newBidder } from 'src/adapters/bidderFactory'; - -const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; - -describe('AppNexusAdapter', () => { - const adapter = newBidder(spec); - - describe('inherited functions', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValid', () => { - let bid = { - 'bidder': 'appnexusAst', - 'params': { - 'placementId': '10433394' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - }; - - it('should return true when required params found', () => { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return true when required params found', () => { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = { - 'member': '1234', - 'invCode': 'ABCD' - }; - - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return false when required params are not passed', () => { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = { - 'placementId': 0 - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('buildRequests', () => { - let bidRequests = [ - { - 'bidder': 'appnexusAst', - 'params': { - 'placementId': '10433394' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - } - ]; - - it('should add source and verison to the tag', () => { - const request = spec.buildRequests(bidRequests); - const payload = JSON.parse(request.data); - expect(payload.sdk).to.exist; - expect(payload.sdk).to.deep.equal({ - source: 'pbjs', - version: '$prebid.version$' - }); - }); - - it('should populate the ad_types array on all requests', () => { - ['banner', 'video', 'native'].forEach(type => { - const bidRequest = Object.assign({}, bidRequests[0]); - bidRequest.mediaTypes = {}; - bidRequest.mediaTypes[type] = {}; - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].ad_types).to.deep.equal([type]); - }); - }); - - it('should populate the ad_types array on outstream requests', () => { - const bidRequest = Object.assign({}, bidRequests[0]); - bidRequest.mediaTypes = {}; - bidRequest.mediaTypes.video = {context: 'outstream'}; - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].ad_types).to.deep.equal(['video']); - }); - - it('sends bid request to ENDPOINT via POST', () => { - const request = spec.buildRequests(bidRequests); - expect(request.url).to.equal(ENDPOINT); - expect(request.method).to.equal('POST'); - }); - - it('should attach valid video params to the tag', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - placementId: '10433394', - video: { - id: 123, - minduration: 100, - foobar: 'invalid' - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - expect(payload.tags[0].video).to.deep.equal({ - id: 123, - minduration: 100 - }); - }); - - it('should attach valid user params to the tag', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - placementId: '10433394', - user: { - external_uid: '123', - foobar: 'invalid' - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.user).to.exist; - expect(payload.user).to.deep.equal({ - external_uid: '123', - }); - }); - - it('should attache native params to the request', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - mediaType: 'native', - nativeParams: { - title: {required: true}, - body: {required: true}, - image: {required: true, sizes: [{ width: 100, height: 100 }] }, - cta: {required: false}, - sponsoredBy: {required: true} - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].native.layouts[0]).to.deep.equal({ - title: {required: true}, - description: {required: true}, - main_image: {required: true, sizes: [{ width: 100, height: 100 }] }, - ctatext: {required: false}, - sponsored_by: {required: true} - }); - }); - - it('sets minimum native asset params when not provided on adunit', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - mediaType: 'native', - nativeParams: { - image: {required: true}, - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].native.layouts[0]).to.deep.equal({ - main_image: {required: true, sizes: [{}] }, - }); - }); - - it('does not overwrite native ad unit params with mimimum params', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - mediaType: 'native', - nativeParams: { - image: { - aspect_ratios: [{ - min_width: 100, - ratio_width: 2, - ratio_height: 3, - }] - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].native.layouts[0]).to.deep.equal({ - main_image: { - required: true, - aspect_ratios: [{ - min_width: 100, - ratio_width: 2, - ratio_height: 3, - }] - }, - }); - }); - - it('should convert keyword params to proper form and attaches to request', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - placementId: '10433394', - keywords: { - single: 'val', - singleArr: ['val'], - singleArrNum: [5], - multiValMixed: ['value1', 2, 'value3'], - singleValNum: 123, - badValue: {'foo': 'bar'} // should be dropped - } - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].keywords).to.deep.equal([{ - 'key': 'single', - 'value': ['val'] - }, { - 'key': 'singleArr', - 'value': ['val'] - }, { - 'key': 'singleArrNum', - 'value': ['5'] - }, { - 'key': 'multiValMixed', - 'value': ['value1', '2', 'value3'] - }, { - 'key': 'singleValNum', - 'value': ['123'] - }]); - }); - - it('should should add payment rules to the request', () => { - let bidRequest = Object.assign({}, - bidRequests[0], - { - params: { - placementId: '10433394', - usePaymentRule: true - } - } - ); - - const request = spec.buildRequests([bidRequest]); - const payload = JSON.parse(request.data); - - expect(payload.tags[0].use_pmt_rule).to.equal(true); - }); - }) - - describe('interpretResponse', () => { - let response = { - 'version': '3.0.0', - 'tags': [ - { - 'uuid': '3db3773286ee59', - 'tag_id': 10433394, - 'auction_id': '4534722592064951574', - 'nobid': false, - 'no_ad_url': 'http://lax1-ib.adnxs.com/no-ad', - 'timeout_ms': 10000, - 'ad_profile_id': 27079, - 'ads': [ - { - 'content_source': 'rtb', - 'ad_type': 'banner', - 'buyer_member_id': 958, - 'creative_id': 29681110, - 'media_type_id': 1, - 'media_subtype_id': 1, - 'cpm': 0.5, - 'cpm_publisher_currency': 0.5, - 'publisher_currency_code': '$', - 'client_initiated_ad_counting': true, - 'rtb': { - 'banner': { - 'content': '', - 'width': 300, - 'height': 250 - }, - 'trackers': [ - { - 'impression_urls': [ - 'http://lax1-ib.adnxs.com/impression' - ], - 'video_events': {} - } - ] - } - } - ] - } - ] - }; - - it('should get correct bid response', () => { - let expectedResponse = [ - { - 'requestId': '3db3773286ee59', - 'cpm': 0.5, - 'creativeId': 29681110, - 'dealId': undefined, - 'width': 300, - 'height': 250, - 'ad': '', - 'mediaType': 'banner', - 'currency': 'USD', - 'ttl': 300, - 'netRevenue': true - } - ]; - let bidderRequest; - let result = spec.interpretResponse({ body: response }, {bidderRequest}); - expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); - }); - - it('handles nobid responses', () => { - let response = { - 'version': '0.0.1', - 'tags': [{ - 'uuid': '84ab500420319d', - 'tag_id': 5976557, - 'auction_id': '297492697822162468', - 'nobid': true - }] - }; - let bidderRequest; - - let result = spec.interpretResponse({ body: response }, {bidderRequest}); - expect(result.length).to.equal(0); - }); - - it('handles non-banner media responses', () => { - let response = { - 'tags': [{ - 'uuid': '84ab500420319d', - 'ads': [{ - 'ad_type': 'video', - 'cpm': 0.500000, - 'rtb': { - 'video': { - 'content': '' - } - } - }] - }] - }; - let bidderRequest; - - let result = spec.interpretResponse({ body: response }, {bidderRequest}); - expect(result[0]).to.have.property('vastUrl'); - expect(result[0]).to.have.property('mediaType', 'video'); - }); - - it('handles native responses', () => { - let response1 = Object.assign({}, response); - response1.tags[0].ads[0].ad_type = 'native'; - response1.tags[0].ads[0].rtb.native = { - 'title': 'Native Creative', - 'desc': 'Cool description great stuff', - 'ctatext': 'Do it', - 'sponsored': 'AppNexus', - 'icon': { - 'width': 0, - 'height': 0, - 'url': 'http://cdn.adnxs.com/icon.png' - }, - 'main_img': { - 'width': 2352, - 'height': 1516, - 'url': 'http://cdn.adnxs.com/img.png' - }, - 'link': { - 'url': 'https://www.appnexus.com', - 'fallback_url': '', - 'click_trackers': ['http://nym1-ib.adnxs.com/click'] - }, - 'impression_trackers': ['http://example.com'], - }; - let bidderRequest; - - let result = spec.interpretResponse({ body: response1 }, {bidderRequest}); - expect(result[0].native.title).to.equal('Native Creative'); - expect(result[0].native.body).to.equal('Cool description great stuff'); - expect(result[0].native.cta).to.equal('Do it'); - expect(result[0].native.image.url).to.equal('http://cdn.adnxs.com/img.png'); - }); - }); -}); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 96916f3fa35..c95fe18c688 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -1,52 +1,405 @@ -import {expect} from 'chai'; -import Adapter from '../../../modules/appnexusBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; - -describe('AppNexus Adapter', () => { - let adapter; - - const REQUEST = { - 'bidderCode': 'appnexus', - 'requestId': 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', - 'bidderRequestId': '7101db09af0db2', - 'bids': [ +import { expect } from 'chai'; +import { spec } from 'modules/appnexusBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; + +describe('AppNexusAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + let bid = { + 'bidder': 'appnexus', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return true when required params found', () => { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'member': '1234', + 'invCode': 'ABCD' + }; + + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params are not passed', () => { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [ { 'bidder': 'appnexus', 'params': { - 'placementId': '4799418', - 'trafficSourceCode': 'source' + 'placementId': '10433394' }, - 'placementCode': '/19968336/header-bid-tag1', - 'sizes': [ - [728, 90], - [970, 90] - ], - 'bidId': '84ab500420319d', - 'bidderRequestId': '7101db09af0db2', - 'requestId': 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6' + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', } - ], - 'start': 1469479810130 - }; - - let sandbox; - let adLoaderStub; - beforeEach(() => { - sandbox = sinon.sandbox.create(); - sandbox.stub(bidManager, 'addBidResponse'); - adLoaderStub = sandbox.stub(adLoader, 'loadScript'); - }); + ]; - afterEach(() => { - sandbox.restore(); - }); + it('should add source and verison to the tag', () => { + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.sdk).to.exist; + expect(payload.sdk).to.deep.equal({ + source: 'pbjs', + version: '$prebid.version$' + }); + }); + + it('sends bid request to ENDPOINT via POST', () => { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.equal(ENDPOINT); + expect(request.method).to.equal('POST'); + }); + + it('should attach valid video params to the tag', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + video: { + id: 123, + minduration: 100, + foobar: 'invalid' + } + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + expect(payload.tags[0].video).to.deep.equal({ + id: 123, + minduration: 100 + }); + }); + + it('should attach valid user params to the tag', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + user: { + external_uid: '123', + foobar: 'invalid' + } + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.user).to.exist; + expect(payload.user).to.deep.equal({ + external_uid: '123', + }); + }); + + it('should attache native params to the request', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + title: {required: true}, + body: {required: true}, + image: {required: true, sizes: [{ width: 100, height: 100 }] }, + cta: {required: false}, + sponsoredBy: {required: true} + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ + title: {required: true}, + description: {required: true}, + main_image: {required: true, sizes: [{ width: 100, height: 100 }] }, + ctatext: {required: false}, + sponsored_by: {required: true} + }); + }); + + it('sets minimum native asset params when not provided on adunit', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + image: {required: true}, + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ + main_image: {required: true, sizes: [{}] }, + }); + }); + + it('does not overwrite native ad unit params with mimimum params', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + image: { + aspect_ratios: [{ + min_width: 100, + ratio_width: 2, + ratio_height: 3, + }] + } + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ + main_image: { + required: true, + aspect_ratios: [{ + min_width: 100, + ratio_width: 2, + ratio_height: 3, + }] + }, + }); + }); + + it('should convert keyword params to proper form and attaches to request', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + keywords: { + single: 'val', + singleArr: ['val'], + singleArrNum: [5], + multiValMixed: ['value1', 2, 'value3'], + singleValNum: 123, + badValue: {'foo': 'bar'} // should be dropped + } + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].keywords).to.deep.equal([{ + 'key': 'single', + 'value': ['val'] + }, { + 'key': 'singleArr', + 'value': ['val'] + }, { + 'key': 'singleArrNum', + 'value': ['5'] + }, { + 'key': 'multiValMixed', + 'value': ['value1', '2', 'value3'] + }, { + 'key': 'singleValNum', + 'value': ['123'] + }]); + }); + + it('should should add payment rules to the request', () => { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + usePaymentRule: true + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].use_pmt_rule).to.equal(true); + }); + }) + + describe('interpretResponse', () => { + let response = { + 'version': '3.0.0', + 'tags': [ + { + 'uuid': '3db3773286ee59', + 'tag_id': 10433394, + 'auction_id': '4534722592064951574', + 'nobid': false, + 'no_ad_url': 'http://lax1-ib.adnxs.com/no-ad', + 'timeout_ms': 10000, + 'ad_profile_id': 27079, + 'ads': [ + { + 'content_source': 'rtb', + 'ad_type': 'banner', + 'buyer_member_id': 958, + 'creative_id': 29681110, + 'media_type_id': 1, + 'media_subtype_id': 1, + 'cpm': 0.5, + 'cpm_publisher_currency': 0.5, + 'publisher_currency_code': '$', + 'client_initiated_ad_counting': true, + 'rtb': { + 'banner': { + 'content': '', + 'width': 300, + 'height': 250 + }, + 'trackers': [ + { + 'impression_urls': [ + 'http://lax1-ib.adnxs.com/impression' + ], + 'video_events': {} + } + ] + } + } + ] + } + ] + }; + + it('should get correct bid response', () => { + let expectedResponse = [ + { + 'requestId': '3db3773286ee59', + 'cpm': 0.5, + 'creativeId': 29681110, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '', + 'mediaType': 'banner', + 'currency': 'USD', + 'ttl': 300, + 'netRevenue': true + } + ]; + let bidderRequest; + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('handles nobid responses', () => { + let response = { + 'version': '0.0.1', + 'tags': [{ + 'uuid': '84ab500420319d', + 'tag_id': 5976557, + 'auction_id': '297492697822162468', + 'nobid': true + }] + }; + let bidderRequest; + + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(result.length).to.equal(0); + }); + + it('handles non-banner media responses', () => { + let response = { + 'tags': [{ + 'uuid': '84ab500420319d', + 'ads': [{ + 'ad_type': 'video', + 'cpm': 0.500000, + 'rtb': { + 'video': { + 'content': '' + } + } + }] + }] + }; + let bidderRequest; + + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(result[0]).to.have.property('vastUrl'); + expect(result[0]).to.have.property('descriptionUrl'); + expect(result[0]).to.have.property('mediaType', 'video'); + }); + + it('handles native responses', () => { + let response1 = Object.assign({}, response); + response1.tags[0].ads[0].ad_type = 'native'; + response1.tags[0].ads[0].rtb.native = { + 'title': 'Native Creative', + 'desc': 'Cool description great stuff', + 'ctatext': 'Do it', + 'sponsored': 'AppNexus', + 'icon': { + 'width': 0, + 'height': 0, + 'url': 'http://cdn.adnxs.com/icon.png' + }, + 'main_img': { + 'width': 2352, + 'height': 1516, + 'url': 'http://cdn.adnxs.com/img.png' + }, + 'link': { + 'url': 'https://www.appnexus.com', + 'fallback_url': '', + 'click_trackers': ['http://nym1-ib.adnxs.com/click'] + }, + 'impression_trackers': ['http://example.com'], + }; + let bidderRequest; - describe('callBids', () => { - it('should contain traffic_source_code', () => { - adapter = new Adapter(); - adapter.callBids(REQUEST); - expect(adLoaderStub.getCall(0).args[0]).to.contain('traffic_source_code=source'); + let result = spec.interpretResponse({ body: response1 }, {bidderRequest}); + expect(result[0].native.title).to.equal('Native Creative'); + expect(result[0].native.body).to.equal('Cool description great stuff'); + expect(result[0].native.cta).to.equal('Do it'); + expect(result[0].native.image.url).to.equal('http://cdn.adnxs.com/img.png'); }); }); }); diff --git a/test/spec/modules/atomxBidAdapter_spec.js b/test/spec/modules/atomxBidAdapter_spec.js deleted file mode 100644 index 646061912e7..00000000000 --- a/test/spec/modules/atomxBidAdapter_spec.js +++ /dev/null @@ -1,150 +0,0 @@ -var chai = require('chai'); -var Adapter = require('modules/atomxBidAdapter')(); -var Ajax = require('src/ajax'); -var adLoader = require('src/adloader'); -var bidmanager = require('src/bidmanager.js'); -var CONSTANTS = require('src/constants.json'); - -describe('Atomx adapter', function () { - var validData_1 = { - bids: [ - { - bidder: 'atomx', - bidId: 'bid_id', - params: {id: 1234}, - placementCode: 'ad-unit-1', - sizes: [[300, 250], [800, 600]] - } - ] - }; - var validData_2 = { - bids: [ - { - bidder: 'adtomx', - bidId: 'bid_id', - params: {id: 5678}, - placementCode: 'ad-unit-1', - sizes: [300, 250] - } - ] - }; - - var invalidData = { - bids: [ - { - bidder: 'atomx', - bidId: 'bid_id', - params: {}, - placementCode: 'ad-unit-1', - sizes: [[300, 250]] - } - ] - }; - - var responseWithAd = JSON.stringify({ - 'cpm': 2.2, - 'url': 'http://p.ato.mx/placement?id=1234', - 'width': 300, - 'height': 250, - 'code': 'ad-unit-1' - }); - var responseWithoutAd = JSON.stringify({ - 'cpm': 0, - 'url': 'http://p.ato.mx/placement?id=1234', - 'width': 300, - 'height': 250, - 'code': 'ad-unit-1' - }); - - var responseEmpty = ''; - var validJsonParams = { - id: '1234', - prebid: 'ad-unit-1', - size: '300x250' - }; - - describe('loads the tag code', function() { - var stubLoadScript = sinon.stub(adLoader, 'loadScript'); - Adapter.callBids(validData_1); - sinon.assert.calledOnce(stubLoadScript); - let url = stubLoadScript.firstCall.args[0]; - let callback = stubLoadScript.firstCall.args[1]; - expect(url).to.equal('http://s.ato.mx/b.js'); - expect(callback).to.be.a('function'); - }); - describe('bid request with valid data', function () { - var stubAjax; - beforeEach(function () { - window.atomx_prebid = function() { - return '/placement'; - }; - stubAjax = sinon.stub(Ajax, 'ajax'); - }); - afterEach(function () { - stubAjax.restore(); - }); - it('bid request should be called. sizes style -> [[],[]]', function () { - Adapter.callBids(validData_1); - sinon.assert.calledTwice(stubAjax); - }); - it('bid request should be called. sizes style -> []', function () { - Adapter.callBids(validData_2); - sinon.assert.calledOnce(stubAjax); - }); - it('ajax params should be matched', function () { - Adapter.callBids(validData_1); - sinon.assert.calledWith(stubAjax, sinon.match('/placement', function () { - }, validJsonParams, {method: 'GET'})); - }); - }); - describe('bid request with invalid data', function () { - var addBidResponse, stubAjax; - beforeEach(function () { - window.atomx_prebid = function() { - return '/placement'; - }; - addBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - stubAjax = sinon.stub(Ajax, 'ajax'); - }); - afterEach(function () { - addBidResponse.restore(); - stubAjax.restore(); - }); - it('ajax shouldn\'t be called', function () { - Adapter.callBids(invalidData); - sinon.assert.notCalled(stubAjax); - }); - it('bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID + '"', function () { - Adapter.callBids(invalidData); - expect(addBidResponse.firstCall.args[1].getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(addBidResponse.firstCall.args[1].bidderCode).to.equal('atomx'); - }); - }); - describe('bid response', function () { - var addBidResponse; - beforeEach(function () { - addBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - }); - afterEach(function () { - addBidResponse.restore(); - }); - it('with ad. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.GOOD + '"', function () { - Adapter.responseCallback(validData_1.bids[0], responseWithAd); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(arg.bidderCode).to.equal('atomx'); - }); - it('without ad. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID, function () { - Adapter.responseCallback(validData_1.bids[0], responseWithoutAd); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(arg.bidderCode).to.equal('atomx'); - }); - it('empty. bidmanager.addBidResponse status code must to be equal "' + CONSTANTS.STATUS.NO_BID, function () { - Adapter.responseCallback(validData_1.bids[0], responseEmpty); - var arg = addBidResponse.firstCall.args[1]; - expect(arg.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(arg.bidderCode).to.equal('atomx'); - }) - }); -}); diff --git a/test/spec/modules/bidfluenceBidAdapter_spec.js b/test/spec/modules/bidfluenceBidAdapter_spec.js deleted file mode 100644 index f623954fa9f..00000000000 --- a/test/spec/modules/bidfluenceBidAdapter_spec.js +++ /dev/null @@ -1,71 +0,0 @@ -describe('Bidfluence Adapter', () => { - const expect = require('chai').expect; - const adapter = require('modules/bidfluenceBidAdapter'); - const bidmanager = require('src/bidmanager'); - - var REQUEST = { - bidderCode: 'bidfluence', - sizes: [[300, 250]], - placementCode: 'div-1', - bids: [{ - bidder: 'bidfluence', - params: { - pubId: 'test', - adunitId: 'test' - } - }] - }; - - var RESPONSE = { - ad: 'ad-code', - cpm: 0.9, - width: 300, - height: 250, - placementCode: 'div-1' - }; - - var NO_RESPONSE = { - ad: 'ad-code', - cpm: 0, - width: 300, - height: 250, - placementCode: 'div-1' - }; - - it('Should exist and be a function', function () { - expect($$PREBID_GLOBAL$$.bfPbjsCB).to.exist.and.to.be.a('function'); - }); - - it('Shoud push a valid bid', () => { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - $$PREBID_GLOBAL$$._bidsRequested.push(REQUEST); - adapter(); - $$PREBID_GLOBAL$$.bfPbjsCB(RESPONSE); - - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - - expect(bidPlacementCode1).to.equal('div-1'); - expect(bidObject1.getStatusCode()).to.equal(1); - expect(bidObject1.bidderCode).to.equal('bidfluence'); - - stubAddBidResponse.restore(); - }); - - it('Shoud push an empty bid', () => { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - $$PREBID_GLOBAL$$._bidsRequested.push(REQUEST); - adapter(); - - $$PREBID_GLOBAL$$.bfPbjsCB(NO_RESPONSE); - - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - - expect(bidPlacementCode1).to.equal('div-1'); - expect(bidObject1.getStatusCode()).to.equal(2); - expect(bidObject1.bidderCode).to.equal('bidfluence'); - - stubAddBidResponse.restore(); - }); -}); diff --git a/test/spec/modules/c1xBidAdapter_spec.js b/test/spec/modules/c1xBidAdapter_spec.js deleted file mode 100644 index e1a48a5b701..00000000000 --- a/test/spec/modules/c1xBidAdapter_spec.js +++ /dev/null @@ -1,203 +0,0 @@ -import {expect} from 'chai'; -import C1XAdapter from 'modules/c1xBidAdapter'; -import bidmanager from 'src/bidmanager'; -import adLoader from 'src/adloader'; - -let getDefaultBidRequest = () => { - return { - bidderCode: 'c1x', - bids: [{ - bidder: 'c1x', - sizes: [[300, 250], [300, 600]], - params: { - siteId: '999', - pixelId: '9999', - placementCode: 'div-c1x-ht', - domain: 'http://c1exchange.com/' - } - }] - }; -}; - -let getDefaultBidResponse = () => { - return { - bid: true, - adId: 'div-c1x-ht', - cpm: 3.31, - ad: '
', - width: 300, - height: 250 - }; -}; - -describe('c1x adapter tests: ', () => { - let pbjs = window.$$PREBID_GLOBAL$$ || {}; - let stubLoadScript; - let adapter; - - function createBidderRequest(bids) { - let bidderRequest = getDefaultBidRequest(); - if (bids && Array.isArray(bids)) { - bidderRequest.bids = bids; - } - return bidderRequest; - } - - beforeEach(() => { - adapter = new C1XAdapter(); - }); - - describe('check callBids()', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - describe('creation of bid url', () => { - beforeEach(() => { - stubLoadScript = sinon.stub(adLoader, 'loadScript'); - }); - afterEach(() => { - stubLoadScript.restore(); - }); - it('should be called only once', () => { - adapter.callBids(getDefaultBidRequest()); - sinon.assert.calledOnce(stubLoadScript); - expect(window._c1xResponse).to.exist.and.to.be.a('function'); - }); - it('require parameters before call', () => { - let xhr; - let requests; - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = request => requests.push(request); - adapter.callBids(getDefaultBidRequest()); - expect(requests).to.be.empty; - xhr.restore(); - }); - it('should send with correct parameters', () => { - adapter.callBids(getDefaultBidRequest()); - let expectedUrl = stubLoadScript.getCall(0).args[0]; - sinon.assert.calledWith(stubLoadScript, expectedUrl); - }); - it('should hit endpoint with optional param', () => { - let bids = [{ - bidder: 'c1x', - sizes: [[300, 250], [300, 600]], - params: { - siteId: '999', - placementCode: 'div-c1x-ht', - endpoint: 'http://ht-integration.c1exchange.com:9000/ht', - floorPriceMap: { - '300x250': 4.00 - }, - dspid: '4288' - } - }]; - adapter.callBids(createBidderRequest(bids)); - let expectedUrl = stubLoadScript.getCall(0).args[0]; - sinon.assert.calledWith(stubLoadScript, expectedUrl); - bids[0].sizes = [[728, 90]]; - adapter.callBids(createBidderRequest(bids)); - sinon.assert.calledTwice(stubLoadScript); - }); - it('should hit default bidder endpoint', () => { - let bid = getDefaultBidRequest(); - bid.bids[0].params.endpoint = null; - adapter.callBids(bid); - let expectedUrl = stubLoadScript.getCall(0).args[0]; - sinon.assert.calledWith(stubLoadScript, expectedUrl); - }); - it('should throw error msg if no site id provided', () => { - let bid = getDefaultBidRequest(); - bid.bids[0].params.siteId = ''; - adapter.callBids(bid); - sinon.assert.notCalled(stubLoadScript); - }); - it('should not inject audience pixel if no pixelId provided', () => { - let bid = getDefaultBidRequest(); - let responsePId; - bid.bids[0].params.pixelId = ''; - adapter.callBids(bid); - }); - }); - describe('bid response', () => { - let server; - let stubAddBidResponse; - beforeEach(() => { - adapter = new C1XAdapter(); - server = sinon.fakeServer.create(); - stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - }); - - afterEach(() => { - server.restore(); - stubAddBidResponse.restore(); - }); - - it('callback function should exist', function () { - expect(pbjs._c1xResponse).to.exist.and.to.be.a('function'); - }); - it('should get JSONP from c1x bidder', function () { - let responses = []; - let stubC1XResponseFunc = sinon.stub(pbjs, '_c1xResponse'); - responses.push(getDefaultBidResponse()); - window._c1xResponse(JSON.stringify(responses)); - sinon.assert.calledOnce(stubC1XResponseFunc); - stubC1XResponseFunc.restore(); - }); - it('should be added to bidmanager after returned from bidder', () => { - let responses = []; - responses.push(getDefaultBidResponse()); - pbjs._c1xResponse(responses); - sinon.assert.calledOnce(stubAddBidResponse); - }); - it('should send correct arguments to bidmanager.addBidResponse', () => { - let responses = []; - responses.push(getDefaultBidResponse()); - pbjs._c1xResponse(JSON.stringify(responses)); - var responseAdId = stubAddBidResponse.getCall(0).args[0]; - var bidObject = stubAddBidResponse.getCall(0).args[1]; - expect(responseAdId).to.equal('div-c1x-ht'); - expect(bidObject.cpm).to.equal(3.31); - expect(bidObject.width).to.equal(300); - expect(bidObject.height).to.equal(250); - expect(bidObject.ad).to.equal('
'); - expect(bidObject.bidderCode).to.equal('c1x'); - sinon.assert.calledOnce(stubAddBidResponse); - }); - it('should response to bidmanager when it is a no bid', () => { - let responses = []; - responses.push({'bid': false, 'adId': 'div-gpt-ad-1494499685685-0'}); - pbjs._c1xResponse(responses); - let responseAdId = stubAddBidResponse.getCall(0).args[0]; - let bidObject = stubAddBidResponse.getCall(0).args[1]; - expect(responseAdId).to.equal('div-gpt-ad-1494499685685-0'); - expect(bidObject.statusMessage).to.equal('Bid returned empty or error response'); - sinon.assert.calledOnce(stubAddBidResponse); - }); - it('should show error when bidder sends invalid bid responses', () => { - let responses; - let adUnits = []; - let unit = {}; - let params = getDefaultBidRequest(); - - unit.bids = params.bids; - unit.code = '/123456/header-bid-tag-1'; - unit.sizes = [[300, 250]]; - adUnits.push(unit); - - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = [params]; - } else { - $$PREBID_GLOBAL$$._bidsRequested.push(params); - } - - $$PREBID_GLOBAL$$.adUnits = adUnits; - - pbjs._c1xResponse(responses); - let bidObject = stubAddBidResponse.getCall(0).args[1]; - expect(bidObject.statusMessage).to.equal('Bid returned empty or error response'); - sinon.assert.calledOnce(stubAddBidResponse); - }); - }); -}); diff --git a/test/spec/modules/carambolaBidAdapter_spec.js b/test/spec/modules/carambolaBidAdapter_spec.js deleted file mode 100644 index e68a5c9221d..00000000000 --- a/test/spec/modules/carambolaBidAdapter_spec.js +++ /dev/null @@ -1,139 +0,0 @@ -import {expect} from 'chai'; -import * as utils from 'src/utils'; -import CarambolaAdapter from 'modules/carambolaBidAdapter'; -import bidmanager from 'src/bidmanager'; - -const DEFAULT_BIDDER_REQUEST = { - bidderCode: 'carambola', - requestId: 'c9ad932a-41d9-4821-b6dc-0c8146029faf', - adId: '2e3daacdeed03d', - start: new Date().getTime(), - bids: [{ - bidder: 'carambola', - adId: '2e3daacdeed03d', - requestId: 'c9ad932a-41d9-4821-b6dc-0c8146029faf', - adUnitCode: 'cbola_prebid_code_97', - token: 'CGYCLyIy', - pageViewId: '22478638', - params: { - pid: 'hbtest', - did: 112591, - wid: 0 - } - }] -}; - -const DEFAULT_HB_RESPONSE = { - cpm: 0.1693953107111156, - ad: ' ', - token: '9cd6bf9c-433d-4663-b67f-da727f4cebff', - width: '300', - height: '250', - currencyCode: 'USD', - pageViewId: '22478638', - requestStatus: 1 - -}; - -describe('carambolaAdapter', function () { - let adapter; - - beforeEach(() => adapter = new CarambolaAdapter()); - - function createBidderRequest({bids, params} = {}) { - var bidderRequest = utils.deepClone(DEFAULT_BIDDER_REQUEST); - if (bids && Array.isArray(bids)) { - bidderRequest.bids = bids; - } - if (params) { - bidderRequest.bids.forEach(bid => bid.params = params); - } - return bidderRequest; - } - - describe('callBids()', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - - // bid request starts - describe('bid request', () => { - let xhr; - let requests; - - beforeEach(() => { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = request => requests.push(request); - }); - - afterEach(() => xhr.restore()); - - it('requires parameters to be made', () => { - adapter.callBids({}); - expect(requests[0]).to.be.empty; - }); - - it('should hit the default hb.carambo.la endpoint', () => { - adapter.callBids(DEFAULT_BIDDER_REQUEST); - expect(requests[0].url).to.contain('hb.carambo.la'); - }); - - it('should verifiy that a page_view_id is sent', () => { - adapter.callBids(DEFAULT_BIDDER_REQUEST); - expect(requests[0].url).to.contain('pageViewId='); - }); - - it('should should send the correct did', () => { - adapter.callBids(createBidderRequest({ - params: { - did: 112591, - wid: 0 - } - })); - expect(requests[0].url).to.contain('did=112591'); - }); - }); - // bid request ends - - // bid response starts - describe('bid response', () => { - let server; - - beforeEach(() => { - server = sinon.fakeServer.create(); - sinon.stub(bidmanager, 'addBidResponse'); - }); - - afterEach(() => { - server.restore(); - bidmanager.addBidResponse.restore(); - }); - - it('should be added to bidmanager if response is valid', () => { - server.respondWith(JSON.stringify(DEFAULT_HB_RESPONSE)); - adapter.callBids(DEFAULT_BIDDER_REQUEST); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - }); - - it('should be added to bidmanager with correct bidderCode', () => { - server.respondWith(JSON.stringify(DEFAULT_HB_RESPONSE)); - adapter.callBids(DEFAULT_BIDDER_REQUEST); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - expect(bidmanager.addBidResponse.firstCall.args[1]).to.have.property('bidderCode', 'carambola'); - }); - - it('should have pageViewId matching the pageViewId from related bid request', () => { - server.respondWith(JSON.stringify(DEFAULT_HB_RESPONSE)); - adapter.callBids(DEFAULT_BIDDER_REQUEST); - server.respond(); - expect(bidmanager.addBidResponse.calledOnce).to.be.true; - expect(bidmanager.addBidResponse.firstCall.args[1]) - .to.have.property('pvid', DEFAULT_BIDDER_REQUEST.bids[0].pageViewId); - }); - }); - // bid response ends - }); -}); diff --git a/test/spec/modules/centroBidAdapter_spec.js b/test/spec/modules/centroBidAdapter_spec.js deleted file mode 100644 index a4bceb5de39..00000000000 --- a/test/spec/modules/centroBidAdapter_spec.js +++ /dev/null @@ -1,225 +0,0 @@ -describe('centro adapter tests', function () { - var expect = require('chai').expect; - var assert = require('chai').assert; - var urlParse = require('url-parse'); - var querystringify = require('querystringify'); - - var adapter = require('modules/centroBidAdapter'); - var bidmanager = require('src/bidmanager'); - var adLoader = require('src/adloader'); - var utils = require('src/utils'); - - let stubLoadScript; - beforeEach(function () { - stubLoadScript = sinon.stub(adLoader, 'loadScript'); - }); - - afterEach(function () { - stubLoadScript.restore(); - }); - - var logErrorSpy; - beforeEach(function () { - logErrorSpy = sinon.spy(utils, 'logError'); - }); - - afterEach(function () { - logErrorSpy.restore(); - }); - - describe('creation of bid url', function () { - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = []; - } - - it('should fix parameter name', function () { - var params = { - bidderCode: 'centro', - bids: [ - { - bidder: 'centro', - sizes: [[300, 250]], - params: { - unit: 28136, - page_url: 'http://test_url.ru' - }, - bidId: '1234', - placementCode: 'div-gpt-ad-12345-1' - }, - { - bidder: 'centro', - sizes: [[728, 90]], - params: { - unit: 28137 - }, - bidId: '5678', - placementCode: 'div-gpt-ad-12345-2' - }, - { - bidder: 'centro', - sizes: [[728, 90]], - params: {}, - bidId: '9101112', - placementCode: 'div-gpt-ad-12345-3' - } - ] - }; - - adapter().callBids(params); - var bidUrl1 = stubLoadScript.getCall(0).args[0]; - var bidUrl2 = stubLoadScript.getCall(1).args[0]; - - sinon.assert.calledWith(logErrorSpy, 'Bid has no unit', 'centro'); - sinon.assert.calledWith(stubLoadScript, bidUrl1); - - var parsedBidUrl = urlParse(bidUrl1); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - var generatedCallback = 'window["adCentroHandler_28136300x2501234"]'; - - expect(parsedBidUrl.hostname).to.equal('staging.brand-server.com'); - expect(parsedBidUrl.pathname).to.equal('/hb'); - - expect(parsedBidUrlQueryString).to.have.property('s').and.to.equal('28136'); - expect(parsedBidUrlQueryString).to.have.property('url').and.to.equal('http://test_url.ru'); - expect(parsedBidUrlQueryString).to.have.property('sz').and.to.equal('300x250'); - expect(parsedBidUrlQueryString).to.have.property('callback').and.to.equal(generatedCallback); - - sinon.assert.calledWith(stubLoadScript, bidUrl2); - - parsedBidUrl = urlParse(bidUrl2); - parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - generatedCallback = 'window["adCentroHandler_28137728x905678"]'; - - expect(parsedBidUrl.hostname).to.equal('t.brand-server.com'); - expect(parsedBidUrl.pathname).to.equal('/hb'); - - expect(parsedBidUrlQueryString).to.have.property('s').and.to.equal('28137'); - expect(parsedBidUrlQueryString).to.have.property('url').and.to.equal(location.href); - expect(parsedBidUrlQueryString).to.have.property('sz').and.to.equal('728x90'); - expect(parsedBidUrlQueryString).to.have.property('callback').and.to.equal(generatedCallback); - }); - }); - - describe('handling of the callback response', function () { - if (typeof ($$PREBID_GLOBAL$$._bidsReceived) === 'undefined') { - $$PREBID_GLOBAL$$._bidsReceived = []; - } - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = []; - } - if (typeof ($$PREBID_GLOBAL$$._adsReceived) === 'undefined') { - $$PREBID_GLOBAL$$._adsReceived = []; - } - - var params = { - bidderCode: 'centro', - bids: [ - { - bidder: 'centro', - sizes: [[300, 250]], - params: { - unit: 28136 - }, - bidId: '12345', - placementCode: '/19968336/header-bid-tag-0' - }, - { - bidder: 'centro', - sizes: [[728, 90]], - params: { - unit: 111111 - }, - bidId: '12346', - placementCode: '/19968336/header-bid-tag-1' - }, - { - bidder: 'centro', - sizes: [[728, 90]], - params: { - unit: 222222 - }, - bidId: '12347', - placementCode: '/19968336/header-bid-tag-2' - }, - { - bidder: 'centro', - sizes: [[728, 90]], - params: { - unit: 333333 - }, - bidId: '12348', - placementCode: '/19968336/header-bid-tag-3' - } - ] - }; - - it('callback function should exist', function () { - adapter().callBids(params); - - expect(window['adCentroHandler_28136300x25012345']) - .to.exist.and.to.be.a('function'); - expect(window['adCentroHandler_111111728x9012346']) - .to.exist.and.to.be.a('function'); - }); - - it('bidmanager.addBidResponse should be called with correct arguments', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - adapter().callBids(params); - - var adUnits = new Array(); - var unit = new Object(); - unit.bids = params.bids; - unit.code = '/19968336/header-bid-tag'; - unit.sizes = [[300, 250], [728, 90]]; - adUnits.push(unit); - - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = [params]; - } else { - $$PREBID_GLOBAL$$._bidsRequested.push(params); - } - - $$PREBID_GLOBAL$$.adUnits = adUnits; - - var response = {'adTag': '
test content
', 'statusMessage': 'Bid available', 'height': 250, '_comment': '', 'value': 0.2, 'width': 300, 'sectionID': 28136}; - var response2 = {'adTag': '', 'statusMessage': 'No bid', 'height': 0, 'value': 0, 'width': 0, 'sectionID': 111111}; - var response3 = {'adTag': '', 'height': 0, 'value': 0, 'width': 0, 'sectionID': 222222}; - var response4 = ''; - - window['adCentroHandler_28136300x25012345'](response); - window['adCentroHandler_111111728x9012346'](response2); - window['adCentroHandler_222222728x9012347'](response3); - window['adCentroHandler_333333728x9012348'](response4); - - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - var bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0]; - var bidObject2 = stubAddBidResponse.getCall(1).args[1]; - var bidPlacementCode3 = stubAddBidResponse.getCall(2).args[0]; - var bidObject3 = stubAddBidResponse.getCall(2).args[1]; - var bidPlacementCode4 = stubAddBidResponse.getCall(3).args[0]; - var bidObject4 = stubAddBidResponse.getCall(3).args[1]; - - expect(logErrorSpy.getCall(0).args[0]).to.equal('Requested unit is 222222. Bid has missmatch format.'); - expect(logErrorSpy.getCall(1).args[0]).to.equal('Requested unit is 333333. Response has no bid.'); - - expect(bidPlacementCode1).to.equal('/19968336/header-bid-tag-0'); - expect(bidObject1.cpm).to.equal(0.2); - expect(bidObject1.ad).to.equal('
test content
'); - expect(bidObject1.width).to.equal(300); - expect(bidObject1.height).to.equal(250); - expect(bidObject1.getStatusCode()).to.equal(1); - expect(bidObject1.bidderCode).to.equal('centro'); - - expect(bidPlacementCode2).to.equal('/19968336/header-bid-tag-1'); - expect(bidObject2.getStatusCode()).to.equal(2); - expect(bidPlacementCode3).to.equal('/19968336/header-bid-tag-2'); - expect(bidObject3.getStatusCode()).to.equal(2); - expect(bidPlacementCode4).to.equal('/19968336/header-bid-tag-3'); - expect(bidObject4.getStatusCode()).to.equal(2); - - stubAddBidResponse.restore(); - }); - }); -}); diff --git a/test/spec/modules/colossussspBidAdapter_spec.js b/test/spec/modules/colossussspBidAdapter_spec.js deleted file mode 100644 index e8435d90679..00000000000 --- a/test/spec/modules/colossussspBidAdapter_spec.js +++ /dev/null @@ -1,127 +0,0 @@ -import { expect } from 'chai'; -import Adapter from '../../../modules/colossussspBidAdapter'; -import adapterManager from 'src/adaptermanager'; -import bidManager from 'src/bidmanager'; -import CONSTANTS from 'src/constants.json'; - -describe('ColossusSSP adapter tests', function () { - let sandbox; - const adUnit = { - code: 'colossusssp', - sizes: [[300, 250], [300, 600]], - bids: [{ - bidder: 'colossusssp', - params: { - placement_id: 0 - } - }] - }; - - const response = { - ad_id: 15, - adm: '
Bid Response
', - cpm: 0.712, - deal: '5e1f0a8f2aa1', - width: 300, - height: 250 - }; - - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('ColossusSSP callBids validation', () => { - let bids, - server; - - beforeEach(() => { - bids = []; - server = sinon.fakeServer.create(); - sandbox.stub(bidManager, 'addBidResponse', (elemId, bid) => { - bids.push(bid); - }); - }); - - afterEach(() => { - server.restore(); - }); - - let adapter = adapterManager.bidderRegistry['colossusssp']; - - it('Valid bid-request', () => { - sandbox.stub(adapter, 'callBids'); - adapterManager.callBids({ - adUnits: [clone(adUnit)] - }); - - let bidderRequest = adapter.callBids.getCall(0).args[0]; - - expect(bidderRequest).to.have.property('bids') - .that.is.an('array') - .with.lengthOf(1); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .to.have.property('bidder', 'colossusssp'); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('sizes') - .that.is.an('array') - .with.lengthOf(2) - .that.deep.equals(adUnit.sizes); - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('params') - .to.have.property('placement_id', 0); - }); - - it('Valid bid-response', () => { - server.respondWith(JSON.stringify( - response - )); - adapterManager.callBids({ - adUnits: [clone(adUnit)] - }); - server.respond(); - - expect(bids).to.be.lengthOf(1); - expect(bids[0].getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bids[0].bidderCode).to.equal('colossusssp'); - expect(bids[0].width).to.equal(300); - expect(bids[0].height).to.equal(250); - expect(bids[0].cpm).to.equal(0.712); - expect(bids[0].dealId).to.equal('5e1f0a8f2aa1'); - }); - }); - - describe('MAS mapping / ordering', () => { - let masSizeOrdering = Adapter.masSizeOrdering; - - it('should not include values without a proper mapping', () => { - let ordering = masSizeOrdering([[320, 50], [42, 42], [300, 250], [640, 480], [0, 0]]); - expect(ordering).to.deep.equal([15, 43, 65]); - }); - - it('should sort values without any MAS priority sizes in regular ascending order', () => { - let ordering = masSizeOrdering([[320, 50], [640, 480], [200, 600]]); - expect(ordering).to.deep.equal([43, 65, 119]); - }); - - it('should sort MAS priority sizes in the proper order w/ rest ascending', () => { - let ordering = masSizeOrdering([[320, 50], [640, 480], [300, 250], [200, 600]]); - expect(ordering).to.deep.equal([15, 43, 65, 119]); - - ordering = masSizeOrdering([[320, 50], [300, 250], [640, 480], [200, 600], [728, 90]]); - expect(ordering).to.deep.equal([15, 2, 43, 65, 119]); - - ordering = masSizeOrdering([ [320, 50], [640, 480], [200, 600], [728, 90]]); - expect(ordering).to.deep.equal([2, 43, 65, 119]); - }) - }); -}); - -function clone(obj) { - return JSON.parse(JSON.stringify(obj)); -} diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index a64a1d956c4..1d62cba72c1 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -3,7 +3,6 @@ import {spec} from 'modules/conversantBidAdapter'; import * as utils from 'src/utils'; var Adapter = require('modules/conversantBidAdapter'); -var bidManager = require('src/bidmanager'); describe('Conversant adapter tests', function() { const siteId = '108060'; diff --git a/test/spec/modules/coxBidAdapter_spec.js b/test/spec/modules/coxBidAdapter_spec.js deleted file mode 100644 index ee1eb991f23..00000000000 --- a/test/spec/modules/coxBidAdapter_spec.js +++ /dev/null @@ -1,120 +0,0 @@ -import Adapter from 'modules/coxBidAdapter'; -import bidManager from 'src/bidmanager'; -import adLoader from 'src/adloader'; -import {expect} from 'chai'; - -describe('CoxAdapter', () => { - let adapter; - let loadScriptStub; - let addBidResponseSpy; - - let emitScript = (script) => { - let node = document.createElement('script'); - node.type = 'text/javascript'; - node.appendChild(document.createTextNode(script)); - document.getElementsByTagName('head')[0].appendChild(node); - }; - - beforeEach(() => { - adapter = new Adapter(); - addBidResponseSpy = sinon.spy(bidManager, 'addBidResponse'); - }); - - afterEach(() => { - loadScriptStub.restore(); - addBidResponseSpy.restore(); - }); - - describe('response handling', () => { - const normalResponse = 'cdsTag.__callback__({"zones":{"as2000005991707":{"ad" : "

FOO<\/h1>","uid" : "","price" : 1.51,"floor" : 0,}},"tpCookieSync":"

FOOKIE<\/h1>"})'; - const zeroPriceResponse = 'cdsTag.__callback__({"zones":{"as2000005991707":{"ad" : "

DEFAULT FOO<\/h1>","uid" : "","price" : 0,"floor" : 0,}},"tpCookieSync":"

FOOKIE<\/h1>"})'; - const incompleteResponse = 'cdsTag.__callback__({"zones":{},"tpCookieSync":"

FOOKIE<\/h1>"})'; - - const oneBidConfig = { - bidderCode: 'cox', - bids: [{ - bidder: 'cox', - placementCode: 'FOO456789', - sizes: [300, 250], - params: { size: '300x250', id: 2000005991707, siteId: 2000100948180, env: 'PROD' }, - }] - }; - - // ===== 1 - it('should provide a correctly populated Bid given a valid response', () => { - loadScriptStub = sinon.stub(adLoader, 'loadScript', () => { emitScript(normalResponse); }) - - adapter.callBids(oneBidConfig); - - let bid = addBidResponseSpy.args[0][1]; - expect(bid.cpm).to.equal(1.51); - expect(bid.ad).to.be.a('string'); - expect(bid.bidderCode).to.equal('cox'); - }); - - // ===== 2 - it('should provide an empty Bid given a zero-price response', () => { - loadScriptStub = sinon.stub(adLoader, 'loadScript', () => { emitScript(zeroPriceResponse); }) - - adapter.callBids(oneBidConfig); - - let bid = addBidResponseSpy.args[0][1]; - expect(bid.cpm).to.not.be.ok - expect(bid.ad).to.not.be.ok; - }); - - // ===== 3 - it('should provide an empty Bid given an incomplete response', () => { - loadScriptStub = sinon.stub(adLoader, 'loadScript', () => { emitScript(incompleteResponse); }) - - adapter.callBids(oneBidConfig); - - let bid = addBidResponseSpy.args[0][1]; - expect(bid.cpm).to.not.be.ok - expect(bid.ad).to.not.be.ok; - }); - - // ===== 4 - it('should not provide a Bid given no response', () => { - loadScriptStub = sinon.stub(adLoader, 'loadScript', () => { emitScript(''); }); - - adapter.callBids(oneBidConfig); - - expect(addBidResponseSpy.callCount).to.equal(0); - }); - }); - - describe('request generation', () => { - const missingBidsConfig = { - bidderCode: 'cox', - bids: null, - }; - const missingParamsConfig = { - bidderCode: 'cox', - bids: [{ - bidder: 'cox', - placementCode: 'FOO456789', - sizes: [300, 250], - params: null, - }] - }; - - // ===== 5 - it('should not make an ad call given missing bids in config', () => { - loadScriptStub = sinon.stub(adLoader, 'loadScript'); - - adapter.callBids(missingBidsConfig); - - expect(loadScriptStub.callCount).to.equal(0); - }); - - // ===== 6 - it('should not make an ad call given missing params in config', () => { - loadScriptStub = sinon.stub(adLoader, 'loadScript'); - - adapter.callBids(missingParamsConfig); - - expect(loadScriptStub.callCount).to.equal(0); - }); - }); -}); diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js deleted file mode 100644 index 68c554c7cb4..00000000000 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ /dev/null @@ -1,274 +0,0 @@ -import Adapter from '../../../modules/criteoBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import { ajax } from '../../../src/ajax' -import { expect } from 'chai'; - -var CONSTANTS = require('../../../src/constants'); - -/* ------------ Publishertag stub begin ------------ */ -before(() => { - window.Criteo = { - PubTag: { - DirectBidding: { - DirectBiddingSlot: function DirectBiddingSlot(placementCode, zoneid, nativeCallback, transactionId, sizes) { - return { - impId: placementCode, - nativeCallback: nativeCallback - }; - }, - - DirectBiddingUrlBuilder: function DirectBiddingUrlBuilder(isAudit) { return {} }, - - DirectBiddingEvent: function DirectBiddingEvent(profileId, urlBuilder, slots, success, error, timeout) { - return { - slots: slots, - eval: function () { - var callbacks = { - error: error, - success: success - } - ajax('//bidder.criteo.com/cdb', callbacks) - } - } - }, - - Size: function Size(width, height) { return {width: width, height: height} } - } - } - }; - - window.criteo_pubtag = window.criteo_pubtag || { - push: function (event) { - event.eval(); - } - } - - window.Criteo.events = window.Criteo.events || []; - window.Criteo.events.push = function (elem) { - if (typeof elem === 'function') { - elem(); - } - }; -}); -/* ------------ Publishertag stub end ------------ */ - -describe('criteo adapter test', () => { - let adapter; - let stubAddBidResponse; - - let validBid = { - bidderCode: 'criteo', - bids: [ - { - bidder: 'criteo', - placementCode: 'foo', - sizes: [[250, 350]], - params: { - zoneId: 32934, - audit: 'true' - } - } - ] - }; - - let validResponse = { slots: [{ impid: 'foo', cpm: 1.12, creative: "" }] }; - let invalidResponse = { slots: [{ 'impid': 'unknownSlot' }] } - - let validMultiBid = { - bidderCode: 'criteo', - bids: [ - { - bidder: 'criteo', - placementCode: 'foo', - sizes: [[250, 350]], - params: { - zoneId: 32934, - audit: 'true' - } - }, - { - bidder: 'criteo', - placementCode: 'bar', - sizes: [[250, 350]], - params: { - zoneId: 32935, - audit: 'true' - } - } - ] - }; - - let validNativeResponse = { slots: [{ impid: 'foo', cpm: 1.12, native: { productName: 'product0' } }] }; - let validNativeBid = { - bidderCode: 'criteo', - bids: [ - { - bidder: 'criteo', - placementCode: 'foo', - sizes: [[250, 350]], - params: { - zoneId: 32934, - audit: 'true', - nativeCallback: function (nativeJson) { console.log('Product name: ' + nativeJson.productName) } - } - } - ] - } - - beforeEach(() => { - adapter = new Adapter(); - }); - - afterEach(() => { - stubAddBidResponse.restore(); - }); - - describe('adding bids to the manager', () => { - let server; - - beforeEach(() => { - server = sinon.fakeServer.create({ autoRespond: true, respondImmediately: true }); - server.respondWith(JSON.stringify(validResponse)); - }); - - afterEach(() => { - server.restore(); - }); - - it('adds bid for valid request', (done) => { - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.GOOD }); - done(); - }); - - adapter.callBids(validBid); - }); - - it('adds bid for multibid valid request', (done) => { - let callCount = 0; - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - callCount++; - - if (callCount == 2) { done(); } - }); - - adapter.callBids(validMultiBid); - }); - - it('adds bidderCode to the response of a valid request', (done) => { - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.have.property('bidderCode', 'criteo'); - done(); - }); - - adapter.callBids(validBid); - }); - - it('adds cpm to the response of a valid request', (done) => { - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.have.property('cpm', 1.12); - done(); - }); - adapter.callBids(validBid); - }); - - it('adds creative to the response of a valid request', (done) => { - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.have.property('ad', ""); - done(); - }); - adapter.callBids(validBid); - }); - }); - - describe('adding bids to the manager with native bids', () => { - let server; - - beforeEach(() => { - server = sinon.fakeServer.create({ autoRespond: true, respondImmediately: true }); - server.respondWith(JSON.stringify(validNativeResponse)); - }); - - afterEach(() => { - server.restore(); - }); - - it('adds creative to the response of a native valid request', (done) => { - stubAddBidResponse = sinon.stub( - bidManager, 'addBidResponse', - function (adUnitCode, bid) { - let expectedAdProperty = ``; - - expect(bid).to.have.property('ad', expectedAdProperty); - done(); - }); - adapter.callBids(validNativeBid); - }); - }); - - describe('dealing with unexpected situations', () => { - let server; - - beforeEach(() => { - server = sinon.fakeServer.create({ autoRespond: true, respondImmediately: true }); - }); - - afterEach(() => { - server.restore(); - }); - - it('no bid if cdb handler responds with no bid empty string response', (done) => { - server.respondWith(''); - - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.NO_BID }); - done(); - }); - - adapter.callBids(validBid); - }); - - it('no bid if cdb handler responds with no bid empty object response', (done) => { - server.respondWith('{ }'); - - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.NO_BID }); - done(); - }); - - adapter.callBids(validBid); - }); - - it('no bid if cdb handler responds with HTTP error', (done) => { - server.respondWith([500, {}, 'Internal Server Error']); - - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.NO_BID }); - done(); - }); - - adapter.callBids(validBid); - }); - - it('no bid if response is invalid because response slots don\'t match input slots', (done) => { - server.respondWith(JSON.stringify(invalidResponse)); - - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.NO_BID }); - done(); - }); - - adapter.callBids(validBid); - }); - }); -}); diff --git a/test/spec/modules/currency_spec.js b/test/spec/modules/currency_spec.js index 06faa5665c9..37bb01b7c16 100644 --- a/test/spec/modules/currency_spec.js +++ b/test/spec/modules/currency_spec.js @@ -6,16 +6,21 @@ import { import { setConfig, addBidResponseHook, - currencySupportEnabled, currencyRates } from 'modules/currency'; +import { createHook } from 'src/hook'; + var assert = require('chai').assert; var expect = require('chai').expect; describe('currency', function () { let fakeCurrencyFileServer; + + let fn = sinon.spy(); + let hookFn = createHook('asyncSeries', fn, 'addBidResponse'); + beforeEach(() => { fakeCurrencyFileServer = sinon.fakeServer.create(); }); diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js index 07439be126c..f7895efa2f2 100644 --- a/test/spec/modules/dfpAdServerVideo_spec.js +++ b/test/spec/modules/dfpAdServerVideo_spec.js @@ -4,7 +4,6 @@ import parse from 'url-parse'; import buildDfpVideoUrl from 'modules/dfpAdServerVideo'; import { parseQS } from 'src/url'; import adUnit from 'test/fixtures/video/adUnit'; -import { newConfig } from 'src/config'; const bid = { videoCacheKey: 'abc', @@ -131,9 +130,6 @@ describe('The DFP video support module', () => { }); it('should not overwrite an existing description_url for object input and cache disabled', () => { - const config = newConfig(); - config.setConfig({ usePrebidCache: true }); - const bidCopy = Object.assign({}, bid); bidCopy.vastUrl = 'vastUrl.example'; diff --git a/test/spec/modules/districtmDMXBidAdapter_spec.js b/test/spec/modules/districtmDMXBidAdapter_spec.js deleted file mode 100644 index 6fc83d88e6d..00000000000 --- a/test/spec/modules/districtmDMXBidAdapter_spec.js +++ /dev/null @@ -1,245 +0,0 @@ -/** - * Created by stevealliance on 2016-11-15. - */ - -import {expect} from 'chai'; -import {should} from 'chai'; -import Adaptor from '../../../modules/districtmDMXBidAdapter'; - -import adLoader from '../../../src/adloader'; - -var _each = function(obj, fn) { - for (var o in obj) { - fn(o, obj[o]); - } -} - -let districtm; -const PREBID_RESPONSE = function() { - return { - result: { - cpm: '3.45', - callbackId: '1490bd6bdc59ce', - width: 300, - height: 250, - banner: 'html' - }, - callback_uid: '1490bd6bdc59ce' - }; -} -const PREBID_PARAMS = { - bidderCode: 'districtmDMX', - requestId: '5ccedbd5-86c1-436f-8649-964262461eac', - bidderRequestId: '1490bd6bdc59ce', - start: new Date().getTime(), - bids: [{ - bidder: 'districtmDMX', - bidId: '84ab500420319d', - bidderRequestId: '1490bd6bdc59ce', - requestId: '5ccedbd5-86c1-436f-8649-964262461eac', - placementCode: 'golden', - params: { - placement: 109801, - floor: '1.00' - }, - sizes: [[300, 250], [300, 600]] - }] -}; - -function resetDm() { - window.hb_dmx_res = undefined; -} - -function activated() { - window.hb_dmx_res = { - ssp: {}, - bh() { - - }, - auction: { - fixSize(s) { - let size; - if (!Array.isArray(s[0])) { - size = [s[0] + 'x' + s[1]]; - } else { - size = s.map(ss => { - return ss[0] + 'x' + ss[1]; - }) - } - - return size; - }, - - run(a, b, c) { - - } - } - } -} - -function definitions() { - districtm.callBids({ - bidderCode: 'districtmDMX', - bids: [ - { - bidder: 'districtmDMX', - adUnitCode: 'golden', - sizes: [[728, 90]], - params: { - siteId: '101000' - } - }, - { - bidder: 'districtmDMX', - adUnitCode: 'stevealliance', - sizes: [[300, 250]], - params: { - siteId: '101000' - } - } - ] - }); -} -describe('DistrictM adapter test', () => { - describe('File loading', () => { - let districtm; - afterEach(() => { - districtm = new Adaptor(); - adLoader.loadScript(districtm.districtUrl, function() {}); - }) - - it('For loading file ', () => { - expect(!window.hb_dmx_res).to.equal(true); - }) - }) - - describe('check for library do exists', () => { - it('library was not loaded', () => { - expect(!window.hb_dmx_res).to.equal(true); - }) - - it('library is now available', () => { - activated(); - - expect(!!window.hb_dmx_res).to.equal(true); - }) - }) - - describe('Check if size get clean', () => { - beforeEach(() => { - activated(); - }) - it('size clean up using fixe size', () => { - activated(); - - expect(window.hb_dmx_res.auction.fixSize([728, 90])[0]).to.equal(['728x90'][0]); - expect(window.hb_dmx_res.auction.fixSize([[300, 250], [300, 600]]).toString()).to.equal(['300x250', '300x600'].toString()); - }) - }) - - describe('Check call bids return no errors', () => { - let districtm; - beforeEach(() => { - districtm = new Adaptor(); - }); - it('check value push using cal bids', () => { - let obj = districtm.callBids(PREBID_PARAMS); - obj.should.have.property('bidderCode'); - obj.should.have.property('requestId'); - obj.should.have.property('bidderRequestId'); - obj.should.have.property('start'); - obj.should.have.property('bids'); - }) - it('check if value got pass correctly for DM params', () => { - let dm = districtm.callBids(PREBID_PARAMS).bids.map(bid => bid); - dm.forEach(a => { - a.should.have.property('bidder'); - a.should.have.property('requestId'); - a.should.have.property('bidderRequestId'); - a.should.have.property('placementCode'); - a.should.have.property('params'); - a.should.have.property('sizes'); - expect(a.bidder).to.equal('districtmDMX'); - expect(a.placementCode).to.equal('golden'); - expect(a.params.placement).to.equal(109801); - }) - }) - }) - - describe('Run prebid definitions !', () => { - let districtm; - beforeEach(() => { - districtm = new Adaptor(); - }) - - it('Run and return send bids', () => { - let sendBids = districtm.sendBids(PREBID_PARAMS); - sendBids.forEach(sb => { - expect(sb.sizes.toString()).to.equal([[300, 250], [300, 600]].toString()); - }) - }) - }) - - describe('HandlerRes function test', () => { - let districtm; - - beforeEach(() => { - districtm = new Adaptor(); - }) - - it('it\'s now time to play with the response ...', () => { - let result = districtm.handlerRes(PREBID_RESPONSE(), PREBID_PARAMS); - _each(result, function(k, v) { - - }) - - expect(result.cpm).to.equal('3.45'); - expect(result.width).to.equal(300); - expect(result.height).to.equal(250); - expect(result.ad).to.equal('html'); - }) - it('it\'s now time to play with the response failure...', () => { - let result = districtm.handlerRes({result: {cpm: 0}}, PREBID_PARAMS); - - result.should.have.property('bidderCode'); - }) - }) - - describe('look at the adloader', () => { - let districtm; - beforeEach(() => { - districtm = new Adaptor(); - sinon.stub(adLoader, 'loadScript'); - }) - - it('Verify districtm library is downloaded if nessesary', () => { - resetDm(); - districtm.callBids(PREBID_PARAMS); - let libraryLoadCall = adLoader.loadScript.firstCall.args[0]; - let callback = adLoader.loadScript.firstCall.args[1]; - expect(libraryLoadCall).to.equal('http://prebid.districtm.ca/lib.js'); - expect(callback).to.be.a('function'); - }); - - afterEach(() => { - adLoader.loadScript.restore(); - }) - }); - describe('run send bid from within !!!', () => { - beforeEach(() => { - districtm = new Adaptor(); - sinon.stub(districtm, 'sendBids'); - }) - - it('last test on send bids', () => { - resetDm(); - districtm.sendBids(PREBID_PARAMS); - expect(districtm.sendBids.calledOnce).to.be.true; - expect(districtm.sendBids.firstCall.args[0]).to.be.a('object'); - }); - - afterEach(() => { - districtm.sendBids.restore(); - }) - }); -}); diff --git a/test/spec/modules/eplanningBidAdapter_spec.js b/test/spec/modules/eplanningBidAdapter_spec.js deleted file mode 100644 index bf09f42f6e7..00000000000 --- a/test/spec/modules/eplanningBidAdapter_spec.js +++ /dev/null @@ -1,112 +0,0 @@ -describe('eplanning adapter tests', function () { - var urlParse = require('url-parse'); - var querystringify = require('querystringify'); - var adapter = require('modules/eplanningBidAdapter'); - var adLoader = require('src/adloader'); - var expect = require('chai').expect; - var bidmanager = require('src/bidmanager'); - var CONSTANTS = require('src/constants.json'); - - var DEFAULT_PARAMS = { - bidderCode: 'eplanning', - bids: [{ - code: 'div-gpt-ad-1460505748561-0', - sizes: [[300, 250], [300, 200]], - bidder: 'eplanning', - params: { - ci: '18f66' - } - }] - }; - - var PARAMS_SERVER_TEST = { - bidderCode: 'eplanning', - bids: [{ - code: 'div-gpt-ad-1460505748561-0', - sizes: [[300, 250], [300, 600]], - bidder: 'eplanning', - params: { - ci: '18f66', - t: '1' - } - }] - }; - - var RESPONSE_AD = { - bids: [{ - placementCode: 'div-gpt-ad-1460505748561-0', - ad: { - ad: '

test ad

', - cpm: 1, - width: 300, - height: 250 - } - }] - }; - - var RESPONSE_EMPTY = { - bids: [{ - placementCode: 'div-gpt-ad-1460505748561-0' - }] - }; - - var stubAddBidResponse; - - describe('eplanning tests', function() { - beforeEach(function() { - stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - }); - afterEach(function() { - stubAddBidResponse.restore(); - }); - - it('callback function should exist', function() { - expect($$PREBID_GLOBAL$$.processEPlanningResponse).to.exist.and.to.be.a('function'); - }); - - it('creates a bid response if bid exists', function() { - adapter().callBids(DEFAULT_PARAMS); - $$PREBID_GLOBAL$$.processEPlanningResponse(RESPONSE_AD); - - var bidPlacementCode = stubAddBidResponse.getCall(0).args[0]; - var bidObject = stubAddBidResponse.getCall(0).args[1]; - - expect(bidPlacementCode).to.equal('div-gpt-ad-1460505748561-0'); - expect(bidObject.cpm).to.equal(1); - expect(bidObject.ad).to.equal('

test ad

'); - expect(bidObject.width).to.equal(300); - expect(bidObject.height).to.equal(250); - expect(bidObject.getStatusCode()).to.equal(1); - expect(bidObject.bidderCode).to.equal('eplanning'); - }); - - it('creates an empty bid response if there is no bid', function() { - adapter().callBids(DEFAULT_PARAMS); - $$PREBID_GLOBAL$$.processEPlanningResponse(RESPONSE_EMPTY); - - var bidPlacementCode = stubAddBidResponse.getCall(0).args[0]; - var bidObject = stubAddBidResponse.getCall(0).args[1]; - - expect(bidPlacementCode).to.equal('div-gpt-ad-1460505748561-0'); - expect(bidObject.getStatusCode()).to.equal(2); - expect(bidObject.bidderCode).to.equal('eplanning'); - }); - - it('creates a bid response and sync users register ad', function() { - adapter().callBids(DEFAULT_PARAMS); - window.hbpb.rH({ - 'sI': { 'k': '18f66' }, - 'sec': { 'k': 'ROS' }, - 'sp': [ { 'k': 'div-gpt-ad-1460505748561-0', 'a': [{ 'w': 300, 'h': 250, 'adm': '

test ad

', 'pr': 1 }] } ], - 'cs': [ - '//test.gif', - { 'j': true, u: '//test.js' }, - { 'ifr': true, u: '//test.html', data: { 'test': 1 } } - ] - }); - var bidPlacementCode = stubAddBidResponse.getCall(0).args[0]; - var bidObject = stubAddBidResponse.getCall(0).args[1]; - expect(bidObject.getStatusCode()).to.equal(2); - }); - }); -}); diff --git a/test/spec/modules/essensBidAdapter_spec.js b/test/spec/modules/essensBidAdapter_spec.js deleted file mode 100644 index aad3d15b0a9..00000000000 --- a/test/spec/modules/essensBidAdapter_spec.js +++ /dev/null @@ -1,828 +0,0 @@ -import { expect } from 'chai' -import Adapter from 'modules/essensBidAdapter' -import bidmanager from 'src/bidmanager' -import adLoader from 'src/adloader' -describe('Essens adapter tests', function () { - describe('Test callbid method ', function () { - let stubLoadScript - beforeEach(() => { - stubLoadScript = sinon.stub(adLoader, 'loadScript') - }) - - afterEach(() => - stubLoadScript.restore() - ) - - it('bid request without bid', () => { - const essensAdapter = new Adapter() - essensAdapter.callBids() - sinon.assert.notCalled(stubLoadScript) - }) - - it('bid request with missing parameter', () => { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1' - } - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - sinon.assert.notCalled(stubLoadScript) - }) - - it('Bid request with wrong parameter', () => { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'placement1-for_essensT1', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - randomParam: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - sinon.assert.notCalled(stubLoadScript) - }) - - it('add one valid requests', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'placement1-for_essensT1', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - const url = stubLoadScript.getCall(0).args[0] - const payload = decodeURIComponent(url.split('&bid=')[1]) - const payloadJson = JSON.parse(payload) - - expect(payloadJson.ua).to.exist.and.to.be.a('string') - expect(payloadJson.url).to.exist.and.to.be.a('string') - expect(Object.keys(payloadJson.imp).length).to.equal(1) - expect(payloadJson.imp[0].impressionId).to.equal('placement1-for_essensT1') - expect(payloadJson.imp[0].placementId).to.equal('placement1') - expect(Object.keys(payloadJson.imp[0].sizes).length).to.equal(2) - expect(payloadJson.imp[0].sizes[0]).to.equal('100x110') - expect(payloadJson.imp[0].sizes[1]).to.equal('200x210') - sinon.assert.calledOnce(stubLoadScript) - }) - it('add more than one valid requests', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'placement1-for_essensT2', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1', - bidderRequestId: 'impression-for-essens-1', - }, - { - bidId: 'placement2-for_essensT2', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement2' - }, - sizes: [ - [300, 310], - [400, 410] - ], - placementCode: 'div-media1-side_banner-1', - bidderRequestId: 'impression-for-essens-1', - }, - { - bidId: 'placement3-for_essensT2', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement3' - }, - sizes: [ - [500, 510], - [600, 610] - ], - placementCode: 'div-media1-side_banner-2', - bidderRequestId: 'impression-for-essens-1', - }, - ] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - const url = stubLoadScript.getCall(0).args[0] - const payload = decodeURIComponent(url.split('&bid=')[1]) - const payloadJson = JSON.parse(payload) - - expect(payloadJson.ua).to.exist.and.to.be.a('string') - expect(payloadJson.url).to.exist.and.to.be.a('string') - expect(Object.keys(payloadJson.imp).length).to.equal(3) - expect(payloadJson.imp[0].impressionId).to.equal('placement1-for_essensT2') - expect(payloadJson.imp[0].placementId).to.equal('placement1') - expect(Object.keys(payloadJson.imp[0].sizes).length).to.equal(2) - expect(payloadJson.imp[0].sizes[0]).to.equal('100x110') - expect(payloadJson.imp[0].sizes[1]).to.equal('200x210') - - expect(payloadJson.imp[1].impressionId).to.equal('placement2-for_essensT2') - expect(payloadJson.imp[1].placementId).to.equal('placement2') - expect(Object.keys(payloadJson.imp[1].sizes).length).to.equal(2) - expect(payloadJson.imp[1].sizes[0]).to.equal('300x310') - expect(payloadJson.imp[1].sizes[1]).to.equal('400x410') - - expect(payloadJson.imp[2].impressionId).to.equal('placement3-for_essensT2') - expect(payloadJson.imp[2].placementId).to.equal('placement3') - expect(Object.keys(payloadJson.imp[2].sizes).length).to.equal(2) - expect(payloadJson.imp[2].sizes[0]).to.equal('500x510') - expect(payloadJson.imp[2].sizes[1]).to.equal('600x610') - sinon.assert.calledOnce(stubLoadScript) - }) - it('should fill all parameters', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'placement1-for_essensT3', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1', - dealId: '1234', - floorPrice: '23.478' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - const url = stubLoadScript.getCall(0).args[0] - const payload = decodeURIComponent(url.split('&bid=')[1]) - const payloadJson = JSON.parse(payload) - - expect(payloadJson.ua).to.exist.and.to.be.a('string') - expect(payloadJson.url).to.exist.and.to.be.a('string') - expect(Object.keys(payloadJson.imp).length).to.equal(1) - expect(payloadJson.imp[0].impressionId).to.equal('placement1-for_essensT3') - expect(payloadJson.imp[0].placementId).to.equal('placement1') - expect(Object.keys(payloadJson.imp[0].sizes).length).to.equal(2) - expect(payloadJson.imp[0].sizes[0]).to.equal('100x110') - expect(payloadJson.imp[0].sizes[1]).to.equal('200x210') - expect(payloadJson.imp[0].deal).to.equal('1234') - expect(payloadJson.imp[0].floorPrice).to.equal('23.478') - }) - it('invalid request: missing mandatory parameters', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'placement1-for_essensT4', - bidder: 'essens', - requestId: 'essens-impression-1', - params: {}, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - sinon.assert.notCalled(stubLoadScript) - }) - }) - - describe('Test essensResponseHandler method', function () { - let stubAddBidResponse - beforeEach(() => { - stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse') - }) - - afterEach(() => { - stubAddBidResponse.restore() - }) - - it('Check method exist', function () { - expect($$PREBID_GLOBAL$$.essensResponseHandler).to.exist.and.to.be.a('function') - }) - - it('Check invalid response', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'placement1-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1T1', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const response = { - 'id': '1234' - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - $$PREBID_GLOBAL$$.essensResponseHandler(response) - - const bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0] - const bidObject1 = stubAddBidResponse.getCall(0).args[1] - - expect(bidPlacementCode1).to.equal('div-media1-top_banner-1T1') - expect(bidObject1.getStatusCode()).to.equal(2) - expect(bidObject1.bidderCode).to.equal('essens') - - sinon.assert.calledOnce(stubAddBidResponse) - }) - - it('Check empty response', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'placement1-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1T2', - bidderRequestId: 'impression-for-essens-1', - }, - { - bidId: 'placement2-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement2' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-side_banner-1T2', - bidderRequestId: 'impression-for-essens-1', - }, - { - bidId: 'placement3-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement3' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-side_banner-2T2', - bidderRequestId: 'impression-for-essens-1', - }, - ] - } - - const response = { - 'id': '1234', - 'seatbid': [] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - $$PREBID_GLOBAL$$.essensResponseHandler(response) - - const bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0] - const bidObject1 = stubAddBidResponse.getCall(0).args[1] - const bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0] - const bidObject2 = stubAddBidResponse.getCall(1).args[1] - const bidPlacementCode3 = stubAddBidResponse.getCall(2).args[0] - const bidObject3 = stubAddBidResponse.getCall(2).args[1] - - expect(bidPlacementCode1).to.equal('div-media1-top_banner-1T2') - expect(bidObject1.getStatusCode()).to.equal(2) - expect(bidObject1.bidderCode).to.equal('essens') - - expect(bidPlacementCode2).to.equal('div-media1-side_banner-1T2') - expect(bidObject2.getStatusCode()).to.equal(2) - expect(bidObject2.bidderCode).to.equal('essens') - - expect(bidPlacementCode3).to.equal('div-media1-side_banner-2T2') - expect(bidObject3.getStatusCode()).to.equal(2) - expect(bidObject3.bidderCode).to.equal('essens') - - sinon.assert.calledThrice(stubAddBidResponse) - }) - - it('Check valid response but invalid bid ', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'bid-on-placement1-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1T3', - bidderRequestId: 'impression-for-essens-1', - }, - { - bidId: 'bid-on-placement2-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement2' - }, - sizes: [ - [300, 310], - [400, 410] - ], - placementCode: 'div-media1-side_banner-1T3', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const response = { - 'id': 'impression-for-essens-1', - 'cur': 'USD', - 'seatbid': [{ - 'bid': [{ - 'id': 'responseOnBid1', - 'impid': 'bid-on-placement1-for_essens', - 'price': 9.01, - 'crid': 'creativeId1', - 'dealid': 'dealId1', - 'h': 100, - 'w': 110 - // ,'ext': { - // 'adUrl': 'creative-link2' - // } - }, - { - 'id': 'responseOnBid1', - // 'impid': 'bid-on-placement2-for_essens', - 'price': 9.01, - 'crid': 'creativeId1', - 'dealid': 'dealId1', - 'h': 300, - 'w': 310, - 'ext': { - 'adUrl': 'creative-link2' - } - }] - }] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - $$PREBID_GLOBAL$$.essensResponseHandler(response) - - let bidPlacementCode1 - let bidPlacementCode2 - let bidObject1 - let bidObject2 - - if (stubAddBidResponse.getCall(0).args[0] === 'div-media1-top_banner-1T3') { - bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0] - bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0] - bidObject1 = stubAddBidResponse.getCall(0).args[1] - bidObject2 = stubAddBidResponse.getCall(0).args[1] - } else { - bidPlacementCode1 = stubAddBidResponse.getCall(1).args[0] - bidPlacementCode2 = stubAddBidResponse.getCall(0).args[0] - bidObject1 = stubAddBidResponse.getCall(1).args[1] - bidObject2 = stubAddBidResponse.getCall(0).args[1] - } - - expect(bidPlacementCode1).to.equal('div-media1-top_banner-1T3') - expect(bidObject1.getStatusCode()).to.equal(2) - expect(bidObject1.bidderCode).to.equal('essens') - - expect(bidPlacementCode2).to.equal('div-media1-side_banner-1T3') - expect(bidObject2.getStatusCode()).to.equal(2) - expect(bidObject2.bidderCode).to.equal('essens') - - sinon.assert.calledTwice(stubAddBidResponse) - }) - - it('Check single non empty minimal valid response', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'bid-on-placement1-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1T3', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const response = { - 'id': 'impression-for-essens-1', - 'cur': 'USD', - 'seatbid': [{ - 'bid': [{ - 'id': 'responseOnBid1', - 'impid': 'bid-on-placement1-for_essens', - 'price': 9.01, - 'crid': 'creativeId1', - 'h': 300, - 'w': 310, - 'ext': { - 'adUrl': 'creative-link' - } - }] - }] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - $$PREBID_GLOBAL$$.essensResponseHandler(response) - - const bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0] - const bidObject1 = stubAddBidResponse.getCall(0).args[1] - - expect(bidPlacementCode1).to.equal('div-media1-top_banner-1T3') - expect(bidObject1.getStatusCode()).to.equal(1) - expect(bidObject1.bidderCode).to.equal('essens') - expect(bidObject1.creative_id).to.equal('creativeId1') - expect(bidObject1.cpm).to.equal(9.01) - expect(bidObject1.height).to.equal(300) - expect(bidObject1.width).to.equal(310) - expect(bidObject1.adUrl).to.equal('creative-link') - expect(bidObject1.adId).to.equal('bid-on-placement1-for_essens') - - sinon.assert.calledOnce(stubAddBidResponse) - }) - - it('Check single non empty response', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'bid-on-placement1-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1T3', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const response = { - 'id': 'impression-for-essens-1', - 'cur': 'USD', - 'seatbid': [{ - 'bid': [{ - 'id': 'responseOnBid1', - 'impid': 'bid-on-placement1-for_essens', - 'price': 9.01, - 'crid': 'creativeId1', - 'dealid': 'dealId1', - 'h': 300, - 'w': 310, - 'ext': { - 'adUrl': 'creative-link' - } - }] - }] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - $$PREBID_GLOBAL$$.essensResponseHandler(response) - - const bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0] - const bidObject1 = stubAddBidResponse.getCall(0).args[1] - - expect(bidPlacementCode1).to.equal('div-media1-top_banner-1T3') - expect(bidObject1.getStatusCode()).to.equal(1) - expect(bidObject1.bidderCode).to.equal('essens') - expect(bidObject1.creative_id).to.equal('creativeId1') - expect(bidObject1.cpm).to.equal(9.01) - expect(bidObject1.height).to.equal(300) - expect(bidObject1.width).to.equal(310) - expect(bidObject1.adUrl).to.equal('creative-link') - expect(bidObject1.adId).to.equal('bid-on-placement1-for_essens') - expect(bidObject1.dealId).to.equal('dealId1') - - sinon.assert.calledOnce(stubAddBidResponse) - }) - - it('Check multiple non empty response', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'bid-on-placement1-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1T4', - bidderRequestId: 'impression-for-essens-1', - }, - { - bidId: 'bid-on-placement2-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement2' - }, - sizes: [ - [300, 310], - [400, 410] - ], - placementCode: 'div-media1-side_banner-1T4', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const response = { - 'id': 'impression-for-essens-1', - 'cur': 'USD', - 'seatbid': [{ - 'bid': [{ - 'id': 'responseOnBid1', - 'impid': 'bid-on-placement1-for_essens', - 'price': 9.01, - 'crid': 'creativeId1', - 'dealid': 'dealId1', - 'h': 100, - 'w': 110, - 'ext': { - 'adUrl': 'creative-link1' - } - }, - { - 'id': 'responseOnBid2', - 'impid': 'bid-on-placement2-for_essens', - 'price': 9.02, - 'crid': 'creativeId2', - 'dealid': 'dealId2', - 'h': 400, - 'w': 410, - 'ext': { - 'adUrl': 'creative-link2' - } - }] - }] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - $$PREBID_GLOBAL$$.essensResponseHandler(response) - - let bidPlacementCode1 - let bidPlacementCode2 - let bidObject1 - let bidObject2 - - if (stubAddBidResponse.getCall(0).args[0] === 'div-media1-top_banner-1T4') { - bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0] - bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0] - bidObject1 = stubAddBidResponse.getCall(0).args[1] - bidObject2 = stubAddBidResponse.getCall(1).args[1] - } else { - bidPlacementCode1 = stubAddBidResponse.getCall(1).args[0] - bidPlacementCode2 = stubAddBidResponse.getCall(0).args[0] - bidObject1 = stubAddBidResponse.getCall(1).args[1] - bidObject2 = stubAddBidResponse.getCall(0).args[1] - } - - expect(bidPlacementCode1).to.equal('div-media1-top_banner-1T4') - expect(bidObject1.getStatusCode()).to.equal(1) - expect(bidObject1.bidderCode).to.equal('essens') - expect(bidObject1.creative_id).to.equal('creativeId1') - expect(bidObject1.cpm).to.equal(9.01) - expect(bidObject1.height).to.equal(100) - expect(bidObject1.width).to.equal(110) - expect(bidObject1.adUrl).to.equal('creative-link1') - expect(bidObject1.adId).to.equal('bid-on-placement1-for_essens') - expect(bidObject1.dealId).to.equal('dealId1') - - expect(bidPlacementCode2).to.equal('div-media1-side_banner-1T4') - expect(bidObject2.getStatusCode()).to.equal(1) - expect(bidObject2.bidderCode).to.equal('essens') - expect(bidObject2.creative_id).to.equal('creativeId2') - expect(bidObject2.cpm).to.equal(9.02) - expect(bidObject2.height).to.equal(400) - expect(bidObject2.width).to.equal(410) - expect(bidObject2.adUrl).to.equal('creative-link2') - expect(bidObject2.adId).to.equal('bid-on-placement2-for_essens') - expect(bidObject2.dealId).to.equal('dealId2') - - sinon.assert.calledTwice(stubAddBidResponse) - }) - - it('Check empty and non empty mixed response', function () { - const bidderRequest = { - bidderCode: 'essens', - requestId: 'impression-1', - bidderRequestId: 'impression-for-essens-1', - bids: [ - { - bidId: 'bid-on-placement1-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement1' - }, - sizes: [ - [100, 110], - [200, 210] - ], - placementCode: 'div-media1-top_banner-1T5', - bidderRequestId: 'impression-for-essens-1', - }, - { - bidId: 'bid-on-placement2-for_essens', - bidder: 'essens', - requestId: 'essens-impression-1', - params: { - placementId: 'placement2' - }, - sizes: [ - [300, 310], - [400, 410] - ], - placementCode: 'div-media1-side_banner-1T5', - bidderRequestId: 'impression-for-essens-1', - } - ] - } - - const response = { - 'id': 'impression-for-essens-1', - 'cur': 'USD', - 'seatbid': [{ - 'bid': [{ - 'id': 'responseOnBid1', - 'impid': 'bid-on-placement2-for_essens', - 'price': 9.01, - 'crid': 'creativeId1', - 'dealid': 'dealId1', - 'h': 500, - 'w': 510, - 'ext': { - 'adUrl': 'creative-link' - } - }] - }] - } - - const essensAdapter = new Adapter() - essensAdapter.callBids(bidderRequest) - - $$PREBID_GLOBAL$$.essensResponseHandler(response) - - let bidPlacementCode1 - let bidPlacementCode2 - let bidObject1 - let bidObject2 - - if (stubAddBidResponse.getCall(0).args[0] === 'div-media1-side_banner-1T5') { - bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0] - bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0] - bidObject1 = stubAddBidResponse.getCall(0).args[1] - bidObject2 = stubAddBidResponse.getCall(1).args[1] - } else { - bidPlacementCode1 = stubAddBidResponse.getCall(1).args[0] - bidPlacementCode2 = stubAddBidResponse.getCall(0).args[0] - bidObject1 = stubAddBidResponse.getCall(1).args[1] - bidObject2 = stubAddBidResponse.getCall(0).args[1] - } - - expect(bidPlacementCode1).to.equal('div-media1-side_banner-1T5') - expect(bidObject1.getStatusCode()).to.equal(1) - expect(bidObject1.bidderCode).to.equal('essens') - expect(bidObject1.creative_id).to.equal('creativeId1') - expect(bidObject1.cpm).to.equal(9.01) - expect(bidObject1.height).to.equal(500) - expect(bidObject1.width).to.equal(510) - expect(bidObject1.adUrl).to.equal('creative-link') - expect(bidObject1.adId).to.equal('bid-on-placement2-for_essens') - expect(bidObject1.dealId).to.equal('dealId1') - - expect(bidPlacementCode2).to.equal('div-media1-top_banner-1T5') - expect(bidObject2.getStatusCode()).to.equal(2) - expect(bidObject2.bidderCode).to.equal('essens') - - sinon.assert.calledTwice(stubAddBidResponse) - }) - }) -}) diff --git a/test/spec/modules/featureforwardBidAdapter_spec.js b/test/spec/modules/featureforwardBidAdapter_spec.js deleted file mode 100644 index 9c6b91d5a36..00000000000 --- a/test/spec/modules/featureforwardBidAdapter_spec.js +++ /dev/null @@ -1,87 +0,0 @@ -import {expect} from 'chai'; -import FeatureForwardAdapter from 'modules/featureforwardBidAdapter'; -import bidManager from 'src/bidmanager'; -import * as ajax from 'src/ajax'; -import {parse as parseURL} from 'src/url'; - -describe('FeatureForward Adapter Tests', () => { - let featureForwardAdapter = new FeatureForwardAdapter(); - let slotConfigs; - let ajaxStub; - beforeEach(() => { - sinon.stub(bidManager, 'addBidResponse'); - ajaxStub = sinon.stub(ajax, 'ajax'); - slotConfigs = { - bids: [ - { - sizes: [[300, 250]], - bidder: 'featureforward', - placementCode: 'test1_placement', - params: { - pubId: '001', - siteId: '111', - placementId: '1', - } - }] - }; - }); - - afterEach(() => { - bidManager.addBidResponse.restore(); - ajaxStub.restore(); - }); - - it('Verify requests sent to FeatureForward', () => { - featureForwardAdapter.callBids(slotConfigs); - var call = ajaxStub.firstCall.args[0]; - var request = JSON.parse(ajaxStub.args[0][2]); - var creds = ajaxStub.args[0][3]; - expect(call).to.equal('http://prmbdr.featureforward.com/newbidder/bidder1_prm.php?'); - expect(request.ca).to.equal('BID'); - expect(request.pubId).to.equal('001'); - expect(request.siteId).to.equal('111'); - expect(request.placementId).to.equal('1'); - expect(request.size[0]).to.equal(300); - expect(request.size[1]).to.equal(250); - expect(creds.method).to.equal('POST'); - }); - - it('Verify bid', () => { - featureForwardAdapter.callBids(slotConfigs); - ajaxStub.firstCall.args[1](JSON.stringify({ - html: 'FF Test Ad', - bidCpm: 0.555, - width: 300, - height: 250 - })); - let bid = bidManager.addBidResponse.firstCall.args[1]; - expect(bid.bidderCode).to.equal('featureforward'); - expect(bid.cpm).to.equal(0.555); - expect(bid.ad).to.equal('FF Test Ad'); - expect(bid.width).to.equal(300); - expect(bid.height).to.equal(250); - }); - - it('Verify passback', () => { - featureForwardAdapter.callBids(slotConfigs); - // trigger a mock ajax callback with no bid. - ajaxStub.firstCall.args[1](null); - let placement = bidManager.addBidResponse.firstCall.args[0]; - let bid = bidManager.addBidResponse.firstCall.args[1]; - expect(placement).to.equal('test1_placement'); - expect(bid.bidderCode).to.equal('featureforward'); - expect(bid).to.not.have.property('ad'); - expect(bid).to.not.have.property('cpm'); - }); - - it('Verify passback when ajax call fails', () => { - ajaxStub.throws(); - featureForwardAdapter.callBids(slotConfigs); - let placement = bidManager.addBidResponse.firstCall.args[0]; - let bid = bidManager.addBidResponse.firstCall.args[1]; - expect(placement).to.equal('test1_placement'); - expect(bid.bidderCode).to.equal('featureforward'); - expect(bid).to.not.have.property('ad'); - expect(bid).to.not.have.property('cpm'); - }); -}); diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js deleted file mode 100644 index b90a1a48b15..00000000000 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ /dev/null @@ -1,295 +0,0 @@ -import {expect} from 'chai'; -import Adapter from '../../../modules/gumgumBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; -import * as utils from '../../../src/utils'; -import { STATUS } from '../../../src/constants'; - -describe('gumgum adapter', () => { - 'use strict'; - - let adapter; - let sandbox; - - const TEST = { - PUBLISHER_IDENTITY: 'ggumtest', - BIDDER_CODE: 'gumgum', - PLACEMENT: 'placementId', - CPM: 2 - }; - const bidderRequest = { - bidderCode: TEST.BIDDER_CODE, - bids: [{ // in-screen - bidId: 'InScreenBidId', - bidder: TEST.BIDDER_CODE, - placementCode: TEST.PLACEMENT, - sizes: [ [728, 90] ], - params: { - inScreen: TEST.PUBLISHER_IDENTITY - } - }, { // in-image - bidId: 'InImageBidId', - bidder: TEST.BIDDER_CODE, - placementCode: TEST.PLACEMENT, - sizes: [ [728, 90] ], - params: { - inImage: TEST.PUBLISHER_IDENTITY - } - }, { // native - bidId: 'NativeBidId', - bidder: TEST.BIDDER_CODE, - placementCode: TEST.PLACEMENT, - sizes: [ [728, 90] ], - params: { - native: 10 - } - }, { // slot - bidId: 'InSlotBidId', - bidder: TEST.BIDDER_CODE, - placementCode: TEST.PLACEMENT, - sizes: [ [728, 90] ], - params: { - inSlot: 10 - } - }, { // no identity - bidId: 'NoIdentityBidId', - bidder: TEST.BIDDER_CODE, - placementCode: TEST.PLACEMENT, - sizes: [ [728, 90] ] - }] - }; - const pageParams = { - 'pvid': 'PVID' - }; - const bidderResponse = { - 'ad': { - 'id': 1, - 'width': 728, - 'height': 90, - 'markup': '
some fancy ad
', - 'ii': true, - 'du': 'http://example.com/', - 'price': TEST.CPM, - 'impurl': 'http://example.com/' - }, - 'pag': pageParams - }; - - function mockBidResponse(response) { - sandbox.stub(bidManager, 'addBidResponse'); - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(bidderRequest); - $$PREBID_GLOBAL$$.handleGumGumCB['InScreenBidId'](response); - return bidManager.addBidResponse.firstCall.args[1]; - } - - beforeEach(() => { - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('DigiTrust params', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - }); - - it('should send digiTrust params', () => { - window.DigiTrust = { - getUser: function() {} - }; - sandbox.stub(window.DigiTrust, 'getUser', () => - ({ - success: true, - identity: { - privacy: {optout: false}, - id: 'testId' - } - }) - ); - - adapter.callBids(bidderRequest); - expect(adLoader.loadScript.firstCall.args[0]).to.include('&dt=testId'); - delete window.DigiTrust; - }); - - it('should not send DigiTrust params when DigiTrust is not loaded', () => { - adapter.callBids(bidderRequest); - expect(adLoader.loadScript.firstCall.args[0]).to.not.include('&dt'); - }); - - it('should not send DigiTrust params due to opt out', () => { - window.DigiTrust = { - getUser: function() {} - }; - sandbox.stub(window.DigiTrust, 'getUser', () => - ({ - success: true, - identity: { - privacy: {optout: true}, - id: 'testId' - } - }) - ); - - adapter.callBids(bidderRequest); - expect(adLoader.loadScript.firstCall.args[0]).to.not.include('&dt'); - delete window.DigiTrust; - }); - - it('should not send DigiTrust params on failure', () => { - window.DigiTrust = { - getUser: function() {} - }; - sandbox.stub(window.DigiTrust, 'getUser', () => - ({ - success: false, - identity: { - privacy: {optout: false}, - id: 'testId' - } - }) - ); - - adapter.callBids(bidderRequest); - expect(adLoader.loadScript.firstCall.args[0]).to.not.include('&dt'); - delete window.DigiTrust; - }); - }); - - describe('callBids', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(bidderRequest); - }); - - it('calls the endpoint once per valid bid', () => { - sinon.assert.callCount(adLoader.loadScript, 4); - }); - - it('includes required browser data', () => { - const endpointRequest = expect(adLoader.loadScript.firstCall.args[0]); - endpointRequest.to.include('vw'); - endpointRequest.to.include('vh'); - endpointRequest.to.include('sw'); - endpointRequest.to.include('sh'); - }); - - it('includes the global bid timeout', () => { - const endpointRequest = expect(adLoader.loadScript.firstCall.args[0]); - endpointRequest.to.include(`tmax=${$$PREBID_GLOBAL$$.cbTimeout}`); - }); - - it('includes the publisher identity', () => { - const endpointRequest = expect(adLoader.loadScript.firstCall.args[0]); - endpointRequest.to.include('t=' + TEST.PUBLISHER_IDENTITY); - }); - - it('first call should be in-screen', () => { - expect(adLoader.loadScript.firstCall.args[0]).to.include('pi=2'); - }); - - it('second call should be in-image', () => { - expect(adLoader.loadScript.secondCall.args[0]).to.include('pi=1'); - }); - - it('third call should be native', () => { - expect(adLoader.loadScript.thirdCall.args[0]).to.include('pi=5'); - }); - - it('last call should be slot', () => { - expect(adLoader.loadScript.lastCall.args[0]).to.include('pi=3'); - }); - }); - - describe('handleGumGumCB[...]', () => { - it('exists and is function', () => { - expect($$PREBID_GLOBAL$$.handleGumGumCB['InScreenBidId']).to.exist.and.to.be.a('function'); - }); - }); - - describe('respond with a successful bid', () => { - let successfulBid; - - beforeEach(() => { - successfulBid = mockBidResponse(bidderResponse); - }); - - it('adds one bid', () => { - sinon.assert.calledOnce(bidManager.addBidResponse); - }); - - it('passes the correct placement code as the first param', () => { - const [ placementCode ] = bidManager.addBidResponse.firstCall.args; - expect(placementCode).to.eql(TEST.PLACEMENT); - }); - - it('has a GOOD status code', () => { - const STATUS_CODE = successfulBid.getStatusCode(); - expect(STATUS_CODE).to.eql(STATUS.GOOD); - }); - - it('uses the CPM returned by the server', () => { - expect(successfulBid).to.have.property('cpm', TEST.CPM); - }); - - it('has an ad', () => { - expect(successfulBid).to.have.property('ad'); - }); - - it('has the size specified by the server', () => { - expect(successfulBid).to.have.property('width', 728); - expect(successfulBid).to.have.property('height', 90); - }); - }); - - describe('respond with an empty bid', () => { - let noBid; - - beforeEach(() => { - noBid = mockBidResponse(undefined); - }); - - it('adds one bid', () => { - sinon.assert.calledOnce(bidManager.addBidResponse); - }); - - it('has a NO_BID status code', () => { - expect(noBid.getStatusCode()).to.eql(STATUS.NO_BID); - }); - - it('passes the correct placement code as the first parameter', () => { - const [ placementCode ] = bidManager.addBidResponse.firstCall.args; - expect(placementCode).to.eql(TEST.PLACEMENT); - }); - - it('adds the bidder code to the bid object', () => { - expect(noBid).to.have.property('bidderCode', TEST.BIDDER_CODE); - }); - }); - - describe('refresh throttle', () => { - beforeEach(() => { - mockBidResponse(bidderResponse); - }); - - afterEach(() => { - if (utils.logWarn.restore) { - utils.logWarn.restore(); - } - }); - - it('warns about the throttle limit', function() { - sinon.spy(utils, 'logWarn'); - // call all the binds again - adapter.callBids(bidderRequest); - // the timeout for in-screen should stop one bid request - const warning = expect(utils.logWarn.args[0][0]); - warning.to.include(TEST.PLACEMENT); - warning.to.include('inScreen'); - }); - }); -}); diff --git a/test/spec/modules/hiromediaBidAdapter_spec.js b/test/spec/modules/hiromediaBidAdapter_spec.js deleted file mode 100644 index c1ed4ee6e11..00000000000 --- a/test/spec/modules/hiromediaBidAdapter_spec.js +++ /dev/null @@ -1,331 +0,0 @@ -import { expect } from 'chai'; -import urlParse from 'url-parse'; - -import Adapter from 'modules/hiromediaBidAdapter'; -import bidmanager from 'src/bidmanager'; -import { STATUS } from 'src/constants'; -import * as utils from 'src/utils'; - -describe('hiromedia adapter', function () { - const BIDDER_CODE = 'hiromedia'; - const DEFAULT_ENDPOINT = 'https://hb-rtb.ktdpublishers.com/bid/get'; - - let adapter; - let sandbox; - let xhr; - let addBidResponseStub; - let hasValidBidRequestSpy; - let placementId = 0; - - window.$$PREBID_GLOBAL$$ = window.$$PREBID_GLOBAL$$ || {}; - - beforeEach(() => { - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - - // Used to spy on bid requests - xhr = sandbox.useFakeXMLHttpRequest(); - - // Used to spy on bid responses - addBidResponseStub = sandbox.stub(bidmanager, 'addBidResponse'); - - // Used to spy on bid validation - hasValidBidRequestSpy = sandbox.spy(utils, 'hasValidBidRequest'); - - placementId = 0; - }); - - afterEach(() => { - sandbox.restore(); - }); - - // Helper function that asserts that no bidding activity (requests nor responses) - // was made during a test. - const assertNoBids = () => { - expect(xhr.requests.length).to.be.equal(0); - sinon.assert.notCalled(addBidResponseStub); - }; - - // Helper function to generate a 'mock' bid object - const makePlacement = (size) => { - placementId += 1; - - return { - bidder: BIDDER_CODE, - sizes: [size], - params: { - accountId: '1337' - }, - placementCode: 'div-gpt-ad-12345-' + placementId - }; - }; - - // 300x250 are in the allowed size by default - const tilePlacement = () => makePlacement([300, 250]); - - // anything else should have no bid by default - const leaderPlacement = () => makePlacement([728, 90]); - - describe('callbids', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - - it('tolerates empty arguments', () => { - expect(adapter.callBids).to.not.throw(Error); - assertNoBids(); - }); - - it('tolerates empty params', () => { - expect(adapter.callBids.bind(adapter, {})).to.not.throw(Error); - assertNoBids(); - }); - - it('tolerates empty bids', () => { - expect(adapter.callBids.bind(adapter, {bids: []})).to.not.throw(Error); - assertNoBids(); - }); - - it('invokes a bid request per placement', () => { - const expectedRequests = [{ - placementCode: 'div-gpt-ad-12345-1', - selectedSize: '300x250' - }, { - placementCode: 'div-gpt-ad-12345-2', - selectedSize: '728x90' - }, { - placementCode: 'div-gpt-ad-12345-3', - selectedSize: '300x250' - }]; - - const params = { - bids: [tilePlacement(), leaderPlacement(), tilePlacement()] - }; - - adapter.callBids(params); - expect(xhr.requests.length).to.equal(3); - sinon.assert.notCalled(addBidResponseStub); - sinon.assert.calledThrice(hasValidBidRequestSpy); - - expectedRequests.forEach(function(request, index) { - expect(hasValidBidRequestSpy.returnValues[index]).to.be.equal(true); - - // validate request - const bidRequest = xhr.requests[index].url; - const defaultBidUrl = urlParse(DEFAULT_ENDPOINT); - const bidUrl = urlParse(bidRequest, true); - const query = bidUrl.query; - - expect(bidUrl.hostname).to.equal(defaultBidUrl.hostname); - expect(bidUrl.pathname).to.equal(defaultBidUrl.pathname); - - expect(query).to.have.property('adapterVersion').and.to.equal('3'); - expect(query).to.have.property('placementCode').and.to.equal(request.placementCode); - expect(query).to.have.property('accountId').and.to.equal('1337'); - expect(query).to.have.property('selectedSize').and.to.equal(request.selectedSize); - expect(query).to.not.have.property('additionalSizes'); - expect(query).to.have.property('domain').and.to.equal(window.top.location.hostname); - }); - }); - - // Test additionalSizes parameter - it('attaches multiple sizes to additionalSizes', () => { - const placement = tilePlacement(); - - // Append additional - placement.sizes.push([300, 600]); - placement.sizes.push([300, 900]); - - const params = { - bids: [placement] - }; - - adapter.callBids(params); - expect(xhr.requests.length).to.be.equal(1); - - const bidRequest = xhr.requests[0].url; - const bidUrl = urlParse(bidRequest, true); - const query = bidUrl.query; - - expect(query).to.have.property('selectedSize').and.to.equal('300x250'); - expect(query).to.have.property('additionalSizes').and.to.equal('300x600,300x900'); - }); - - // Test `params.accountId` validation - it('invalidates bids with no id', () => { - const placement = tilePlacement(); - delete placement.params; - - const params = { - bids: [placement] - }; - - adapter.callBids(params); - expect(xhr.requests.length).to.be.equal(0); - sinon.assert.calledOnce(hasValidBidRequestSpy); - sinon.assert.calledOnce(addBidResponseStub); - - expect(hasValidBidRequestSpy.returnValues[0]).to.be.equal(false); - const placementCode = addBidResponseStub.getCall(0).args[0]; - const bidObject = addBidResponseStub.getCall(0).args[1]; - - expect(placementCode).to.be.equal('div-gpt-ad-12345-1'); - expect(bidObject.getStatusCode()).to.be.equal(STATUS.NO_BID); - }); - - // Test `params.bidUrl` - it('accepts a custom bid endpoint url', () => { - const placement = tilePlacement(); - placement.params.bidUrl = DEFAULT_ENDPOINT + '?someparam=value'; - - const params = { - bids: [placement] - }; - - adapter.callBids(params); - expect(xhr.requests.length).to.be.equal(1); - - const bidRequest = xhr.requests[0].url; - const defaultBidUrl = urlParse(DEFAULT_ENDPOINT); - const bidUrl = urlParse(bidRequest, true); - const query = bidUrl.query; - - expect(bidUrl.hostname).to.equal(defaultBidUrl.hostname); - expect(bidUrl.pathname).to.equal(defaultBidUrl.pathname); - - expect(query).to.have.property('someparam').and.to.equal('value'); - }); - }); - - describe('response handler', () => { - let server; - - beforeEach(() => { - server = sandbox.useFakeServer(); - }); - - const assertSingleFailedBidResponse = () => { - sinon.assert.calledOnce(addBidResponseStub); - const placementCode = addBidResponseStub.getCall(0).args[0]; - const bidObject = addBidResponseStub.getCall(0).args[1]; - - expect(placementCode).to.be.equal('div-gpt-ad-12345-1'); - expect(bidObject.getStatusCode()).to.be.equal(STATUS.NO_BID); - }; - - it('tolerates an empty response', () => { - server.respondWith(''); - adapter.callBids({bids: [tilePlacement()]}); - server.respond(); - - assertSingleFailedBidResponse(); - }); - - it('tolerates a response error', () => { - server.respondWith([500, {}, '']); - adapter.callBids({bids: [tilePlacement()]}); - server.respond(); - - assertSingleFailedBidResponse(); - }); - - it('tolerates an invalid response', () => { - server.respondWith('not json'); - adapter.callBids({bids: [tilePlacement()]}); - server.respond(); - - assertSingleFailedBidResponse(); - }); - - it('adds a bid reponse for each pending bid', () => { - const responses = [{ - width: '300', - height: '250', - cpm: 0.4, - ad: '' - }, { - width: '728', - height: '90', - cpm: 0.4, - ad: '' - }]; - - let id = 0; - server.respondWith((request) => { - request.respond(200, {}, JSON.stringify(responses[id])); - id += 1; - }); - - const params = { - bids: [tilePlacement(), leaderPlacement()] - }; - - adapter.callBids(params); - server.respond(); - - expect(server.requests.length).to.be.equal(2); - sinon.assert.calledTwice(addBidResponseStub); - - responses.forEach((expectedResponse, i) => { - const placementCode = addBidResponseStub.getCall(i).args[0]; - const bidObject = addBidResponseStub.getCall(i).args[1]; - - expect(placementCode).to.be.equal('div-gpt-ad-12345-' + (i + 1)); - - expect(bidObject.getStatusCode()).to.be.equal(STATUS.GOOD); - expect(bidObject).to.have.property('cpm').and.to.equal(expectedResponse.cpm); - expect(bidObject).to.have.property('ad').and.to.equal(expectedResponse.ad); - expect(bidObject).to.have.property('width').and.to.equal(expectedResponse.width); - expect(bidObject).to.have.property('height').and.to.equal(expectedResponse.height); - }); - }); - - // We want to check that responses are added according to a sampling value, - // this is possible by stubbing `Math.random`, to ensure the effect is - // limited to the area we check, we create a self destructing stub which - // restores itself once called. - it('adds responses according to the sampling defined in the response', () => { - const response = { - cpm: 0.4, - chance: 0.25, - ad: '' - }; - - // List of "random" values. We check that the first two pass and the last - // one is skipped. - const randomValues = [0.2, 0.3]; - let randomIndex = 0; - - server.respondWith((request) => { - const mathRandomStub = sandbox.stub(Math, 'random', function () { - const randomValue = randomValues[randomIndex]; - - randomIndex += 1; - mathRandomStub.restore(); // self destruct on call - - return randomValue; - }); - - request.respond(200, {}, JSON.stringify(response)); - - mathRandomStub.restore(); - }); - - const params = { - bids: [tilePlacement()] - }; - - adapter.callBids(params); - adapter.callBids(params); - server.respond(); - - sinon.assert.calledTwice(addBidResponseStub); - - const firstBidObject = addBidResponseStub.getCall(0).args[1]; - const secondBidObject = addBidResponseStub.getCall(1).args[1]; - - expect(firstBidObject.getStatusCode()).to.be.equal(STATUS.GOOD); - expect(secondBidObject.getStatusCode()).to.be.equal(STATUS.NO_BID); - }); - }); -}); diff --git a/test/spec/modules/imonomyBidAdapter_spec.js b/test/spec/modules/imonomyBidAdapter_spec.js deleted file mode 100644 index e27a0d69a60..00000000000 --- a/test/spec/modules/imonomyBidAdapter_spec.js +++ /dev/null @@ -1,109 +0,0 @@ -import Adapter from '../../../modules/imonomyBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import {expect} from 'chai'; -import adLoader from '../../../src/adloader'; - -var CONSTANTS = require('../../../src/constants'); - -describe('imonomy adapter test', () => { - var utils = require('src/utils'); - let adapter; - let stubAddBidResponse; - let sandbox; - - let validBid = { - bidderCode: 'imonomy', - bids: [ - { - bidder: 'imonomy', - placementCode: 'foo', - bidId: 'foo', - sizes: [[300, 250]], - params: { - publisher_id: '14567721164', - } - } - ] - }; - - let validResponse = { - ads: [ - { - impression_id: 'foo', - cpm: 1.12, - creative: '' - } - ] - }; - - beforeEach(() => { - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - stubAddBidResponse.restore(); - sandbox.restore(); - }); - - describe('dealing with diffrent situations', () => { - let server; - var stubGetUniqueIdentifierStr = sinon.spy(utils, 'getUniqueIdentifierStr'); - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - stubAddBidResponse.restore(); - sandbox.restore(); - stubGetUniqueIdentifierStr.restore(); - }); - - it('no bid if cdb handler responds with no bid empty string response', (done) => { - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.NO_BID }); - done(); - }); - - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(validBid); - var callbackName = '_hb_' + stubGetUniqueIdentifierStr.returnValues[0] - $$PREBID_GLOBAL$$[callbackName]({}) - }); - - it('adds bid for valid request', (done) => { - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.GOOD }); - done(); - }); - - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(validBid); - var callbackName = '_hb_' + stubGetUniqueIdentifierStr.returnValues[0] - $$PREBID_GLOBAL$$[callbackName](validResponse) - }); - - it('adds bid for valid request with UM', (done) => { - stubAddBidResponse = sinon.stub(bidManager, 'addBidResponse', function (adUnitCode, bid) { - expect(bid).to.satisfy(bid => { return bid.getStatusCode() == CONSTANTS.STATUS.GOOD }); - done(); - }); - - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(validBid); - var callbackName = '_hb_' + stubGetUniqueIdentifierStr.returnValues[0] - $$PREBID_GLOBAL$$[callbackName](validResponseUM) - }); - }); -}); diff --git a/test/spec/modules/indexExchangeBidAdapter_request_spec.js b/test/spec/modules/indexExchangeBidAdapter_request_spec.js deleted file mode 100644 index 787c6bafde4..00000000000 --- a/test/spec/modules/indexExchangeBidAdapter_request_spec.js +++ /dev/null @@ -1,528 +0,0 @@ -import Adapter from 'modules/indexExchangeBidAdapter'; -import bidManager from 'src/bidmanager'; -import adLoader from 'src/adloader'; -import * as url from 'src/url'; - -var assert = require('chai').assert; -var IndexUtils = require('../../helpers/index_adapter_utils.js'); -var HeaderTagRequest = '/cygnus'; -var SlotThreshold = 20; -var ADAPTER_CODE = 'indexExchange'; - -window.pbjs = window.pbjs || {}; - -describe('indexExchange adapter - Request', function () { - let adapter; - let sandbox; - - beforeEach(function() { - window._IndexRequestData = {}; - _IndexRequestData.impIDToSlotID = {}; - _IndexRequestData.reqOptions = {}; - _IndexRequestData.targetIDToResp = {}; - window.cygnus_index_args = {}; - - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - sandbox.stub(adLoader, 'loadScript'); - sandbox.stub(bidManager, 'addBidResponse'); - }); - - afterEach(function() { - sandbox.restore(); - }); - - it('test_prebid_indexAdapter_parameter_x3: prebid sends AS request -> x3 parameter does not exist in the request', function () { - var configuredBids = IndexUtils.createBidSlots(); - adapter.callBids({ bids: configuredBids }); - - assert.notInclude(adLoader.loadScript.firstCall.args[0], 'x3=', 'x3 parameter is not in AS request'); - }); - - it('test_prebid_indexAdapter_request_1_1: single slot with single size -> single request object for the slot', function () { - var configuredBids = IndexUtils.createBidSlots(); - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.isString(requestJSON.r.id, 'ID is string'); - }); - - it('test_prebid_indexAdapter_request_1_1: single slot with single size -> single request object for the slot', function () { - var configuredBids = IndexUtils.createBidSlots(); - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_request_1_2: single slot with unsupported single size -> indexExchange does not participate in auction', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.unsupportedSizes[0] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to AS'); - - var adapterResponse = {}; - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - }; - assert.deepEqual(Object.keys(adapterResponse), [IndexUtils.DefaultPlacementCodePrefix], 'bid response from placement code that is configured'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix].length, 1, 'one response back returned for placement ' + IndexUtils.DefaultPlacementCodePrefix); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].bidderCode, ADAPTER_CODE, "bidder code match with adapter's name"); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - }); - - it('test_prebid_indexAdapter_request_2_1: single slot with all supported multiple sizes -> multiple request objects for the slot', function () { - var configuredBids = IndexUtils.createBidSlots(1, 5); - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_request_2_2: single slot with all unsupported multiple sizes -> no request objects for the slot', function () { - var isSetExpectedBidsCountCalled = false; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.unsupportedSizes[0], IndexUtils.unsupportedSizes[1], IndexUtils.unsupportedSizes[2] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to AS'); - }); - - it('test_prebid_indexAdapter_request_2_3: single slot with supported, unsupportrd, supported sizes -> only the supported size request objects for the slot', function () { - var unsupportedSize = IndexUtils.unsupportedSizes[0]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], unsupportedSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, unsupportedSize, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize)); - }); - - it('test_prebid_indexAdapter_request_2_4: single slot with unsupported, supportrd, unsupported sizes -> only the supported size request objects for the slot', function () { - var unsupportedSize1 = IndexUtils.unsupportedSizes[0]; - var unsupportedSize2 = IndexUtils.unsupportedSizes[1]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ unsupportedSize1, IndexUtils.supportedSizes[1], unsupportedSize2 ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 2, '2 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, unsupportedSize1, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize1)); - assert.equal(sidMatched.unmatched.configured[1].size, unsupportedSize2, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize2)); - }); - - it('test_prebid_indexAdapter_request_3: multiple slots with single size below allowed slot threshold -> request for all the slots', function () { - var configuredBids = IndexUtils.createBidSlots(10); - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_request_4: multiple slots with single size at exact allowed slot threshold -> request for all the slots', function () { - var configuredBids = IndexUtils.createBidSlots(SlotThreshold); - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_request_5: multiple slots with single size exceed allowed slot threshold -> request for all the slots', function () { - var requestSlotNumber = SlotThreshold + 1; - var configuredBids = IndexUtils.createBidSlots(requestSlotNumber); - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_request_6: threshold valid + non valid which exceeds threshold -> 1 Ad Server request with supported sizes only', function () { - var unsupportedSizeCount = 1; - var requestSlotNumber = SlotThreshold; - var configuredBids = IndexUtils.createBidSlots(requestSlotNumber); - // add additional unsupported sized slot - var invalidSlotPlacement = IndexUtils.DefaultPlacementCodePrefix + 'invalid'; - var invalidSlotID = 'slot-invalid'; - configuredBids.push(IndexUtils.createBidSlot(invalidSlotPlacement, invalidSlotID, [ IndexUtils.unsupportedSizes[0] ])); - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, unsupportedSizeCount, unsupportedSizeCount + ' of configured bids is missing in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].placementCode, invalidSlotPlacement, "missing slot's placement code is " + invalidSlotPlacement); - assert.equal(sidMatched.unmatched.configured[0].params.id, invalidSlotID, "missing slot's slotID is " + invalidSlotID); - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_request_7: multiple sizes with slots that exceeds max threshold requests -> 1 Ad Server request with supported sizes only', function () { - var requestSlotNumber = SlotThreshold; - var requestSizeNumber = 2; - var configuredBids = IndexUtils.createBidSlots(requestSlotNumber, requestSizeNumber); - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - - assert.equal(sidMatched.matched.length, requestSlotNumber * requestSizeNumber, 'All slots each with multiple sizes are in AS request'); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_request_sizeID_1: 1 prebid size slot, 1 index slot with size -> one slot in AS request 1 no size ID', function () { - var slotID = 52; - var slotSizes = IndexUtils.supportedSizes[0]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID, [ slotSizes ], { slotSize: slotSizes }) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - assert.equal(impressionObj.length, 1, '1 slot is made in the request'); - assert.equal(impressionObj[0].banner.w, slotSizes[0], 'the width made in the request matches with request: ' + slotSizes[0]); - assert.equal(impressionObj[0].banner.h, slotSizes[1], 'the height made in the request matches with request: ' + slotSizes[1]); - assert.equal(impressionObj[0].ext.sid, slotID, 'slotID in the request matches with configuration: ' + slotID); - assert.equal(impressionObj[0].ext.siteID, IndexUtils.DefaultSiteID, 'siteID in the request matches with request: ' + IndexUtils.DefaultSiteID); - }); - - it('test_prebid_indexAdapter_request_sizeID_2: multiple prebid size slot, 1 index slot with size -> one slot in AS request 1 no size ID', function () { - var slotID = 52; - var slotSizes = IndexUtils.supportedSizes[0]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID, [ slotSizes, IndexUtils.supportedSizes[1] ], { slotSize: slotSizes }) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - assert.equal(impressionObj.length, 1, '1 slot is made in the request'); - assert.equal(impressionObj[0].banner.w, slotSizes[0], 'the width made in the request matches with request: ' + slotSizes[0]); - assert.equal(impressionObj[0].banner.h, slotSizes[1], 'the height made in the request matches with request: ' + slotSizes[1]); - assert.equal(impressionObj[0].ext.sid, slotID, 'slotID in the request matches with configuration: ' + slotID); - assert.equal(impressionObj[0].ext.siteID, IndexUtils.DefaultSiteID, 'siteID in the request matches with request: ' + IndexUtils.DefaultSiteID); - }); - - it('test_prebid_indexAdapter_request_sizeID_3: multiple prebid size slot, index slots with size for all prebid slots -> all size in AS request, no size ID', function () { - var slotID_1 = 52; - var slotID_2 = 53; - var slotSizes_1 = IndexUtils.supportedSizes[0]; - var slotSizes_2 = IndexUtils.supportedSizes[1]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID_1, [ slotSizes_1, slotSizes_2 ], { slotSize: slotSizes_1 }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID_2, [ slotSizes_1, slotSizes_2 ], { slotSize: slotSizes_2 }) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - assert.equal(impressionObj.length, 2, '2 slot is made in the request'); - assert.equal(impressionObj[0].banner.w, slotSizes_1[0], 'the width made in the request matches with request: ' + slotSizes_1[0]); - assert.equal(impressionObj[0].banner.h, slotSizes_1[1], 'the height made in the request matches with request: ' + slotSizes_1[1]); - assert.equal(impressionObj[0].ext.sid, slotID_1, 'slotID in the request matches with configuration: ' + slotID_1); - assert.equal(impressionObj[0].ext.siteID, IndexUtils.DefaultSiteID, 'siteID in the request matches with request: ' + IndexUtils.DefaultSiteID); - - assert.equal(impressionObj[1].banner.w, slotSizes_2[0], 'the width made in the request matches with request: ' + slotSizes_2[0]); - assert.equal(impressionObj[1].banner.h, slotSizes_2[1], 'the height made in the request matches with request: ' + slotSizes_2[1]); - assert.equal(impressionObj[1].ext.sid, slotID_2, 'slotID in the request matches with configuration: ' + slotID_2); - assert.equal(impressionObj[1].ext.siteID, IndexUtils.DefaultSiteID, 'siteID in the request matches with request: ' + IndexUtils.DefaultSiteID); - }); - - it('test_prebid_indexAdapter_request_sizeID_4: multiple prebid size slot, 1 index slot but size not in prebid defined size git -> no AS requset', function () { - var slotID = 52; - var slotSizes = IndexUtils.unsupportedSizes[0]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID, [ IndexUtils.supportedSizes[0] ], { slotSize: slotSizes }) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to AS'); - }); - - it('test_prebid_indexAdapter_request_sizeID_5: multiple prebid size slot, 1 index slot but size not defined in slot -> no AS requset', function () { - var slotID = 52; - var slotSizes = IndexUtils.supportedSizes[1]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID, [ IndexUtils.supportedSizes[0] ], { slotSize: slotSizes }) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to AS'); - }); - - it('test_prebid_indexAdapter_request_different_type_adUnits: both display and video slots -> 2 Ad Server requests, 1 for display and 1 for video', function() { - var videoConfig = { - 'siteID': 6, - 'playerType': 'HTML5', - 'protocols': ['VAST2', 'VAST3'], - 'maxduration': 15 - } - var videoWidth = 640; - var videoHeight = 480; - var configuredBids = IndexUtils.createBidSlots(2); - configuredBids[1].params.video = Object.assign({}, videoConfig); - configuredBids[1].mediaType = 'video'; - configuredBids[1].sizes[0] = videoWidth; - configuredBids[1].sizes[1] = videoHeight; - - adapter.callBids({ bids: configuredBids }); - - sinon.assert.calledTwice(adLoader.loadScript); - - // Check request for display ads - assert.include(adLoader.loadScript.secondCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.secondCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = [IndexUtils.expandSizes(configuredBids[0])]; - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.isString(requestJSON.r.id, 'ID is string'); - - // Check request for video ads - let cygnusRequestUrl = url.parse(encodeURIComponent(adLoader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].ext.siteID).to.equal(videoConfig.siteID); - expect(cygnusRequestUrl.search.r.imp[0].video.maxduration).to.equal(videoConfig.maxduration); - expect(cygnusRequestUrl.search.r.imp[0].video.w).to.equal(videoWidth); - expect(cygnusRequestUrl.search.r.imp[0].video.h).to.equal(videoHeight); - }); -}); diff --git a/test/spec/modules/indexExchangeBidAdapter_response_spec.js b/test/spec/modules/indexExchangeBidAdapter_response_spec.js deleted file mode 100644 index 817244a2c68..00000000000 --- a/test/spec/modules/indexExchangeBidAdapter_response_spec.js +++ /dev/null @@ -1,1170 +0,0 @@ -import Adapter from 'modules/indexExchangeBidAdapter'; -import bidManager from 'src/bidmanager'; -import adLoader from 'src/adloader'; - -var assert = require('chai').assert; -var IndexUtils = require('../../helpers/index_adapter_utils.js'); -var HeaderTagRequest = '/cygnus'; -var SlotThreshold = 20; -var ADAPTER_CODE = 'indexExchange'; -var DefaultValue = { - dealID: 'IXDeal' -}; -window.pbjs = window.pbjs || {}; -var ResponseStatus = { - noBid: 'Bid returned empty or error response' -}; - -describe('indexExchange adapter - Response', function () { - let adapter; - let sandbox; - - beforeEach(function() { - window._IndexRequestData = {}; - _IndexRequestData.impIDToSlotID = {}; - _IndexRequestData.reqOptions = {}; - _IndexRequestData.targetIDToResp = {}; - window.cygnus_index_args = {}; - - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - sandbox.stub(bidManager, 'addBidResponse'); - sandbox.stub(adLoader, 'loadScript'); - }); - - afterEach(function() { - sandbox.restore(); - }); - - it('test_prebid_indexAdapter_response_1_1: response for single slot with single size -> bid fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - assert.equal(pair.prebid.length, 1, 'Only one bid is ferched into prebid'); - assert.equal(pair.prebid[0].siteID, pair.expected[0].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[0].siteID); - assert.equal(pair.prebid[0].bidderCode, pair.expected[0].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[0].bidderCode); - assert.equal(pair.prebid[0].width, pair.expected[0].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[0].width); - assert.equal(pair.prebid[0].height, pair.expected[0].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[0].height); - assert.equal(pair.prebid[0].ad, pair.expected[0].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[0].ad); - assert.equal(pair.prebid[0].cpm, pair.expected[0].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[0].cpm); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_1_2: pass on bid for single slot with single size -> bid fetched into prebid', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot1', [ IndexUtils.supportedSizes[0] ]), - ]; - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, [ [ true ] ]); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - assert.equal(prebidResponsePair.matched.length, 0, 'No bids are added to prebid'); - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 1, 'no Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_2_1: response for single slot with multiple sizes -> all bids fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(1, 3); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse, [ [1000, 3000, 2000] ]); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - assert.equal(pair.prebid.length, 3, 'all bids are fetched into prebid'); - for (var j = 0; j < pair.prebid.length; j++) { - assert.equal(pair.prebid[j].siteID, pair.expected[j].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[j].siteID); - assert.equal(pair.prebid[j].bidderCode, pair.expected[j].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[j].bidderCode); - assert.equal(pair.prebid[j].width, pair.expected[j].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[j].width); - assert.equal(pair.prebid[j].height, pair.expected[j].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[j].height); - assert.equal(pair.prebid[j].ad, pair.expected[j].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[j].ad); - assert.equal(pair.prebid[j].cpm, pair.expected[j].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[j].cpm); - } - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_2_2: pass on bid on some sizes for single slot with multiple sizes -> highest bid fetched into prebid', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot1', [ IndexUtils.supportedSizes[0], IndexUtils.supportedSizes[1] ]), - ]; - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - // pass on bid on second size - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, [ [ false, true ] ]); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - assert.equal(prebidResponsePair.matched.length, 1, 'one slot is added to prebid'); - var pair = prebidResponsePair.matched[0]; - assert.equal(pair.prebid[0].siteID, pair.expected[0].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[0].siteID); - assert.equal(pair.prebid[0].bidderCode, pair.expected[0].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[0].bidderCode); - assert.equal(pair.prebid[0].width, pair.expected[0].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[0].width); - assert.equal(pair.prebid[0].height, pair.expected[0].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[0].height); - assert.equal(pair.prebid[0].ad, pair.expected[0].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[0].ad); - assert.equal(pair.prebid[0].cpm, pair.expected[0].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[0].cpm); - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_2_3: pass on bid on all sizes for a single slot -> no bids fetched into prebid', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot1', [ IndexUtils.supportedSizes[0], IndexUtils.supportedSizes[1] ]), - ]; - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - // pass on bid on all bids - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, [ [ true, true ] ]); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - assert.equal(prebidResponsePair.matched.length, 0, 'no bids fetched into prebid'); - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid[0][0].statusMessage, ResponseStatus.noBid, 'Bid response status is set to ' + ResponseStatus.noBid); - }); - - it('test_prebid_indexAdapter_response_3_1: response for multiple slots request with single size for each slots -> all response for all adunit fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(20); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse, [ [1000, 3000, 2000] ]); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - assert.equal(pair.prebid.length, 1, 'all bids are fetched into prebid'); - assert.equal(pair.prebid[0].siteID, pair.expected[0].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[0].siteID); - assert.equal(pair.prebid[0].bidderCode, pair.expected[0].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[0].bidderCode); - assert.equal(pair.prebid[0].width, pair.expected[0].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[0].width); - assert.equal(pair.prebid[0].height, pair.expected[0].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[0].height); - assert.equal(pair.prebid[0].ad, pair.expected[0].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[0].ad); - assert.equal(pair.prebid[0].cpm, pair.expected[0].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[0].cpm); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_3_2: some slots response returned -> returned bids fetched into prebid ', function () { - var configuredBids = IndexUtils.createBidSlots(2); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - var passOnBid = [ - [ false ], // bids back on first slot - [ true ], // pass on bid on second slot - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, passOnBid); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse, [ [1000, 3000, 2000] ]); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - assert.equal(prebidResponsePair.matched.length, 1, '1 bid from ad server is fetched into prebid'); - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - assert.equal(pair.prebid.length, 1, 'all bids are fetched into prebid'); - assert.equal(pair.prebid[0].siteID, pair.expected[0].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[0].siteID); - assert.equal(pair.prebid[0].bidderCode, pair.expected[0].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[0].bidderCode); - assert.equal(pair.prebid[0].width, pair.expected[0].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[0].width); - assert.equal(pair.prebid[0].height, pair.expected[0].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[0].height); - assert.equal(pair.prebid[0].ad, pair.expected[0].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[0].ad); - assert.equal(pair.prebid[0].cpm, pair.expected[0].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[0].cpm); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 1, 'One slot passed on bid from Ad Server'); - }); - - it('test_prebid_indexAdapter_response_3_3: response for multiple slots with no response returned -> no bid fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(2); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - var passOnBid = [ - [ true ], // pass on bid on the first slot - [ true ], // pass on bid on the second slot - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, passOnBid); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse, [ [1000, 3000, 2000] ]); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - assert.equal(prebidResponsePair.matched.length, 0, 'no bids from ad server is fetched into prebid'); - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 2, 'two slots passed on bid from Ad Server'); - }); - - it("test_prebid_indexAdapter_refreshSlot_1: slot refreshes multiple times with different bids on refresh with same price -> response to prebid use correct AS response's creative", function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - - var refreshSetup = [ {price: 1000, request: 'request-1'}, {price: 1000, request: 'request-2'} ]; - for (var i = 0; i < refreshSetup.length; i++) { - var requestParams = refreshSetup[i]; - - adapter.callBids({ bids: configuredBids }); - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - // first ix call - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, [ [requestParams.price] ], requestParams.request); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var j = 0; j < prebidResponsePair.matched.length; j++) { - var pair = prebidResponsePair.matched[j]; - - assert.equal(pair.prebid.length, 1, 'all bids are fetched into prebid'); - for (var k = 0; k < pair.prebid.length; k++) { - assert.equal(pair.prebid[k].siteID, pair.expected[k].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[k].siteID); - assert.equal(pair.prebid[k].bidderCode, pair.expected[k].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[k].bidderCode); - assert.equal(pair.prebid[k].width, pair.expected[k].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[k].width); - assert.equal(pair.prebid[k].height, pair.expected[k].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[k].height); - assert.equal(pair.prebid[k].ad, pair.expected[k].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[k].ad); - assert.equal(pair.prebid[k].cpm, pair.expected[k].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[k].cpm); - } - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - - bidManager.addBidResponse.reset(); - adapterResponse = {}; // initialize adapterReaponse for refresh test - } - }); - - it("test_prebid_indexAdapter_refreshSlot_2: slot refreshes multiple times with different bids on refresh with different price, but first bid is higher -> response to prebid use correct AS response's creative", function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - - var refreshSetup = [ {price: 8000, request: 'request-1'}, {price: 1000, request: 'request-2'} ]; - for (var i = 0; i < refreshSetup.length; i++) { - var requestParams = refreshSetup[i]; - - adapter.callBids({ bids: configuredBids }); - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - // first ix call - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, [ [requestParams.price] ], requestParams.request); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var j = 0; j < prebidResponsePair.matched.length; j++) { - var pair = prebidResponsePair.matched[j]; - - assert.equal(pair.prebid.length, 1, 'all bids are fetched into prebid'); - for (var k = 0; k < pair.prebid.length; k++) { - assert.equal(pair.prebid[k].siteID, pair.expected[k].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[k].siteID); - assert.equal(pair.prebid[k].bidderCode, pair.expected[k].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[k].bidderCode); - assert.equal(pair.prebid[k].width, pair.expected[k].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[k].width); - assert.equal(pair.prebid[k].height, pair.expected[k].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[k].height); - assert.equal(pair.prebid[k].ad, pair.expected[k].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[k].ad); - assert.equal(pair.prebid[k].cpm, pair.expected[k].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[k].cpm); - } - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - bidManager.addBidResponse.reset(); - adapterResponse = {}; // initialize adapterReaponse for refresh test - } - }); - - it("test_prebid_indexAdapter_refreshSlot_3: slot refreshes multiple times with different bids on refresh with different price, but first bid is lower -> response to prebid use correct AS response's creative", function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - - var refreshSetup = [ {price: 1000, request: 'request-1'}, {price: 8000, request: 'request-2'} ]; - for (var i = 0; i < refreshSetup.length; i++) { - var requestParams = refreshSetup[i]; - - adapter.callBids({ bids: configuredBids }); - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - // first ix call - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, [ [requestParams.price] ], requestParams.request); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var j = 0; j < prebidResponsePair.matched.length; j++) { - var pair = prebidResponsePair.matched[j]; - - assert.equal(pair.prebid.length, 1, 'all bids are fetched into prebid'); - for (var k = 0; k < pair.prebid.length; k++) { - assert.equal(pair.prebid[k].siteID, pair.expected[k].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[k].siteID); - assert.equal(pair.prebid[k].bidderCode, pair.expected[k].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[k].bidderCode); - assert.equal(pair.prebid[k].width, pair.expected[k].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[k].width); - assert.equal(pair.prebid[k].height, pair.expected[k].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[k].height); - assert.equal(pair.prebid[k].ad, pair.expected[k].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[k].ad); - assert.equal(pair.prebid[k].cpm, pair.expected[k].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[k].cpm); - } - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - bidManager.addBidResponse.reset(); - adapterResponse = {}; // initialize adapterReaponse for refresh test - } - }); - - it('test_prebid_indexAdapter_refreshSlot_4: got no response the second time -> no bids fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - - var refreshSetup = [ { price: 1000, request: 'request-1', passOnBid: false}, { price: 1000, request: 'request-2', passOnBid: true} ]; - for (var i = 0; i < refreshSetup.length; i++) { - var requestParams = refreshSetup[i]; - - adapter.callBids({ bids: configuredBids }); - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - - // first ix call - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, [ [requestParams.price] ], requestParams.request, [ [ requestParams.passOnBid ] ]); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var j = 0; j < prebidResponsePair.matched.length; j++) { - var pair = prebidResponsePair.matched[j]; - - assert.equal(pair.prebid.length, 1, 'all bids are fetched into prebid'); - for (var k = 0; k < pair.prebid.length; k++) { - assert.equal(pair.prebid[k].siteID, pair.expected[k].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[k].siteID); - assert.equal(pair.prebid[k].bidderCode, pair.expected[k].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[k].bidderCode); - assert.equal(pair.prebid[k].width, pair.expected[k].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[k].width); - assert.equal(pair.prebid[k].height, pair.expected[k].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[k].height); - assert.equal(pair.prebid[k].ad, pair.expected[k].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[k].ad); - assert.equal(pair.prebid[k].cpm, pair.expected[k].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[k].cpm); - } - } - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - if (requestParams.passOnBid) { - assert.equal(prebidResponsePair.unmatched.prebid.length, 1, '1 Adapter response is missing'); - } else { - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - } - - bidManager.addBidResponse.reset(); - adapterResponse = {}; // initialize adapterReaponse for refresh test - } - }); - - it('test_prebid_indexAdapter_refreshSlot_5: unsupported slots refresh -> no ad server request, no bids fetched into prebid', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.unsupportedSizes[0] ]) - ]; - - var refreshSetup = [ { request: 'request-1' }, { request: 'request-2' } ]; - for (var i = 0; i < refreshSetup.length; i++) { - var requestParams = refreshSetup[i]; - - adapter.callBids({ bids: configuredBids }); - assert.isFalse(adLoader.loadScript.called, 'no ad server request for ' + requestParams.request) - } - }); - - it('test_prebid_indexAdapter_response_deal_1_1: response for single slot with single size contains alpha deal -> bid fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { dealid: 'ixDeal' } } // first slot first size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - assert.equal(pair.prebid[i].siteID, pair.expected[i].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[i].siteID); - assert.equal(pair.prebid[i].bidderCode, pair.expected[i].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[i].bidderCode); - assert.equal(pair.prebid[i].width, pair.expected[i].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[i].width); - assert.equal(pair.prebid[i].height, pair.expected[i].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[i].height); - assert.equal(pair.prebid[i].ad, pair.expected[i].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[i].ad); - assert.equal(pair.prebid[i].cpm, pair.expected[i].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[i].cpm); - assert.equal(pair.prebid[i].dealId, pair.expected[i].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[i].dealId); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_1_2: response for single slot with single size contains numeric deal -> bid fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { dealid: '239' } } // first slot first size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - assert.equal(pair.prebid[i].siteID, pair.expected[i].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[i].siteID); - assert.equal(pair.prebid[i].bidderCode, pair.expected[i].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[i].bidderCode); - assert.equal(pair.prebid[i].width, pair.expected[i].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[i].width); - assert.equal(pair.prebid[i].height, pair.expected[i].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[i].height); - assert.equal(pair.prebid[i].ad, pair.expected[i].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[i].ad); - assert.equal(pair.prebid[i].cpm, pair.expected[i].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[i].cpm); - assert.equal(pair.prebid[i].dealId, pair.expected[i].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[i].dealId); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_1_3: response for single slot with single size contains alpha-numeric deal starting with numeric -> bid fetched into prebid', function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { dealid: '1234Deal' } } // first slot first size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - assert.equal(pair.prebid[i].siteID, pair.expected[i].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[i].siteID); - assert.equal(pair.prebid[i].bidderCode, pair.expected[i].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[i].bidderCode); - assert.equal(pair.prebid[i].width, pair.expected[i].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[i].width); - assert.equal(pair.prebid[i].height, pair.expected[i].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[i].height); - assert.equal(pair.prebid[i].ad, pair.expected[i].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[i].ad); - assert.equal(pair.prebid[i].cpm, pair.expected[i].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[i].cpm); - assert.equal(pair.prebid[i].dealId, pair.expected[i].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[i].dealId); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_1_4: response for single slot with single size contains alpha-numeric deal starting with non-numeric -> bid fetched into prebid ', function () { - var configuredBids = IndexUtils.createBidSlots(1, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { dealid: 'deal1234' } } // first slot first size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); // Alpha numeric starting with non-numeric - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - assert.equal(pair.prebid[i].siteID, pair.expected[i].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[i].siteID); - assert.equal(pair.prebid[i].bidderCode, pair.expected[i].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[i].bidderCode); - assert.equal(pair.prebid[i].width, pair.expected[i].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[i].width); - assert.equal(pair.prebid[i].height, pair.expected[i].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[i].height); - assert.equal(pair.prebid[i].ad, pair.expected[i].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[i].ad); - assert.equal(pair.prebid[i].cpm, pair.expected[i].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[i].cpm); - assert.equal(pair.prebid[i].dealId, pair.expected[i].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[i].dealId); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_2_1: response for single slot with multi size, all deal bids returned -> all bid fetched into prebid as deal bid', function () { - var sizeCount = 2; - var configuredBids = IndexUtils.createBidSlots(1, sizeCount); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { deal: 'deal1', dealid: 'ixDealID1', dealname: 'deal name 1' } }, // first slot first size - { ext: { deal: 'deal2', dealid: 'ixDealID2', dealname: 'deal name 2' } }, // first slot second size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - for (var j = 0; j < pair.expected.length; j++) { - assert.equal(pair.prebid[j].siteID, pair.expected[j].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[i].siteID); - assert.equal(pair.prebid[j].bidderCode, pair.expected[j].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[i].bidderCode); - assert.equal(pair.prebid[j].width, pair.expected[j].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[i].width); - assert.equal(pair.prebid[j].height, pair.expected[j].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[i].height); - assert.equal(pair.prebid[j].ad, pair.expected[j].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[i].ad); - assert.equal(pair.prebid[j].cpm, pair.expected[j].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[i].cpm); - assert.equal(pair.prebid[j].dealId, pair.expected[j].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[i].dealId); - } - } - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_2_2: response for single slot with multi size, some deal resposne returned and the rest non deal response -> all bid fetched, only deal response has dealID', function () { - var sizeCount = 2; - var configuredBids = IndexUtils.createBidSlots(1, sizeCount); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { deal: 'deal1', dealid: 'ixDealID1', dealname: 'deal name 1' } } // first slot first size - // No deal on first slot second size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - - for (var j = 0; j < pair.expected.length; j++) { - assert.equal(pair.prebid[j].siteID, pair.expected[j].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[i].siteID); - assert.equal(pair.prebid[j].bidderCode, pair.expected[j].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[i].bidderCode); - assert.equal(pair.prebid[j].width, pair.expected[j].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[i].width); - assert.equal(pair.prebid[j].height, pair.expected[j].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[i].height); - assert.equal(pair.prebid[j].ad, pair.expected[j].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[i].ad); - assert.equal(pair.prebid[j].cpm, pair.expected[j].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[i].cpm); - if (i === 0) { - assert.equal(pair.prebid[j].dealId, pair.expected[j].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[i].dealId); - } else { - assert.isUndefined(pair.prebid[j].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is not set'); - } - } - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_2_3: response for single slot with multi size, all returned as non-deal response -> all bid fetched, no response has dealID', function () { - var sizeCount = 2; - var configuredBids = IndexUtils.createBidSlots(1, sizeCount); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - {}, - {} - // No deal on first slot first size - // No deal on first slot second size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - for (var j = 0; j < pair.expected.length; j++) { - assert.equal(pair.prebid[i].siteID, pair.expected[i].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[i].siteID); - assert.equal(pair.prebid[i].bidderCode, pair.expected[i].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[i].bidderCode); - assert.equal(pair.prebid[i].width, pair.expected[i].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[i].width); - assert.equal(pair.prebid[i].height, pair.expected[i].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[i].height); - assert.equal(pair.prebid[i].ad, pair.expected[i].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[i].ad); - assert.equal(pair.prebid[i].cpm, pair.expected[i].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[i].cpm); - assert.isUndefined(pair.prebid[i].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is not set'); - } - } - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_3_1: multi slots, all responses contain deal -> all bid fetched into prebid as deal bid', function () { - var slotCount = 2; - var configuredBids = IndexUtils.createBidSlots(slotCount, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { dealid: 'ixDeal1' } } // first slot first size - ], - [ - { ext: { dealid: 'ixDeal2' } } // second slot first size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - assert.equal(pair.prebid[0].siteID, pair.expected[0].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[0].siteID); - assert.equal(pair.prebid[0].bidderCode, pair.expected[0].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[0].bidderCode); - assert.equal(pair.prebid[0].width, pair.expected[0].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[0].width); - assert.equal(pair.prebid[0].height, pair.expected[0].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[0].height); - assert.equal(pair.prebid[0].ad, pair.expected[0].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[0].ad); - assert.equal(pair.prebid[0].cpm, pair.expected[0].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[0].cpm); - assert.equal(pair.prebid[0].dealId, pair.expected[0].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[0].dealId); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_3_2: multi slots, some responses contain deal -> all bid fetched, only deal response has dealID', function () { - var slotCount = 2; - var configuredBids = IndexUtils.createBidSlots(slotCount, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - { ext: { dealid: 'ixDeal1' } } // first slot first size - ], - [ - {} - // no deal on second slot first size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - var count = 0; - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - assert.equal(pair.prebid[0].siteID, pair.expected[0].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[0].siteID); - assert.equal(pair.prebid[0].bidderCode, pair.expected[0].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[0].bidderCode); - assert.equal(pair.prebid[0].width, pair.expected[0].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[0].width); - assert.equal(pair.prebid[0].height, pair.expected[0].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[0].height); - assert.equal(pair.prebid[0].ad, pair.expected[0].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[0].ad); - assert.equal(pair.prebid[0].cpm, pair.expected[0].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[0].cpm); - if (count === 0) { // if first slot, check deal parameter - assert.equal(pair.prebid[0].dealId, pair.expected[0].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is set to ' + pair.expected[0].dealId); - } else { - assert.isUndefined(pair.prebid[0].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is not defined'); - } - count++; - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_response_deal_3_3: multi slots, no responses contain deal -> all bid fetched, no response has dealID ', function () { - var slotCount = 2; - var configuredBids = IndexUtils.createBidSlots(slotCount, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var optionalResponseParam = [ - [ - {} - // no deal on first slot first size - ], - [ - {} - // no deal on second slot first size - ] - ]; - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, undefined, optionalResponseParam); - cygnus_index_parse_res(asResponse); - var expectedAdapterResponse = IndexUtils.getExpectedAdaptorResponse(configuredBids, asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - - var prebidResponsePair = IndexUtils.matchOnPlacementCode(expectedAdapterResponse, adapterResponse); - - for (var i = 0; i < prebidResponsePair.matched.length; i++) { - var pair = prebidResponsePair.matched[i]; - assert.equal(pair.prebid[0].siteID, pair.expected[0].siteID, 'adapter response for ' + pair.placementCode + ' siteID is set to ' + pair.expected[0].siteID); - assert.equal(pair.prebid[0].bidderCode, pair.expected[0].bidderCode, 'adapter response for ' + pair.placementCode + ' bidderCode is set to ' + pair.expected[0].bidderCode); - assert.equal(pair.prebid[0].width, pair.expected[0].width, 'adapter response for ' + pair.placementCode + ' width is set to ' + pair.expected[0].width); - assert.equal(pair.prebid[0].height, pair.expected[0].height, 'adapter response for ' + pair.placementCode + ' height is set to ' + pair.expected[0].height); - assert.equal(pair.prebid[0].ad, pair.expected[0].ad, 'adapter response for ' + pair.placementCode + ' ad is set to ' + pair.expected[0].ad); - assert.equal(pair.prebid[0].cpm, pair.expected[0].cpm, 'adapter response for ' + pair.placementCode + ' cpm is set to ' + pair.expected[0].cpm); - assert.isUndefined(pair.prebid[0].dealId, 'adapter response for ' + pair.placementCode + ' deaiid is not defined'); - } - - assert.equal(prebidResponsePair.unmatched.expected.length, 0, 'All AS bid response translated to Adapter response for prebid'); - assert.equal(prebidResponsePair.unmatched.prebid.length, 0, 'All Adapter response for prebid is from AS bid'); - }); - - it('test_prebid_indexAdapter_tier: one slot with multiple tier -> all tier bids are fetched into prebid', function() { - var slotConfig = { - tier2SiteID: IndexUtils.DefaultSiteID + 1, - tier3SiteID: IndexUtils.DefaultSiteID + 2, - }; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], slotConfig), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - - assert.equal(sidMatched.matched.length, 3, 'Three slots are configured and sent to AS'); - // check normal site id - var normalSitePair = sidMatched.matched[0]; - - var expectedSlotID = normalSitePair.configured.params.id + '_1'; - assert.equal(normalSitePair.sent.ext.sid, expectedSlotID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSlotID); - assert.isString(normalSitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedSiteID = normalSitePair.configured.params.siteID; - assert.equal(normalSitePair.sent.ext.siteID, expectedSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(normalSitePair.sent.ext.siteID, 'site ID is integer'); - - // check tier 1 site id - var tier2SitePair = sidMatched.matched[1]; - var expectedTierSlotID = 'T1_' + tier2SitePair.configured.params.id + '_1'; - assert.equal(tier2SitePair.sent.ext.sid, expectedTierSlotID, 'request ' + tier2SitePair.name + ' site ID is set to ' + expectedTierSlotID); - assert.isString(tier2SitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedTierSiteID = tier2SitePair.configured.params.tier2SiteID; - assert.equal(tier2SitePair.sent.ext.siteID, expectedTierSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedTierSiteID); - assert.isNumber(tier2SitePair.sent.ext.siteID, 'site ID is integer'); - - // check tier 2 site id - var tier3SitePair = sidMatched.matched[2]; - var expectedTierSlotID = 'T2_' + tier3SitePair.configured.params.id + '_1'; - assert.equal(tier3SitePair.sent.ext.sid, expectedTierSlotID, 'request ' + tier3SitePair.name + ' site ID is set to ' + expectedTierSlotID); - assert.isString(tier3SitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedTier3SiteID = tier3SitePair.configured.params.tier3SiteID; - assert.equal(tier3SitePair.sent.ext.siteID, expectedTier3SiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedTier3SiteID); - assert.isNumber(tier3SitePair.sent.ext.siteID, 'site ID is integer'); - - // check unsent bids - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_callback_bids: callback function defined with bids -> calls callback function with bids', function () { - var callbackCalled = false; - var callback_requestID; - var callback_slots; - window.cygnus_index_args['callback'] = function(requestID, slots) { - callbackCalled = true; - callback_requestID = requestID; - callback_slots = slots; - } - - var configuredBids = IndexUtils.createBidSlots(1, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON); - cygnus_index_parse_res(asResponse); - - assert.equal(callbackCalled, true, 'callback function is called'); - assert.equal(callback_requestID, requestJSON.r.id, 'callback requestID matches with actual request ID: ' + requestJSON.r.id); - assert.equal(callback_slots.length, 1, 'callback slots include one slot'); - }); - - it('test_prebid_indexAdapter_callback_nobids: callback function defined with no bids -> calls callback function without bids', function () { - var callbackCalled = false; - var callback_requestID; - var callback_slots; - window.cygnus_index_args['callback'] = function(requestID, slots) { - callbackCalled = true; - callback_requestID = requestID; - callback_slots = slots; - } - - var configuredBids = IndexUtils.createBidSlots(1, 1); - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, [[true]]); // pass on bid - cygnus_index_parse_res(asResponse); - - assert.equal(callbackCalled, true, 'callback function is called'); - assert.equal(callback_requestID, requestJSON.r.id, 'callback requestID matches with actual request ID: ' + requestJSON.r.id); - assert.isUndefined(callback_slots, 'callback slot is undefined because all bids passed on bid'); - }); - - it('test_prebid_indexAdapter_response_sizeID_1: multiple prebid size slot, index slots with size for all prebid slots -> all size in AS request, no size ID', function () { - var slotID_1 = '52'; - var slotID_2 = '53'; - var slotSizes_1 = IndexUtils.supportedSizes[0]; - var slotSizes_2 = IndexUtils.supportedSizes[1]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + slotID_1, slotID_1, [ slotSizes_1, slotSizes_2 ], { slotSize: slotSizes_1 }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + slotID_2, slotID_2, [ slotSizes_1, slotSizes_2 ], { siteID: IndexUtils.DefaultSiteID + 1 }) - ]; - - adapter.callBids({ bids: configuredBids }); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - var asResponse = IndexUtils.getBidResponse(configuredBids, requestJSON, undefined, undefined, [[true]]); // pass on bid - cygnus_index_parse_res(asResponse); - - var adapterResponse = {}; - - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - } - }); -}); diff --git a/test/spec/modules/indexExchangeBidAdapter_validation_spec.js b/test/spec/modules/indexExchangeBidAdapter_validation_spec.js deleted file mode 100644 index 46a1996cc8a..00000000000 --- a/test/spec/modules/indexExchangeBidAdapter_validation_spec.js +++ /dev/null @@ -1,1607 +0,0 @@ -import Adapter from '../../../modules/indexExchangeBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; - -var assert = require('chai').assert; -var IndexUtils = require('../../helpers/index_adapter_utils.js'); -var HeaderTagRequest = '/cygnus'; -var ADAPTER_CODE = 'indexExchange'; - -window.pbjs = window.pbjs || {}; - -describe('indexExchange adapter - Validation', function () { - let adapter; - let sandbox; - - beforeEach(function() { - window._IndexRequestData = {}; - _IndexRequestData.impIDToSlotID = {}; - _IndexRequestData.reqOptions = {}; - _IndexRequestData.targetIDToResp = {}; - window.cygnus_index_args = {}; - - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - sandbox.stub(adLoader, 'loadScript'); - sandbox.stub(bidManager, 'addBidResponse'); - }); - - afterEach(function() { - sandbox.restore(); - }); - - it('test_prebid_indexAdapter_sizeValidation_1: request slot has supported and unsupported size -> unsupported size ignored in IX demand request', function () { - // create 2 sizes for 1 slot, 1 for supported size, the other is not supported - var unsupportedSize = IndexUtils.unsupportedSizes[0]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], unsupportedSize ]) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, unsupportedSize, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize)); - - // checking bid manager responses. Only one bid back into bidmanager because one size is unsupported - var adapterResponse = {}; - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - }; - assert.deepEqual(Object.keys(adapterResponse), [IndexUtils.DefaultPlacementCodePrefix], 'bid response from placement code that is configured'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix].length, 1, 'one response back returned for placement ' + IndexUtils.DefaultPlacementCodePrefix); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - }); - - it('test_prebid_indexAdapter_sizeValidation_2_1: some slot has unsupported size -> unsupported slot ignored in IX demand request', function () { - // create 2 slot, 1 for supported size, the other is not supported - var unsupportedSize = IndexUtils.unsupportedSizes[0]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'supported', 'slot_1', [ IndexUtils.supportedSizes[0], ], { siteID: IndexUtils.DefaultSiteID }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'unspported', 'slot_2', [ unsupportedSize ], { siteID: IndexUtils.DefaultSiteID + 1}) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, unsupportedSize, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize)); - assert.equal(sidMatched.unmatched.configured[0].params.id, 'slot_2', 'configured bid not in impression obj id is slot_2'); - assert.equal(sidMatched.unmatched.configured[0].params.siteID, IndexUtils.DefaultSiteID + 1, 'configured bid not in impression obj siteID is ' + (IndexUtils.DefaultSiteID + 1)); - }); - - it('test_prebid_indexAdapter_sizeValidation_2_2: multiple slots with sinle size, all slot has supported size -> all slots are sent to IX demand', function () { - // create 2 slot, 1 for supported size, the other is not supported - var unsupportedSize = IndexUtils.unsupportedSizes[0]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'supported1', 'slot_1', [ IndexUtils.supportedSizes[0] ], { siteID: IndexUtils.DefaultSiteID }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'supported2', 'slot_2', [ IndexUtils.supportedSizes[1] ], { siteID: IndexUtils.DefaultSiteID + 1}) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 0, '0 configured bid is not in impression Obj'); - }); - - it('test_prebid_indexAdapter_sizeValidation_2_3: multiple slots with sinle size, all slot has unsupported size -> all slots are ignored', function () { - // create 2 slot, 1 for supported size, the other is not supported - var unsupportedSize = IndexUtils.unsupportedSizes[0]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'unsupported1', 'slot_1', [ IndexUtils.unsupportedSizes[0] ], { siteID: IndexUtils.DefaultSiteID }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'unsupported2', 'slot_2', [ IndexUtils.unsupportedSizes[1] ], { siteID: IndexUtils.DefaultSiteID + 1}) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to IX demand'); - }); - - it('test_prebid_indexAdapter_sizeValidation_3_1: one slot has supported, unsupported, supported size -> unsupported slot ignored in IX demand request', function () { - // create 2 slot, 1 for supported size, the other is not supported - var unsupportedSize = IndexUtils.unsupportedSizes[0]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'somesupported', 'slot_1', [ IndexUtils.supportedSizes[0], unsupportedSize, IndexUtils.supportedSizes[1] ], { siteID: IndexUtils.DefaultSiteID }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'allsupported', 'slot_2', [ IndexUtils.supportedSizes[2], IndexUtils.supportedSizes[3] ], { siteID: IndexUtils.DefaultSiteID + 1}) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, unsupportedSize, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize)); - assert.equal(sidMatched.unmatched.configured[0].params.id, 'slot_1', 'configured bid not in impression obj id is slot_1'); - assert.equal(sidMatched.unmatched.configured[0].params.siteID, IndexUtils.DefaultSiteID, 'configured bid not in impression obj siteID is ' + (IndexUtils.DefaultSiteID)); - }); - - it('test_prebid_indexAdapter_sizeValidation_3_2: one slot has unsupported, supported, unsupported size -> unsupported slot ignored in IX demand request', function () { - // create 2 slot, 1 for supported size, the other is not supported - var unsupportedSize1 = IndexUtils.unsupportedSizes[0]; - var unsupportedSize2 = IndexUtils.unsupportedSizes[1]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'somesupported', 'slot_1', [ unsupportedSize1, IndexUtils.supportedSizes[1], unsupportedSize2 ], { siteID: IndexUtils.DefaultSiteID }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'allsupported', 'slot_2', [ IndexUtils.supportedSizes[2], IndexUtils.supportedSizes[3] ], { siteID: IndexUtils.DefaultSiteID + 1}) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 2, '2 configured bid is not in impression Obj'); - - assert.equal(sidMatched.unmatched.configured[0].size, unsupportedSize1, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize1)); - assert.equal(sidMatched.unmatched.configured[0].params.id, 'slot_1', 'configured bid not in impression obj id is slot_1'); - assert.equal(sidMatched.unmatched.configured[0].params.siteID, IndexUtils.DefaultSiteID, 'configured bid not in impression obj siteID is ' + (IndexUtils.DefaultSiteID)); - - assert.equal(sidMatched.unmatched.configured[1].size, unsupportedSize2, 'configured bid not in impression obj size width is' + JSON.stringify(unsupportedSize2)); - assert.equal(sidMatched.unmatched.configured[1].params.id, 'slot_1', 'configured bid not in impression obj id is slot_1'); - assert.equal(sidMatched.unmatched.configured[1].params.siteID, IndexUtils.DefaultSiteID, 'configured bid not in impression obj siteID is ' + (IndexUtils.DefaultSiteID)); - }); - - it('test_prebid_indexAdapter_sizeValidation_3_3: multiple slots, all slots have supported size -> all slots are included in IX demand request', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'allsupported1', 'slot_1', [ IndexUtils.supportedSizes[0], IndexUtils.supportedSizes[1] ], { siteID: IndexUtils.DefaultSiteID }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + 'allsupported2', 'slot_2', [ IndexUtils.supportedSizes[2], IndexUtils.supportedSizes[3] ], { siteID: IndexUtils.DefaultSiteID + 1}) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 0, '0 configured bid is not in impression Obj'); - }); - - it('test_prebid_indexAdapter_sizeValidation_3_4: multiple slots, all slots have unsupported size -> no slots are sent to IX demand', function () { - var firstPlacement = IndexUtils.DefaultPlacementCodePrefix + 'allsupported1'; - var secondPlacement = IndexUtils.DefaultPlacementCodePrefix + 'allsupported2'; - var configuredBids = [ - IndexUtils.createBidSlot(firstPlacement, 'slot_1', [ IndexUtils.unsupportedSizes[0], IndexUtils.unsupportedSizes[1] ], { siteID: IndexUtils.DefaultSiteID }), - IndexUtils.createBidSlot(secondPlacement, 'slot_2', [ IndexUtils.unsupportedSizes[2], IndexUtils.unsupportedSizes[3] ], { siteID: IndexUtils.DefaultSiteID + 1}) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'No request to IX demand'); - - // checking bid manager responses. Only one bid back into bidmanager because one size is unsupported - var adapterResponse = {}; - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - }; - assert.deepEqual(Object.keys(adapterResponse), [firstPlacement, secondPlacement], 'bid response from placement code that is configured'); - assert.equal(adapterResponse[firstPlacement].length, 2, 'two response back returned for placement ' + firstPlacement); - assert.equal(adapterResponse[firstPlacement][0].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[firstPlacement][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - assert.equal(adapterResponse[firstPlacement][1].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[firstPlacement][1].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - assert.equal(adapterResponse[secondPlacement].length, 2, 'two response back returned for placement ' + secondPlacement); - assert.equal(adapterResponse[secondPlacement][0].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[secondPlacement][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - assert.equal(adapterResponse[secondPlacement][1].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[secondPlacement][1].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - }); - - it('test_prebid_indexAdapter_param_timeout_integer: timeout is integer -> t parameter that matches with the integer', function () { - var testTimeout = 100; // integer timeout - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.equal(requestJSON.t, testTimeout, 't parameter matches timeout and is included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_quoted_integer: timeout is quoted integer -> t parameter that matches with the integer', function () { - var testTimeout = '100'; // quoted integer timeout - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.equal(requestJSON.t, testTimeout, 't parameter matches timeout and is included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_float: timeout is float number -> t parameter is not included in AS request', function () { - var testTimeout = 1.234; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_float: timeout is float number -> t parameter is not included in AS request', function () { - var testTimeout = 1.234; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_string: timeout is string -> t parameter is not included in AS request', function () { - var testTimeout = 'string'; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_array: timeout is array -> t parameter is not included in AS request', function () { - var testTimeout = [ 'abc' ]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_hash: timeout is hash -> t parameter is not included in AS request', function () { - var testTimeout = { 'timeout': 100 }; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_zero: timeout is zero -> t parameter is not included in AS request', function () { - var testTimeout = 0; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_negative: timeout is negative integer -> t parameter is not included in AS request', function () { - var testTimeout = -100; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_too_big: timeout is bigger than AS max timeout -> t parameter is not included in AS request', function () { - var testTimeout = 25000; // very large timeout - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout }), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.equal(requestJSON.t, testTimeout, 't parameter matches timeout and is included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_missing: timeout is missing -> t parameter is not included in AS request', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ]), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - it('test_prebid_indexAdapter_param_timeout_empty_string: timeout is empty string -> t parameter is not included in AS request', function () { - var testTimeout = ''; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], { timeout: testTimeout}), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isUndefined(requestJSON.t, 't parameter is not included in AS request parameter'); - }); - - var test_indexAdapter_slotid = [ - { - 'testname': 'test_prebid_indexAdapter_slotid_integer: slot ID is integer -> slot ID sent to AS in string', - 'slotID': 123, - 'expected': 'pass' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_quoted_integer: slot ID is quoted_integer -> slot ID sent to AS in string', - 'slotID': '123', - 'expected': 'pass' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_float: slot ID is float -> slot ID sent to AS in string', - 'slotID': 123.45, - 'expected': 'pass' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_string: slot ID is string -> slot ID sent to AS in string', - 'slotID': 'string', - 'expected': 'pass' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_array: slot ID is array -> slot is not sent to AS', - 'slotID': [ 'arrayelement1', 'arrayelement2' ], - 'expected': 'fail' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_hash: slot ID is hash -> slot is not sent to AS', - 'slotID': { 'hashName': 'hashKey' }, - 'expected': 'fail' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_zero: slot ID is zero integer -> slot ID sent to AS in string', - 'slotID': 0, - 'expected': 'pass' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_negative: slot ID is negative integer -> slot ID sent to AS in string', - 'slotID': -100, - 'expected': 'pass' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_undefined: slot ID is undefined -> slot is not sent to AS', - 'slotID': undefined, - 'expected': 'fail' - }, - { - 'testname': 'test_prebid_indexAdapter_slotid_missing: slot ID is missing -> slot is not sent to AS', - 'param': { 'missingSlotID': true}, - 'expected': 'invalid' - } - ]; - - function base_prebid_indexAdapter_slotid (testname, slotID, expected, param) { - it(testname, function() { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID, [ IndexUtils.supportedSizes[0] ], param), - ]; - adapter.callBids({ bids: configuredBids }); - var adapterResponse = {}; - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - }; - if (expected == 'pass') { - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - var actualSlotID = pair.sent.ext.sid; - var expectedSlotID = pair.configured.params.id + '_1'; - assert.equal(actualSlotID, expectedSlotID, 'request ' + pair.name + ' slot ID is set to ' + expectedSlotID); - assert.isString(actualSlotID, 'slotID is string'); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.deepEqual(Object.keys(adapterResponse), [], 'no explicit pass on bid'); - } else if (expected == 'invalid') { - // case where callBids throws out request due to missing params - assert.isFalse(adLoader.loadScript.called, 'No request to AS') - assert.deepEqual(Object.keys(adapterResponse), [IndexUtils.DefaultPlacementCodePrefix], 'bid response from placement code that is configured'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix].length, 1, 'one response back returned for placement ' + IndexUtils.DefaultPlacementCodePrefix); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - } else { - assert.strictEqual(typeof indexBidRequest, 'undefined', 'No request to AS'); - assert.deepEqual(Object.keys(adapterResponse), [IndexUtils.DefaultPlacementCodePrefix], 'bid response from placement code that is configured'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix].length, 1, 'one response back returned for placement ' + IndexUtils.DefaultPlacementCodePrefix); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - } - }); - }; - - for (var i = 0; i < test_indexAdapter_slotid.length; i++) { - var test = test_indexAdapter_slotid[i]; - base_prebid_indexAdapter_slotid(test.testname, test.slotID, test.expected, test.param); - } - - it('test_prebid_indexAdapter_slotid_multiple_slot: uniqueness for multiple slots -> all slots in ad server request with unique slot id', function() { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ]), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_2', [ IndexUtils.supportedSizes[1] ]), - ]; - adapter.callBids({ bids: configuredBids }); - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - var actualSlotID = pair.sent.ext.sid; - var expectedSlotID = pair.configured.params.id + '_1'; - assert.equal(actualSlotID, expectedSlotID, 'request ' + pair.name + ' slot ID is set to ' + expectedSlotID); - assert.isString(actualSlotID, 'slotID is string'); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_slotid_multiple_same: same across some slots -> all slots in ad server request with same slot id', function() { - var slotName = 'slot_same'; - var secondSlotSize = IndexUtils.supportedSizes[1]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotName, [ IndexUtils.supportedSizes[0] ]), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotName, [ secondSlotSize ]), - ]; - adapter.callBids({ bids: configuredBids }); - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - var actualSlotID = pair.sent.ext.sid; - var expectedSlotID = pair.configured.params.id + '_1'; - assert.equal(actualSlotID, expectedSlotID, 'request ' + pair.name + ' slot ID is set to ' + expectedSlotID); - assert.isString(actualSlotID, 'slotID is string'); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.equal(sidMatched.unmatched.configured.length, 1, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, secondSlotSize, 'configured bid not in impression obj size width is' + JSON.stringify(secondSlotSize)); - assert.equal(sidMatched.unmatched.configured[0].params.id, slotName, 'slot name is ' + slotName); - }); - - var test_indexAdapter_siteid = [ - { - 'testname': 'test_prebid_indexAdapter_siteid_integer: site ID is integer -> siteID ID sent to AS as integer', - 'param': { 'siteID': 12345 }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_quoted_integer: site ID is quoted integer -> siteID ID sent to AS as integer', - 'param': { 'siteID': '12345' }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_float: site ID is float -> slot is ignored', - 'param': { 'siteID': 12.345 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_string: site ID is string -> slot is ignored', - 'param': { 'siteID': 'string' }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_array: site ID is array with int -> siteID sent to AS as integer', - 'param': { 'siteID': [ 12345 ] }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_array: site ID is array with quoted int -> siteID sent to AS as integer', - 'param': { 'siteID': [ '12345' ] }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_array: site ID is array with alpha string -> slot is ignored', - 'param': { 'siteID': [ 'ABC' ] }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_hash: site ID is hash -> slot is ignored', - 'param': { 'siteID': { 12345: 678 } }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_zero: site ID is zero integer -> slot is ignored', - 'param': { 'siteID': 0 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_negative: site ID is a negative integer -> slot is ignored', - 'param': { 'siteID': -1234 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_siteid_missing: site ID is missing -> slot is ignored', - 'param': { 'missingSiteID': true }, - 'expected': 'invalid', - }, - ]; - - function base_prebid_indexAdapter_siteid (testname, param, expected) { - it(testname, function() { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], param), - ]; - - adapter.callBids({ bids: configuredBids }); - var adapterResponse = {}; - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - }; - if (expected == 'pass') { - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - var actualSiteID = pair.sent.ext.siteID; - var expectedSiteID = pair.configured.params.siteID; - assert.equal(actualSiteID, expectedSiteID, 'request ' + pair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(actualSiteID, 'site ID is integer'); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.deepEqual(Object.keys(adapterResponse), [], 'no explicit pass on bid'); - } else if (expected == 'invalid') { - // case where callBids throws out request due to missing params - assert.isFalse(adLoader.loadScript.called, 'No request to AS'); - assert.deepEqual(Object.keys(adapterResponse), [IndexUtils.DefaultPlacementCodePrefix], 'bid response from placement code that is configured'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix].length, 1, 'one response back returned for placement ' + IndexUtils.DefaultPlacementCodePrefix); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - } else { - assert.isFalse(adLoader.loadScript.called, 'No request to AS'); - assert.deepEqual(Object.keys(adapterResponse), [IndexUtils.DefaultPlacementCodePrefix], 'bid response from placement code that is configured'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix].length, 1, 'one response back returned for placement ' + IndexUtils.DefaultPlacementCodePrefix); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].bidderCode, ADAPTER_CODE, 'bidder code match with adapter\'s name'); - assert.equal(adapterResponse[IndexUtils.DefaultPlacementCodePrefix][0].statusMessage, 'Bid returned empty or error response', 'pass on bid message'); - } - }); - }; - - for (var i = 0; i < test_indexAdapter_siteid.length; i++) { - var test = test_indexAdapter_siteid[i]; - base_prebid_indexAdapter_siteid(test.testname, test.param, test.expected); - } - - // TS: case created by PBA-12 - it('test_prebid_indexAdapter_second_siteid_float: site ID is float -> slot is ignored', function() { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + '1', 'slot_1', [ IndexUtils.supportedSizes[0] ]), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix + '2', 'slot_2', [ IndexUtils.supportedSizes[1] ], { 'siteID': 123.45 }), - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - assert.equal(sidMatched.matched.length, 1, 'one slot is configured and sent to AS'); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - var actualSiteID = pair.sent.ext.siteID; - var expectedSiteID = pair.configured.params.siteID; - assert.equal(actualSiteID, expectedSiteID, 'request ' + pair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(actualSiteID, 'site ID is integer'); - } - - assert.equal(sidMatched.unmatched.configured.length, 1, 'float site ID configured bid is missing in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - var test_indexAdapter_tier2siteid = [ - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_integer: tier2 site ID is integer -> siteID ID sent to AS in integer', - 'param': { 'tier2SiteID': 12345 }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_quoted_integer: tier2 site ID is quoted integer -> siteID ID sent to AS in integer', - 'param': { 'tier2SiteID': '12345' }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_float: tier2 site ID is float -> slot is ignored', - 'param': { 'tier2SiteID': 12.345 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_string: tier2 site ID is string -> slot is ignored', - 'param': { 'tier2SiteID': 'string' }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_array: tier2 site ID is array -> slot is ignored', - 'param': { 'tier2SiteID': [ 12345 ] }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_hash: tier2 site ID is hash -> slot is ignored', - 'param': { 'tier2SiteID': { 12345: 678 } }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_zero: tier2 site ID is zero integer -> slot is ignored', - 'param': { 'tier2SiteID': 0 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_negative: tier2 site ID is a negative integer -> slot is ignored', - 'param': { 'tier2SiteID': -1234 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier2siteid_missing: tier2 site ID is missing -> slot is ignored', - 'param': { 'missingtier2SiteID': true }, - 'expected': 'fail', - }, - ]; - function base_prebid_indexAdapter_tier2siteid (testname, param, expected) { - it(testname, function() { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], param), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - - var adapterResponse = {}; - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - }; - if (expected == 'pass') { - assert.equal(sidMatched.matched.length, 2, 'Two slots are configured and sent to AS'); - - // check normal site id - var normalSitePair = sidMatched.matched[0]; - - var expectedSlotID = normalSitePair.configured.params.id + '_1'; - assert.equal(normalSitePair.sent.ext.sid, expectedSlotID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSlotID); - assert.isString(normalSitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedSiteID = normalSitePair.configured.params.siteID; - assert.equal(normalSitePair.sent.ext.siteID, expectedSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(normalSitePair.sent.ext.siteID, 'site ID is integer'); - - // check tier site id - var tier2SitePair = sidMatched.matched[1]; - var expectedTierSlotID = 'T1_' + tier2SitePair.configured.params.id + '_1'; - assert.equal(tier2SitePair.sent.ext.sid, expectedTierSlotID, 'request ' + tier2SitePair.name + ' site ID is set to ' + expectedTierSlotID); - assert.isString(tier2SitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedTierSiteID = tier2SitePair.configured.params.tier2SiteID; - assert.equal(tier2SitePair.sent.ext.siteID, expectedTierSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedTierSiteID); - assert.isNumber(tier2SitePair.sent.ext.siteID, 'site ID is integer'); - - // check unsent bids - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.deepEqual(Object.keys(adapterResponse), [], 'no explicit pass on bid'); - } else { - assert.equal(sidMatched.matched.length, 1, 'one slot is configured and sent to AS'); - - // check normal site id - var normalSitePair = sidMatched.matched[0]; - - var expectedSlotID = normalSitePair.configured.params.id + '_1'; - assert.equal(normalSitePair.sent.ext.sid, expectedSlotID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSlotID); - assert.isString(normalSitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedSiteID = normalSitePair.configured.params.siteID; - assert.equal(normalSitePair.sent.ext.siteID, expectedSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(normalSitePair.sent.ext.siteID, 'site ID is integer'); - - // check unsent bids - if (param.missingtier2SiteID) { - assert.equal(sidMatched.unmatched.configured.length, 0, 'one configured bid is missing in impression Obj'); - } else { - assert.equal(sidMatched.unmatched.configured.length, 1, 'one configured bid is missing in impression Obj'); - } - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.deepEqual(Object.keys(adapterResponse), [], 'no explicit pass on bid'); - } - }); - }; - - for (var i = 0; i < test_indexAdapter_tier2siteid.length; i++) { - var test = test_indexAdapter_tier2siteid[i]; - base_prebid_indexAdapter_tier2siteid(test.testname, test.param, test.expected); - } - - var test_indexAdapter_tier3siteid = [ - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_integer: tier3 site ID is integer -> siteID ID sent to AS in integer', - 'param': { 'tier3SiteID': 12345 }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_quoted_integer: tier3 site ID is quoted integer -> siteID ID sent to AS in integer', - 'param': { 'tier3SiteID': '12345' }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_float: tier3 site ID is float -> slot is ignored', - 'param': { 'tier3SiteID': 12.345 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_string: tier3 site ID is string -> slot is ignored', - 'param': { 'tier3SiteID': 'string' }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_array: tier3 site ID is array -> slot is ignored', - 'param': { 'tier3SiteID': [ 12345 ] }, - 'expected': 'pass', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_hash: tier3 site ID is hash -> slot is ignored', - 'param': { 'tier3SiteID': { 12345: 678 } }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_zero: tier3 site ID is zero integer -> slot is ignored', - 'param': { 'tier3SiteID': 0 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_negative: tier3 site ID is a negative integer -> slot is ignored', - 'param': { 'tier3SiteID': -1234 }, - 'expected': 'fail', - }, - { - 'testname': 'test_prebid_indexAdapter_tier3siteid_missing: tier3 site ID is missing -> slot is ignored', - 'param': { 'missingtier3SiteID': true }, - 'expected': 'fail', - }, - ]; - function base_prebid_indexAdapter_tier3siteid (testname, param, expected) { - it(testname, function() { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0] ], param), - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - - var adapterResponse = {}; - for (var i = 0; i < bidManager.addBidResponse.callCount; i++) { - var adUnitCode = bidManager.addBidResponse.getCall(i).args[0]; - var bid = bidManager.addBidResponse.getCall(i).args[1]; - - if (typeof adapterResponse[adUnitCode] === 'undefined') { - adapterResponse[adUnitCode] = []; - }; - adapterResponse[adUnitCode].push(bid); - }; - if (expected == 'pass') { - assert.equal(sidMatched.matched.length, 2, 'Two slots are configured and sent to AS'); - - // check normal site id - var normalSitePair = sidMatched.matched[0]; - - var expectedSlotID = normalSitePair.configured.params.id + '_1'; - assert.equal(normalSitePair.sent.ext.sid, expectedSlotID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSlotID); - assert.isString(normalSitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedSiteID = normalSitePair.configured.params.siteID; - assert.equal(normalSitePair.sent.ext.siteID, expectedSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(normalSitePair.sent.ext.siteID, 'site ID is integer'); - - // check tier site id - var tier3SitePair = sidMatched.matched[1]; - var expectedTierSlotID = 'T2_' + tier3SitePair.configured.params.id + '_1'; - assert.equal(tier3SitePair.sent.ext.sid, expectedTierSlotID, 'request ' + tier3SitePair.name + ' site ID is set to ' + expectedTierSlotID); - assert.isString(tier3SitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedTierSiteID = tier3SitePair.configured.params.tier3SiteID; - assert.equal(tier3SitePair.sent.ext.siteID, expectedTierSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedTierSiteID); - assert.isNumber(tier3SitePair.sent.ext.siteID, 'site ID is integer'); - - // check unsent bids - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.deepEqual(Object.keys(adapterResponse), [], 'no explicit pass on bid'); - } else { - assert.equal(sidMatched.matched.length, 1, 'one slot is configured and sent to AS'); - - // check normal site id - var normalSitePair = sidMatched.matched[0]; - - var expectedSlotID = normalSitePair.configured.params.id + '_1'; - assert.equal(normalSitePair.sent.ext.sid, expectedSlotID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSlotID); - assert.isString(normalSitePair.sent.ext.sid, 'type of slot ID is string'); - - var expectedSiteID = normalSitePair.configured.params.siteID; - assert.equal(normalSitePair.sent.ext.siteID, expectedSiteID, 'request ' + normalSitePair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(normalSitePair.sent.ext.siteID, 'site ID is integer'); - - // check unsent bids - if (param.missingtier3SiteID) { - assert.equal(sidMatched.unmatched.configured.length, 0, 'one configured bid is missing in impression Obj'); - } else { - assert.equal(sidMatched.unmatched.configured.length, 1, 'one configured bid is missing in impression Obj'); - } - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - - assert.deepEqual(Object.keys(adapterResponse), [], 'no explicit pass on bid'); - } - }); - }; - - for (var i = 0; i < test_indexAdapter_tier3siteid.length; i++) { - var test = test_indexAdapter_tier3siteid[i]; - base_prebid_indexAdapter_tier3siteid(test.testname, test.param, test.expected); - } - - it('test_prebid_indexAdapter_siteID_multiple: multiple slots have same siteIDs -> all slots in ad server request with the same site IDs', function() { - var first_slot = { - slotName: 'slot1', - siteID: 111111, - }; - var second_slot = { - slotName: 'slot2', - siteID: 111111, // same as first slot - }; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, first_slot['slotName'], [ IndexUtils.supportedSizes[0] ], { siteID: first_slot['siteID'] }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, second_slot['slotName'], [ IndexUtils.supportedSizes[1] ], { siteID: second_slot['siteID'] }), - ]; - - adapter.callBids({ bids: configuredBids }); - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - var expectedSiteID = pair.configured.params.siteID; - var actualSiteID = pair.sent.ext.siteID; - assert.equal(actualSiteID, expectedSiteID, 'request ' + pair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(actualSiteID, 'site ID is number'); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - }); - - it('test_prebid_indexAdapter_siteID_different: multiple slots have different siteIDs -> all slots in ad server request with the different site IDs', function() { - var first_slot = { - slotName: 'slot1', - siteID: 111111, - }; - var second_slot = { - slotName: 'slot2', - siteID: 222222, - }; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, first_slot['slotName'], [ IndexUtils.supportedSizes[0] ], { siteID: first_slot['siteID'] }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, second_slot['slotName'], [ IndexUtils.supportedSizes[1] ], { siteID: second_slot['siteID'] }), - ]; - - adapter.callBids({ bids: configuredBids }); - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - var expectedSiteID = pair.configured.params.siteID; - var actualSiteID = pair.sent.ext.siteID; - assert.equal(actualSiteID, expectedSiteID, 'request ' + pair.name + ' site ID is set to ' + expectedSiteID); - assert.isNumber(actualSiteID, 'site ID is number'); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - }); - - it('test_prebid_indexAdapter_size_singleArr: single sized array -> width and height in integer in request', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', IndexUtils.supportedSizes[0]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSID(expandedBids, impressionObj); - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.configured.length, 0, 'All configured bids are in impression Obj'); - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - }); - - it('test_prebid_indexAdapter_size_singleDim: missing width/height -> size is ignored, no ad server request for bad size', function () { - var oneDimSize = [728]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], oneDimSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, oneDimSize, 'configured bid not in impression obj size width is' + JSON.stringify(oneDimSize)); - }); - - it('test_prebid_indexAdapter_size_missing: missing size -> slot is ignored, no ad server request', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', []) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to AS'); - }); - - it('test_prebid_indexAdapter_size_negativeWidth: negative width -> size is ignored, no ad server request for bad size', function () { - var invalidSize = [-728, 90]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], invalidSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, invalidSize, 'configured bid not in impression obj size width is' + JSON.stringify(invalidSize)); - }); - - it('test_prebid_indexAdapter_size_negativeHeight: negative height -> size is ignored, no ad server request for bad size', function () { - var invalidSize = [728, -90]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], invalidSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)) - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, invalidSize, 'configured bid not in impression obj size width is' + JSON.stringify(invalidSize)); - }); - - it('test_prebid_indexAdapter_size_quoted: height and width quoted -> invalid size, no ad server request for invalid size', function () { - var otherSize = ['300', '250']; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], otherSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 0, '0 configured bid is not in impression Obj'); - }); - - it('test_prebid_indexAdapter_size_float: height and width float -> invalid size, no ad server request for invalid size ', function () { - var otherSize = [300.1, 250]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], otherSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, otherSize, 'configured bid not in impression obj size width is' + JSON.stringify(otherSize)); - }); - - it('test_prebid_indexAdapter_size_string_1_pba23: height and width string -> invalid size, no ad server request for invalid size ', function () { - var otherSize = [String(IndexUtils.supportedSizes[0][0]), String(IndexUtils.supportedSizes[0][1])]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[1], otherSize, IndexUtils.supportedSizes[2] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 0, 'all configured bids are in impression Obj'); - }); - - it('test_prebid_indexAdapter_size_string_2: whole size is string -> invalid size, no ad server request for invalid size ', function () { - var otherSize = 'gallery'; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], otherSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, otherSize, 'configured bid not in impression obj size width is' + JSON.stringify(otherSize)); - }); - - it('test_prebid_indexAdapter_size_string_3: entire size structure is string -> no ad server request since size is invalid', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', 'gallery') - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to AS'); - }); - - it('test_prebid_indexAdapter_size_hash_1: height or width hash -> invalid size, no ad server request for invalid size ', function () { - var otherSize = [{728: 1}, 90]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], otherSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, otherSize, 'configured bid not in impression obj size width is' + JSON.stringify(otherSize)); - }); - - it('test_prebid_indexAdapter_size_hash_2: whole size hash -> invalid size, no ad server request for invalid size ', function () { - var otherSize = {728: 1, 90: 1}; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], otherSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, otherSize, 'configured bid not in impression obj size width is' + JSON.stringify(otherSize)); - }); - - it('test_prebid_indexAdapter_size_hash_3: entire size structure is hash -> no ad server request since size is invalid', function () { - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', {728: 90}) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isFalse(adLoader.loadScript.called, 'no request made to AS'); - }); - - it('test_prebid_indexAdapter_size_swap: swap size and width for valid so now its invalid -> unsupportedsize, no ad server request for unsupported size ', function () { - var otherSize = [90, 728]; - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ IndexUtils.supportedSizes[0], otherSize, IndexUtils.supportedSizes[1] ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, otherSize, 'configured bid not in impression obj size width is' + JSON.stringify(otherSize)); - }); - - it('test_prebid_indexAdapter_size_sameWidth: same width for all sizes in a slot -> ad server request only for supported sizes', function () { - var valid1Size = [300, 250]; - var otherSize = [300, 999]; - var valid2Size = [300, 600]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ valid1Size, otherSize, valid2Size ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, otherSize, 'configured bid not in impression obj size width is' + JSON.stringify(otherSize)); - }); - - it('test_prebid_indexAdapter_size_sameHeight: same height for all sizes in a slot -> ad server request only for supported sizes', function () { - var valid1Size = [120, 600]; - var otherSize = [999, 600]; - var valid2Size = [300, 600]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, 'slot_1', [ valid1Size, otherSize, valid2Size ]) - ]; - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - - var expandedBids = configuredBids.map(bid => IndexUtils.expandSizes(bid)); - var sidMatched = IndexUtils.matchBidsOnSize(expandedBids, impressionObj); - - for (var i = 0; i < sidMatched.matched.length; i++) { - var pair = sidMatched.matched[i]; - - assert.equal(pair.sent.banner.w, pair.configured.size[0], 'request ' + pair.name + ' width is set to ' + pair.configured.size[0]); - assert.equal(pair.sent.banner.h, pair.configured.size[1], 'request ' + pair.name + ' width is set to ' + pair.configured.size[1]); - assert.equal(pair.sent.ext.siteID, pair.configured.params.siteID, 'request ' + pair.name + ' siteID is set to ' + pair.configured.params.siteID); - } - - assert.equal(sidMatched.unmatched.sent.length, 0, 'All bids in impression object are from configured bids'); - assert.equal(sidMatched.unmatched.configured.length, 1, '1 configured bid is not in impression Obj'); - assert.equal(sidMatched.unmatched.configured[0].size, otherSize, 'configured bid not in impression obj size width is' + JSON.stringify(otherSize)); - }); - - it('test_prebid_indexAdapter_request_sizeID_validation_1: multiple prebid size slot, index slots with size for all prebid slots, 1 slot is not configured properly -> all size in AS request, except misconfigured slot', function () { - var slotID_1 = 52; - var slotID_2 = 53; - var slotSizes_1 = IndexUtils.supportedSizes[0]; - var slotSizes_2 = IndexUtils.supportedSizes[1]; - - var configuredBids = [ - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID_1, [ slotSizes_1, slotSizes_2 ], { slotSize: [ 728, 'invalid' ] }), - IndexUtils.createBidSlot(IndexUtils.DefaultPlacementCodePrefix, slotID_2, [ slotSizes_1, slotSizes_2 ], { slotSize: slotSizes_2 }) - ]; - - adapter.callBids({ bids: configuredBids }); - - assert.isTrue(adLoader.loadScript.called, 'loadScript get request'); - - assert.include(adLoader.loadScript.firstCall.args[0], HeaderTagRequest, 'request is headertag request'); - - var requestJSON = IndexUtils.parseIndexRequest(adLoader.loadScript.firstCall.args[0]); - assert.isNotNull(requestJSON.r.imp, 'headertag request include impression object'); - - var impressionObj = requestJSON.r.imp; - assert.equal(impressionObj.length, 1, '1 slot is made in the request'); - - assert.equal(impressionObj[0].banner.w, slotSizes_2[0], 'the width made in the request matches with request: ' + slotSizes_2[0]); - assert.equal(impressionObj[0].banner.h, slotSizes_2[1], 'the height made in the request matches with request: ' + slotSizes_2[1]); - assert.equal(impressionObj[0].ext.sid, slotID_2, 'slotID in the request matches with configuration: ' + slotID_2); - assert.equal(impressionObj[0].ext.siteID, IndexUtils.DefaultSiteID, 'siteID in the request matches with request: ' + IndexUtils.DefaultSiteID); - }); -}); diff --git a/test/spec/modules/indexExchangeBidAdapter_video_spec.js b/test/spec/modules/indexExchangeBidAdapter_video_spec.js deleted file mode 100644 index 45231084dcc..00000000000 --- a/test/spec/modules/indexExchangeBidAdapter_video_spec.js +++ /dev/null @@ -1,953 +0,0 @@ -import { expect } from 'chai'; -import Adapter from 'modules/indexExchangeBidAdapter'; -import bidmanager from 'src/bidmanager'; -import adloader from 'src/adloader'; -import * as url from 'src/url'; - -const PREBID_REQUEST = { 'bidderCode': 'indexExchange', 'requestId': '6f4cb846-1901-4fc4-a1a4-5daf58a26e71', 'bidderRequestId': '16940e979c42d4', 'bids': [{ 'bidder': 'indexExchange', 'params': { 'video': { 'siteID': 6, 'playerType': 'HTML5', 'protocols': ['VAST2', 'VAST3'], 'maxduration': 15 } }, 'placementCode': 'video1', 'mediaType': 'video', 'sizes': [640, 480], 'bidId': '2f4e1cc0f992f2', 'bidderRequestId': '16940e979c42d4', 'requestId': '6f4cb846-1901-4fc4-a1a4-5daf58a26e71' }], 'start': 1488236870659, 'auctionStart': 1488236870656, 'timeout': 3000 }; - -const CYGNUS_REQUEST_R_PARAM = { 'id': '16940e979c42d4', 'imp': [{ 'id': '2f4e1cc0f992f2', 'ext': { 'siteID': 6, 'sid': 'pr_1_1_s' }, 'video': { 'protocols': [2, 5, 3, 6], 'maxduration': 15, 'minduration': 0, 'startdelay': 0, 'linearity': 1, 'mimes': ['video/mp4', 'video/webm'], 'w': 640, 'h': 480 } }], 'site': { 'page': 'http://localhost:9876/' }}; - -const PREBID_RESPONSE = { 'bidderCode': 'indexExchange', 'width': 640, 'height': 480, 'statusMessage': 'Bid available', 'adId': '2f4e1cc0f992f2', 'code': 'indexExchange', 'cpm': 10, 'vastUrl': 'http://vast.url' }; - -const CYGNUS_RESPONSE = { 'seatbid': [{ 'bid': [{ 'crid': '1', 'adomain': ['vastdsp.com'], 'adid': '1', 'impid': '2f4e1cc0f992f2', 'cid': '1', 'id': '1', 'ext': { 'vasturl': 'http://vast.url', 'errorurl': 'http://error.url', 'dspid': 1, 'pricelevel': '_1000', 'advbrandid': 75, 'advbrand': 'Nacho Momma' } }], 'seat': '1' }], 'cur': 'USD', 'id': '16940e979c42d4' }; - -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_SECURE = 'https://as-sec.casalemedia.com/cygnus?v=8&fn=$$PREBID_GLOBAL$$.handleCygnusResponse&s=6&r='; - -const DEFAULT_MIMES_MAP = { - FLASH: ['video/mp4', 'video/x-flv'], - HTML5: ['video/mp4', 'video/webm'] -}; -const DEFAULT_VPAID_MIMES_MAP = { - FLASH: ['application/x-shockwave-flash'], - HTML5: ['application/javascript'] -}; -const SUPPORTED_API_MAP = { - FLASH: [1, 2], - HTML5: [2] -}; - -describe('indexExchange adapter - Video', () => { - let adapter; - - beforeEach(() => adapter = new Adapter()); - - describe('request to prebid', () => { - let prebidRequest; - - beforeEach(() => { - prebidRequest = JSON.parse(JSON.stringify(PREBID_REQUEST)); - sinon.stub(adloader, 'loadScript'); - }); - - afterEach(() => { - adloader.loadScript.restore(); - }); - - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - - describe('should make request with specified values', () => { - let insecureExpectedUrl = url.parse(CYGNUS_REQUEST_BASE_URL_INSECURE.concat(encodeURIComponent(JSON.stringify(CYGNUS_REQUEST_R_PARAM)))); - - let secureExpectedUrl = url.parse(CYGNUS_REQUEST_BASE_URL_SECURE.concat(encodeURIComponent(JSON.stringify(CYGNUS_REQUEST_R_PARAM)))); - - it('when valid HTML5 required bid request parameters are present', () => { - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.protocol).to.equal(insecureExpectedUrl.protocol); - expect(cygnusRequestUrl.hostname).to.equal(insecureExpectedUrl.hostname); - expect(cygnusRequestUrl.port).to.equal(insecureExpectedUrl.port); - expect(cygnusRequestUrl.pathname).to.equal(insecureExpectedUrl.pathname); - - expect(cygnusRequestUrl.search.v).to.equal(insecureExpectedUrl.search.v); - expect(cygnusRequestUrl.search.s).to.equal(insecureExpectedUrl.search.s); - expect(cygnusRequestUrl.search.fn).to.equal(insecureExpectedUrl.search.fn); - expect(cygnusRequestUrl.search.r).to.exist; - - expect(cygnusRequestUrl.search.r.id).to.equal(prebidRequest.bidderRequestId); - - expect(cygnusRequestUrl.search.r.site.page).to.have.string(CYGNUS_REQUEST_R_PARAM.site.page); - - expect(cygnusRequestUrl.search.r.imp).to.be.a('array'); - expect(cygnusRequestUrl.search.r.imp[0]).to.have.all.keys(Object.keys(CYGNUS_REQUEST_R_PARAM.imp[0])); - - expect(cygnusRequestUrl.search.r.imp[0].id).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].id); - - expect(cygnusRequestUrl.search.r.imp[0].ext.siteID).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].ext.siteID); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - - expect(cygnusRequestUrl.search.r.imp[0].video.protocols).to.deep.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.protocols); - expect(cygnusRequestUrl.search.r.imp[0].video.maxduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.maxduration); - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.minduration); - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].video.linearity).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.linearity); - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.deep.equal(DEFAULT_MIMES_MAP.HTML5); - expect(cygnusRequestUrl.search.r.imp[0].video.w).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.w); - expect(cygnusRequestUrl.search.r.imp[0].video.h).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.h); - }); - - it('when valid FLASH required bid request parameters are present', () => { - prebidRequest.bids[0].params.video.playerType = 'FLASH'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.protocol).to.equal(insecureExpectedUrl.protocol); - expect(cygnusRequestUrl.hostname).to.equal(insecureExpectedUrl.hostname); - expect(cygnusRequestUrl.port).to.equal(insecureExpectedUrl.port); - expect(cygnusRequestUrl.pathname).to.equal(insecureExpectedUrl.pathname); - - expect(cygnusRequestUrl.search.v).to.equal(insecureExpectedUrl.search.v); - expect(cygnusRequestUrl.search.s).to.equal(insecureExpectedUrl.search.s); - expect(cygnusRequestUrl.search.fn).to.equal(insecureExpectedUrl.search.fn); - expect(cygnusRequestUrl.search.r).to.exist; - - expect(cygnusRequestUrl.search.r.id).to.equal(prebidRequest.bidderRequestId); - - expect(cygnusRequestUrl.search.r.site.page).to.have.string(CYGNUS_REQUEST_R_PARAM.site.page); - - expect(cygnusRequestUrl.search.r.imp).to.be.a('array'); - expect(cygnusRequestUrl.search.r.imp[0]).to.have.all.keys(Object.keys(CYGNUS_REQUEST_R_PARAM.imp[0])); - - expect(cygnusRequestUrl.search.r.imp[0].id).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].id); - - expect(cygnusRequestUrl.search.r.imp[0].ext.siteID).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].ext.siteID); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - - expect(cygnusRequestUrl.search.r.imp[0].video.protocols).to.deep.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.protocols); - expect(cygnusRequestUrl.search.r.imp[0].video.maxduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.maxduration); - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.minduration); - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].video.linearity).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.linearity); - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.deep.equal(DEFAULT_MIMES_MAP.FLASH); - expect(cygnusRequestUrl.search.r.imp[0].video.w).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.w); - expect(cygnusRequestUrl.search.r.imp[0].video.h).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.h); - }); - - it('when required field site ID is a numeric string', () => { - prebidRequest.bids[0].params.video.siteID = '6'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.s).to.equal(insecureExpectedUrl.search.s); - expect(cygnusRequestUrl.search.r).to.exist; - - expect(cygnusRequestUrl.search.r.imp[0].ext.siteID).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].ext.siteID); - }); - - it('when required field maxduration is a numeric string', () => { - prebidRequest.bids[0].params.video.maxduration = '15'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.maxduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.maxduration); - }); - - describe('when optional field minduration', () => { - it('is valid number', () => { - prebidRequest.bids[0].params.video.minduration = 5; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(prebidRequest.bids[0].params.video.minduration); - }); - - it('is valid number string', () => { - prebidRequest.bids[0].params.video.minduration = '5'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(prebidRequest.bids[0].params.video.minduration); - }); - }); - - describe('when optional field startdelay', () => { - it('is valid string', () => { - prebidRequest.bids[0].params.video.startdelay = 'midroll'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(prebidRequest.bids[0].params.video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string('m_1_1_s'); - }); - - it('is valid number string', () => { - prebidRequest.bids[0].params.video.startdelay = '5'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(prebidRequest.bids[0].params.video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string('m_1_1_s'); - }); - - it('is valid midroll number', () => { - prebidRequest.bids[0].params.video.startdelay = 5; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(prebidRequest.bids[0].params.video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string('m_1_1_s'); - }); - - it('is valid preroll number', () => { - prebidRequest.bids[0].params.video.startdelay = 0; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(prebidRequest.bids[0].params.video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string('pr_1_1_s'); - }); - }); - - describe('when optional field linearity', () => { - it('is valid string', () => { - prebidRequest.bids[0].params.video.linearity = 'nonlinear'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.linearity).to.equal(2); - }); - }); - - describe('when optional field mimes', () => { - it('is valid mime', () => { - prebidRequest.bids[0].params.video.mimes = ['a/b']; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.deep.equal(prebidRequest.bids[0].params.video.mimes); - }); - }); - - describe('when optional field API list', () => { - it('is valid array', () => { - prebidRequest.bids[0].params.video.apiList = [2]; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.include.members([2]); - }); - }); - - describe('when optional field allowVPAID', () => { - it('is valid boolean', () => { - prebidRequest.bids[0].params.video.allowVPAID = true; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.include.members(DEFAULT_VPAID_MIMES_MAP.HTML5); - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.include.members(SUPPORTED_API_MAP.HTML5); - }); - }); - }); - - describe('should make request with default values', () => { - describe('when optional field minduration', () => { - it('is invalid string', () => { - prebidRequest.bids[0].params.video.minduration = 'a'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.minduration); - }); - - it('is empty object', () => { - prebidRequest.bids[0].params.video.minduration = {}; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.minduration); - }); - - it('is empty array', () => { - prebidRequest.bids[0].params.video.minduration = []; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.minduration); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.minduration = undefined; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.minduration).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.minduration); - }); - }); - - describe('when optional field startdelay', () => { - it('is invalid string', () => { - prebidRequest.bids[0].params.video.startdelay = 'cucumber'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - }); - - it('is invalid number string', () => { - prebidRequest.bids[0].params.video.startdelay = '-5'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - }); - - it('is invalid number', () => { - prebidRequest.bids[0].params.video.startdelay = -5; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - }); - - it('is empty object', () => { - prebidRequest.bids[0].params.video.startdelay = {}; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - }); - - it('is empty array', () => { - prebidRequest.bids[0].params.video.startdelay = []; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.startdelay = undefined; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.startdelay).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.startdelay); - expect(cygnusRequestUrl.search.r.imp[0].ext.sid).to.have.string(CYGNUS_REQUEST_R_PARAM.imp[0].ext.sid); - }); - }); - - describe('when optional field linearity', () => { - it('is invalid string', () => { - prebidRequest.bids[0].params.video.linearity = 'cucumber'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.linearity).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.linearity); - }); - - it('is empty object', () => { - prebidRequest.bids[0].params.video.linearity = {}; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.linearity).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.linearity); - }); - - it('is empty array', () => { - prebidRequest.bids[0].params.video.linearity = []; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.linearity).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.linearity); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.linearity = undefined; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.linearity).to.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.linearity); - }); - }); - - describe('when optional field mimes', () => { - it('is invalid mime string', () => { - prebidRequest.bids[0].params.video.mimes = 'a'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.deep.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - }); - - it('is empty object', () => { - prebidRequest.bids[0].params.video.mimes = {}; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.deep.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - }); - - it('is empty array', () => { - prebidRequest.bids[0].params.video.mimes = []; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.deep.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.mimes = undefined; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.deep.equal(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - }); - }); - - describe('when optional field API list', () => { - it('is invalid array', () => { - prebidRequest.bids[0].params.video.apiList = ['cucumber']; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - - it('is empty array', () => { - prebidRequest.bids[0].params.video.apiList = []; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - - it('is empty object', () => { - prebidRequest.bids[0].params.video.apiList = {}; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - - it('is string', () => { - prebidRequest.bids[0].params.video.apiList = 'cucumber'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.apiList = undefined; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - }); - - describe('when optional field allowVPAID', () => { - it('is not boolean', () => { - prebidRequest.bids[0].params.video.allowVPAID = 'a'; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.have.members(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - - it('is empty object', () => { - prebidRequest.bids[0].params.video.allowVPAID = {}; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.have.members(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - - it('is empty array', () => { - prebidRequest.bids[0].params.video.allowVPAID = []; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.have.members(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.allowVPAID = undefined; - adapter.callBids(prebidRequest); - sinon.assert.calledOnce(adloader.loadScript); - let cygnusRequestUrl = url.parse(encodeURIComponent(adloader.loadScript.firstCall.args[0])); - cygnusRequestUrl.search.r = JSON.parse(decodeURIComponent(cygnusRequestUrl.search.r)); - - expect(cygnusRequestUrl.search.r.imp[0].video.mimes).to.have.members(CYGNUS_REQUEST_R_PARAM.imp[0].video.mimes); - expect(cygnusRequestUrl.search.r.imp[0].video.apiList).to.not.exist; - }); - }); - }) - - describe('should not make request', () => { - describe('when request', () => { - it('is empty', () => { - adapter.callBids({}); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is for no bids', () => { - adapter.callBids({ bids: [] }); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is undefined', () => { - adapter.callBids(undefined); - sinon.assert.notCalled(adloader.loadScript); - }); - }); - - describe('when request site ID', () => { - it('is negative number', () => { - prebidRequest.bids[0].params.video.siteID = -5; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is negative number string', () => { - prebidRequest.bids[0].params.video.siteID = '-5'; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is invalid string', () => { - prebidRequest.bids[0].params.video.siteID = 'cucumber'; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.siteID = undefined; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - }); - - describe('when request player type', () => { - it('is invalid string', () => { - prebidRequest.bids[0].params.video.playerType = 'cucumber'; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is number', () => { - prebidRequest.bids[0].params.video.playerType = 1; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.playerType = undefined; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - }); - - describe('when request protocols', () => { - it('is empty array', () => { - prebidRequest.bids[0].params.video.protocols = []; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is a string', () => { - prebidRequest.bids[0].params.video.protocols = 'cucumber'; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is an invalid array', () => { - prebidRequest.bids[0].params.video.protocols = ['cucumber']; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.protocols = undefined; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - }); - - describe('when request maxduration', () => { - it('is a non-numeric string', () => { - prebidRequest.bids[0].params.video.maxduration = 'cucumber'; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is a negative number', () => { - prebidRequest.bids[0].params.video.maxduration = -1; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is a negative number string', () => { - prebidRequest.bids[0].params.video.maxduration = '-1'; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - - it('is undefined', () => { - prebidRequest.bids[0].params.video.maxduration = undefined; - adapter.callBids(prebidRequest); - sinon.assert.notCalled(adloader.loadScript); - }); - }); - }); - }); - - describe('response from cygnus', () => { - let response; - let request; - let width; - let height; - - beforeEach(() => { - sinon.stub(bidmanager, 'addBidResponse'); - - [width, height] = PREBID_REQUEST.bids[0].sizes; - - request = JSON.parse(JSON.stringify(PREBID_REQUEST)); - response = JSON.parse(JSON.stringify(CYGNUS_RESPONSE)); - }); - - afterEach(() => { - bidmanager.addBidResponse.restore(); - }); - - describe('should add empty bid', () => { - describe('when response', () => { - beforeEach(() => { - adapter.callBids(request); - }); - - it('is empty object', () => { - $$PREBID_GLOBAL$$.handleCygnusResponse({}); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is empty array', () => { - $$PREBID_GLOBAL$$.handleCygnusResponse({}); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is undefined', () => { - $$PREBID_GLOBAL$$.handleCygnusResponse(undefined); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is number', () => { - $$PREBID_GLOBAL$$.handleCygnusResponse(1); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is string', () => { - $$PREBID_GLOBAL$$.handleCygnusResponse('cucumber'); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is explicit pass', () => { - $$PREBID_GLOBAL$$.handleCygnusResponse({ id: CYGNUS_RESPONSE.id }); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - }); - - describe('when impid', () => { - beforeEach(() => { - adapter.callBids(request); - }); - - it('is mismatched', () => { - response.seatbid[0].bid[0].impid = 'cucumber'; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is undefined', () => { - response.seatbid[0].bid[0].impid = undefined; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is array', () => { - response.seatbid[0].bid[0].impid = []; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is object', () => { - response.seatbid[0].bid[0].impid = {}; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is string', () => { - response.seatbid[0].bid[0].impid = {}; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - }); - - describe('when price level', () => { - beforeEach(() => { - adapter.callBids(request); - }); - - it('is string', () => { - response.seatbid[0].bid[0].ext.pricelevel = 'cucumber'; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is undefined', () => { - response.seatbid[0].bid[0].ext.pricelevel = undefined; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is array', () => { - response.seatbid[0].bid[0].ext.pricelevel = []; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is object', () => { - response.seatbid[0].bid[0].ext.pricelevel = {}; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - }); - - describe('when vasturl', () => { - beforeEach(() => { - adapter.callBids(request); - }); - - it('is undefined', () => { - response.seatbid[0].bid[0].ext.vasturl = undefined; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is number', () => { - response.seatbid[0].bid[0].ext.vasturl = 1; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - - it('is not a url', () => { - response.seatbid[0].bid[0].ext.vasturl = 'cucumber'; - $$PREBID_GLOBAL$$.handleCygnusResponse(response); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const bidResponse = bidmanager.addBidResponse.firstCall.args[1]; - expect(bidResponse).to.have.property('code', PREBID_RESPONSE.code); - expect(bidResponse).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(bidResponse).to.have.property('statusMessage', EMPTY_MESSAGE); - }); - }); - }); - - describe('should add available bid', () => { - describe('when response', () => { - beforeEach(() => { - adapter.callBids(request); - }); - - it('is success', () => { - $$PREBID_GLOBAL$$.handleCygnusResponse(CYGNUS_RESPONSE); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('code', PREBID_RESPONSE.code); - expect(response).to.have.property('bidderCode', PREBID_RESPONSE.bidderCode); - expect(response).to.have.property('statusMessage', PREBID_RESPONSE.statusMessage); - expect(response).to.have.property('cpm', PREBID_RESPONSE.cpm); - expect(response).to.have.property('vastUrl', PREBID_RESPONSE.vastUrl); - expect(response).to.have.property('width', PREBID_RESPONSE.width); - expect(response).to.have.property('height', PREBID_RESPONSE.height); - }); - }); - }); - }); -}); diff --git a/test/spec/modules/inneractiveBidAdapter_spec.js b/test/spec/modules/inneractiveBidAdapter_spec.js deleted file mode 100644 index aef9a6b7b49..00000000000 --- a/test/spec/modules/inneractiveBidAdapter_spec.js +++ /dev/null @@ -1,291 +0,0 @@ -/* globals context */ - -import {expect} from 'chai'; -import {default as InneractiveAdapter} from 'modules/inneractiveBidAdapter'; -import bidmanager from 'src/bidmanager'; - -// Using plain-old-style functions, why? see: http://mochajs.org/#arrow-functions -describe('InneractiveAdapter', function () { - let adapter, - bidRequest; - - beforeEach(function () { - adapter = new InneractiveAdapter(); - bidRequest = { - bidderCode: 'inneractive', - bids: [ - { - bidder: 'inneractive', - params: { - appId: '', - }, - placementCode: 'div-gpt-ad-1460505748561-0', - sizes: [[300, 250], [300, 600]], - bidId: '507e8db167d219', - bidderRequestId: '49acc957f92917', - requestId: '51381cd0-c29c-405b-9145-20f60abb1e76' - }, - { - bidder: 'inneractive', - params: { - noappId: '...', - }, - placementCode: 'div-gpt-ad-1460505661639-0', - sizes: [[728, 90], [970, 90]], - bidId: '507e8db167d220', - bidderRequestId: '49acc957f92917', - requestId: '51381cd0-c29c-405b-9145-20f60abb1e76' - }, - { - bidder: 'inneractive', - params: { - APP_ID: 'Inneractive_AndroidHelloWorld_Android', - spotType: 'rectangle', - customParams: { - Portal: 7002, - } - }, - placementCode: 'div-gpt-ad-1460505748561-0', - sizes: [[320, 50], [300, 600]], - bidId: '507e8db167d221', - bidderRequestId: '49acc957f92917', - requestId: '51381cd0-c29c-405b-9145-20f60abb1e76' - }, - { - bidder: 'inneractive', - params: { - appId: 'Inneractive_IosHelloWorld_iPhone', - spotType: 'banner', // Just for coverage considerations, no real impact in production - customParams: { - portal: 7001, - gender: '' - } - }, - placementCode: 'div-gpt-ad-1460505661639-0', - sizes: [[728, 90], [970, 90]], - bidId: '507e8db167d222', - bidderRequestId: '49acc957f92917', - requestId: '51381cd0-c29c-405b-9145-20f60abb1e76' - }] - }; - }); - - describe('Reporter', function () { - context('on HBPreBidError event', function () { - it('should contain "mbwError" the inside event report url', function () { - const Reporter = InneractiveAdapter._getUtils().Reporter; - const extraDetailsParam = { - 'appId': 'CrunchMind_DailyDisclosure_other', - 'spotType': 'rectangle', - 'portal': 7002 - }; - let eventReportUrl = Reporter.getEventUrl('HBPreBidError', extraDetailsParam); - expect(eventReportUrl).to.include('mbwError'); - }); - }); - }); - - it('should return an instance of this adapter having a "callBids" method', function () { - expect(adapter) - .to.be.instanceOf(InneractiveAdapter).and - .to.have.property('callBids').and - .to.be.a('function'); - }); - - describe('when sending out bid requests to the ad server', function () { - let bidRequests, - xhr; - - beforeEach(function () { - bidRequests = []; - xhr = sinon.useFakeXMLHttpRequest(); - xhr.onCreate = (request) => { - bidRequests.push(request); - }; - }); - - afterEach(function () { - xhr.restore(); - }); - - context('when there are no bid requests', function () { - it('should not issue a request', function () { - const Reporter = InneractiveAdapter._getUtils().Reporter; - Reporter.getEventUrl('HBPreBidError', { - 'appId': 'CrunchMind_DailyDisclosure_other', - 'spotType': 'rectangle', - 'portal': 7002 - }); - - delete bidRequest.bids; - adapter.callBids(bidRequest); - - expect(bidRequests).to.be.empty; - }); - }); - - context('when there is at least one bid request', function () { - it('should filter out invalid bids', function () { - const INVALID_BIDS_COUNT = 2; - sinon.spy(adapter, '_isValidRequest'); - adapter.callBids(bidRequest); - - for (let id = 0; id < INVALID_BIDS_COUNT; id++) { - expect(adapter._isValidRequest.getCall(id).returned(false)).to.be.true; - } - - adapter._isValidRequest.restore(); - }); - - it('should store all valid bids internally', function () { - adapter.callBids(bidRequest); - expect(Object.keys(adapter.bidByBidId).length).to.equal(2); - }); - - it('should issue ad requests to the ad server for every valid bid', function () { - adapter.callBids(bidRequest); - expect(bidRequests).to.have.lengthOf(2); - }); - }); - }); - - describe('when registering the bids that are returned with Prebid.js', function () { - const BID_DETAILS_ARG_INDEX = 1; - let server; - - beforeEach(function () { - sinon.stub(bidmanager, 'addBidResponse'); - server = sinon.fakeServer.create(); - }); - - afterEach(function () { - server.restore(); - bidmanager.addBidResponse.restore(); - }); - - context('when the bid is valid', function () { - let adServerResponse, - headers, - body; - - beforeEach(function () { - adServerResponse = { - headers: { - 'X-IA-Ad-Height': 250, - 'X-IA-Ad-Width': 300, - 'X-IA-Error': 'OK', - 'X-IA-Pricing': 'CPM', - 'X-IA-Pricing-Currency': 'USD', - 'X-IA-Pricing-Value': 0.0005 - }, - body: { - ad: { - html: '' - }, - config: { - tracking: { - impressions: [ - 'http://event.inner-active.mobi/simpleM2M/reportEvent?eventArchetype=impress…pe=3&network=Inneractive_CS&acp=&pcp=&secure=false&rtb=false&houseAd=false' - ], - clicks: [ - 'http://event.inner-active.mobi/simpleM2M/reportEvent?eventArchetype=richMed…pe=3&network=Inneractive_CS&acp=&pcp=&secure=false&rtb=false&houseAd=false', - '' - ], - passback: 'http://event.inner-active.mobi/simpleM2M/reportEvent?eventArchetype=passbac…pe=3&network=Inneractive_CS&acp=&pcp=&secure=false&rtb=false&houseAd=false' - }, - moat: { - countryCode: 'IL' - } - } - } - }; - headers = adServerResponse.headers; - body = JSON.stringify(adServerResponse.body); - }); - - it('should register bid responses with a status code of 1', function () { - server.respondWith([200, headers, body]); - adapter.callBids(bidRequest); - server.respond(); - - let firstRegisteredBidResponse = bidmanager.addBidResponse.firstCall.args[BID_DETAILS_ARG_INDEX]; - expect(firstRegisteredBidResponse) - .to.have.property('statusMessage', 'Bid available'); - }); - - it('should use the first element inside the bid request size array when no (width,height) is returned within the headers', function () { - delete headers['X-IA-Ad-Height']; - delete headers['X-IA-Ad-Width']; - server.respondWith([200, headers, body]); - adapter.callBids(bidRequest); - server.respond(); - - let firstRegisteredBidResponse = bidmanager.addBidResponse.firstCall.args[BID_DETAILS_ARG_INDEX]; - expect(firstRegisteredBidResponse).to.have.property('width', 320); - expect(firstRegisteredBidResponse).to.have.property('height', 50); - }); - }); - - context('when the bid is invalid', function () { - let passbackAdServerResponse, - headers, - body; - - beforeEach(function () { - passbackAdServerResponse = { - headers: { - 'X-IA-Error': 'House Ad', - 'X-IA-Content': 600145, - 'X-IA-Cid': 99999, - 'X-IA-Publisher': 206536, - 'Content-Type': 'application/json; charset=UTF-8', - 'X-IA-Session': 6512147119979250840, - 'X-IA-AdNetwork': 'inneractive360' - }, - body: { - 'ad': { - 'html': '' - }, - 'config': { - 'passback': 'http://event.inner-active.mobi/simpleM2M/reportEvent?eventArchetype=passbac…pe=3&network=Inneractive_CS&acp=&pcp=&secure=false&rtb=false&houseAd=false' - } - } - }; - headers = passbackAdServerResponse.headers; - body = JSON.stringify(passbackAdServerResponse.body); - }); - - it('should register bid responses with a status code of 2', function () { - server.respondWith([200, headers, body]); - adapter.callBids(bidRequest); - server.respond(); - - let firstRegisteredBidResponse = bidmanager.addBidResponse.firstCall.args[BID_DETAILS_ARG_INDEX]; - expect(firstRegisteredBidResponse) - .to.have.property('statusMessage', 'Bid returned empty or error response'); - }); - - it('should handle responses from our server in case we had no ad to offer', function () { - const n = bidRequest.bids.length; - bidRequest.bids[n - 1].params.appId = 'Komoona_InquisitrRectangle2_other'; - server.respondWith([200, headers, body]); - adapter.callBids(bidRequest); - server.respond(); - - let secondRegisteredBidResponse = bidmanager.addBidResponse.secondCall.args[BID_DETAILS_ARG_INDEX]; - expect(secondRegisteredBidResponse) - .to.have.property('statusMessage', 'Bid returned empty or error response'); - }); - - it('should handle JSON.parse errors', function () { - server.respondWith(''); - adapter.callBids(bidRequest); - server.respond(); - - const firstRegisteredBidResponse = bidmanager.addBidResponse.firstCall.args[BID_DETAILS_ARG_INDEX]; - expect(firstRegisteredBidResponse) - .to.have.property('statusMessage', 'Bid returned empty or error response'); - }); - }); - }); -}); diff --git a/test/spec/modules/innityBidAdapter_spec.js b/test/spec/modules/innityBidAdapter_spec.js deleted file mode 100644 index 7e4ac147c68..00000000000 --- a/test/spec/modules/innityBidAdapter_spec.js +++ /dev/null @@ -1,157 +0,0 @@ -describe('innity adapter tests', function () { - var expect = require('chai').expect; - var urlParse = require('url-parse'); - var querystringify = require('querystringify'); - var adapter = require('modules/innityBidAdapter'); - var adLoader = require('src/adloader'); - var bidmanager = require('src/bidmanager'); - - var stubLoadScript; - - beforeEach(function () { - stubLoadScript = sinon.stub(adLoader, 'loadScript'); - }); - - afterEach(function () { - stubLoadScript.restore(); - }); - - describe('creation of bid url', function () { - if (typeof ($$PREBID_GLOBAL$$._bidsReceived) === 'undefined') { - $$PREBID_GLOBAL$$._bidsReceived = []; - } - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = []; - } - - it('bid request for single placement', function () { - var params = { - bids: [{ - placementCode: '/19968336/header-bid-tag-0', - sizes: [[300, 250]], - bidId: 'b12345', - bidder: 'innity', - params: { pub: '267', zone: '62546' } - }] - }; - - adapter().callBids(params); - - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledOnce(stubLoadScript); - - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - expect(parsedBidUrlQueryString).to.have.property('pub').and.to.equal('267'); - expect(parsedBidUrlQueryString).to.have.property('zone').and.to.equal('62546'); - expect(parsedBidUrlQueryString).to.have.property('width').and.to.equal('300'); - expect(parsedBidUrlQueryString).to.have.property('height').and.to.equal('250'); - }); - }); - - describe('handling bid response', function () { - it('should return complete bid response', function() { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - var params = { - bids: [{ - placementCode: '/19968336/header-bid-tag-0', - sizes: [[300, 250]], - bidId: 'b12345', - bidder: 'innity', - params: { pub: '267', zone: '62546' } - }] - }; - - var response = { - cpm: 100, - width: 300, - height: 250, - callback_uid: 'b12345', - tag: ' - `); - expect(bidResponse.cpm).to.equal(1.0); - expect(bidResponse.width).to.equal(160); - expect(bidResponse.height).to.equal(600); - }); - }); - }); -}); diff --git a/test/spec/modules/mantisBidAdapter_spec.js b/test/spec/modules/mantisBidAdapter_spec.js deleted file mode 100644 index ac072aacccf..00000000000 --- a/test/spec/modules/mantisBidAdapter_spec.js +++ /dev/null @@ -1,168 +0,0 @@ -'use strict'; - -describe('mantis adapter tests', function () { - const expect = require('chai').expect; - const Adapter = require('modules/mantisBidAdapter'); - const bidmanager = require('src/bidmanager'); - const adloader = require('src/adloader'); - const constants = require('src/constants.json'); - - var mantis, sandbox; - - beforeEach(() => { - mantis = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - - delete window.context; - delete window.mantis_link; - delete window.mantis_breakpoint; - delete window.mantis_uuid; - }); - - var callBidExample = { - bidderCode: 'mantis', - bids: [ - { - bidId: 'bidId1', - bidder: 'mantis', - placementCode: 'foo', - sizes: [[728, 90]], - params: { - property: '1234', - zoneId: 'zone1' - } - }, - { - bidId: 'bidId2', - bidder: 'mantis', - placementCode: 'bar', - sizes: [[300, 600], [300, 250]], - params: { - property: '1234', - zoneId: 'zone2' - } - } - ] - }; - - describe('callBids', () => { - it('should create appropriate bid responses', () => { - sandbox.stub(bidmanager, 'addBidResponse'); - sandbox.stub(adloader, 'loadScript', function (url) { - var jsonp = eval(decodeURIComponent(url.match(/jsonp=(.*)&property/)[1])); - - jsonp({ - ads: { - bidId1: { - cpm: 1, - html: '', - width: 300, - height: 600 - } - } - }); - }); - - mantis.callBids(callBidExample); - - sinon.assert.calledTwice(bidmanager.addBidResponse); - - expect(bidmanager.addBidResponse.firstCall.args[0]).to.eql('foo'); - - var bid1 = bidmanager.addBidResponse.firstCall.args[1]; - expect(bid1.getStatusCode()).to.eql(constants.STATUS.GOOD); - expect(bid1.bidderCode).to.eql('mantis'); - expect(bid1.cpm).to.eql(1); - expect(bid1.ad).to.eql(''); - expect(bid1.width).to.eql(300); - expect(bid1.height).to.eql(600); - - expect(bidmanager.addBidResponse.secondCall.args[0]).to.eql('bar'); - - var bid2 = bidmanager.addBidResponse.secondCall.args[1]; - expect(bid2.getStatusCode()).to.eql(constants.STATUS.NO_BID); - expect(bid2.bidderCode).to.eql('mantis'); - }); - - it('should load script with relevant bid data', () => { - sandbox.stub(adloader, 'loadScript'); - - mantis.callBids(callBidExample); - - sinon.assert.calledOnce(adloader.loadScript); - - var serverCall = adloader.loadScript.firstCall.args[0]; - - expect(serverCall).to.match(/buster=[0-9]+&/); - expect(serverCall).to.match(/tz=-?[0-9]+&/); - expect(serverCall).to.match(/secure=(true|false)&/); - expect(serverCall).to.string('property=1234&'); - expect(serverCall).to.string('bids[0][bidId]=bidId1&'); - expect(serverCall).to.string('bids[0][sizes][0][width]=728&'); - expect(serverCall).to.string('bids[0][sizes][0][height]=90&'); - expect(serverCall).to.string('bids[0][config][zoneId]=zone1&'); - expect(serverCall).to.string('bids[1][bidId]=bidId2&'); - expect(serverCall).to.string('bids[1][sizes][0][width]=300&'); - expect(serverCall).to.string('bids[1][sizes][0][height]=600&'); - expect(serverCall).to.string('bids[1][sizes][1][width]=300&'); - expect(serverCall).to.string('bids[1][sizes][1][height]=250&'); - expect(serverCall).to.string('bids[1][config][zoneId]=zone2&'); - expect(serverCall).to.string('version=1'); - }); - - /* tests below are to just adhere to code coverage requirements, but it is already tested in our own libraries/deployment process */ - it('should send uuid from window if set', () => { - sandbox.stub(adloader, 'loadScript'); - - window.mantis_uuid = '4321'; - - mantis.callBids(callBidExample); - - sinon.assert.calledOnce(adloader.loadScript); - - var serverCall = adloader.loadScript.firstCall.args[0]; - - expect(serverCall).to.string('uuid=4321&'); - }); - - it('should send mobile = true if breakpoint is hit', () => { - sandbox.stub(adloader, 'loadScript'); - - window.mantis_link = true; // causes iframe detection to not work - window.mantis_breakpoint = 100000000; // force everything to be mobile - - mantis.callBids(callBidExample); - - sinon.assert.calledOnce(adloader.loadScript); - - var serverCall = adloader.loadScript.firstCall.args[0]; - - expect(serverCall).to.string('mobile=true&'); - }); - - it('should send different params if amp is detected', () => { - sandbox.stub(adloader, 'loadScript'); - - window.context = { - tagName: 'AMP-AD', - location: { - href: 'bar', - referrer: 'baz' - } - }; - - mantis.callBids(callBidExample); - - sinon.assert.calledOnce(adloader.loadScript); - - var serverCall = adloader.loadScript.firstCall.args[0]; - - expect(serverCall).to.string('mobile=true&'); - // expect(serverCall).to.string('url=bar&'); - }); - }); -}); diff --git a/test/spec/modules/marsmediaBidAdapter_spec.js b/test/spec/modules/marsmediaBidAdapter_spec.js deleted file mode 100644 index c9381eb3c5f..00000000000 --- a/test/spec/modules/marsmediaBidAdapter_spec.js +++ /dev/null @@ -1,185 +0,0 @@ -import { expect } from 'chai'; -import * as ajax from 'src/ajax'; -import bidManager from 'src/bidmanager'; -import MarsmediaBidAdapter from '../../../modules/marsmediaBidAdapter'; -import CONSTANTS from 'src/constants.json'; -import adLoader from 'src/adloader'; - -describe('MarsMedia adapter implementation', () => { - let sandbox, - server, - marsmediaAdapter = new MarsmediaBidAdapter(), - BIDDER_REQUEST, - EMPTY_RESPONSE, - VALID_RESPONSE; - - beforeEach(() => { - BIDDER_REQUEST = { - bidderCode: 'marsmedia', - placementCode: 'div-1', - bids: [ - { - bidder: 'marsmedia', - params: { - publisherID: '1111', - floor: 0 - }, - sizes: [[320, 50]] - } - ] - }; - - EMPTY_RESPONSE = { - 'seatbid': [ - { - 'bid': [ - {} - ] - } - ], - 'bidid': '5616322932456153', - 'cur': 'USD' - }; - - VALID_RESPONSE = { - 'seatbid': [ - { - 'bid': [ - { - 'id': '1', - 'impid': '0c5b2f42-057b-0429-0694-0b42029af9e8', - 'price': 5, - 'adid': '11890', - 'nurl': 'http://ping-hq-2.rtbanalytics.com/bidder/ping_rtb.php?bid=3mhdom&wn=1&a_id=e7a96e1a-9777-5c48-41bc-91151c5b0b8e&gid=&r_id=9625963823905202&a_bp=5.0&a_p=${AUCTION_PRICE}&dcid=1&d=real1.rtbsrv.com&s_id=26&b_r_id=11890&v_id=0&a_pos=&u=5956487987&enp=uQ5qwrn5TQ&oapi=IzJ6W%3D%3DwN4kzN4QjN1kTN23bqB&oai=R2hHylhjYwIWNjFTNxETOtMmYxQTL4QzY10yN3cTOtEWMlZTOhdTZeXpeu&aname=asV6EXbmbP&abundle=ZywyWBnMaH&sdomain=0vQGB%3D%3DQbvNmL2J3ciRncuEDbhVmcKD4pf&spid=iPR8W%3D%3DwN4kzN4QjN1kTNKsMet&s_s_id=5956487987&dcarrier=HMjOzDJYic&city=G9diP6gJT7&uctm=1495112599131&b_id=306&cui=jYGqt%3D0SL8hqk6&hostn=bw7NZyEDbhVmc5j4VD&dspr=X2WmAw4CMCM32y', - 'adm': '', - 'adomain': ['wooga.com'], - 'iurl': 'http://feed-848915510.us-east-1.elb.amazonaws.com/banners/2290/jelly_splash/2861815_jelly-splash-iphone-app_android-app-install_creatives-jelly_320x50.jpg', - 'cid': '11890', - 'crid': '11890', - 'attr': [16] - } - ], - 'seat': '306' - } - ], - 'bidid': '9625963823905202', - 'cur': 'USD' - }; - - sandbox = sinon.sandbox.create(); - server = sinon.fakeServer.create(); - marsmediaAdapter = marsmediaAdapter.createNew(); - - sandbox.stub(bidManager, 'addBidResponse'); - }); - - afterEach(() => { - sandbox.restore(); - server.restore(); - }); - - describe('should receive a valid request bid -', () => { - it('no params', () => { - var bidder_request = BIDDER_REQUEST; - delete bidder_request.bids[0].params; - - expect(marsmediaAdapter.buildCallParams.bind(marsmediaAdapter, bidder_request.bids[0])).to.throw('No params'); - }); - - it('no sizes', () => { - var bidder_request = BIDDER_REQUEST; - delete bidder_request.bids[0].sizes; - - expect(marsmediaAdapter.buildCallParams.bind(marsmediaAdapter, bidder_request.bids[0])).to.throw('No sizes'); - }); - - it('no floor', () => { - var bidder_request = BIDDER_REQUEST; - delete bidder_request.bids[0].params.floor; - - expect(marsmediaAdapter.buildCallParams.bind(marsmediaAdapter, bidder_request.bids[0])).to.throw('No floor'); - }); - - it('floor should be number', () => { - var bidder_request = BIDDER_REQUEST; - bidder_request.bids[0].params.floor = 'str'; - - expect(marsmediaAdapter.buildCallParams.bind(marsmediaAdapter, bidder_request.bids[0])).to.throw('Floor must be numeric value'); - }); - }); - - describe('should receive a valid response -', () => { - it('error building call params', () => { - var request = marsmediaAdapter.buildCallParams(BIDDER_REQUEST.bids[0]); - - expect(request).that.is.an('string'); - - var request_obj = JSON.parse(request); - expect(request_obj).that.is.an('object'); - expect(request_obj).to.have.deep.property('id'); - expect(request_obj).to.have.deep.property('cur'); - - expect(request_obj).to.have.deep.property('imp'); - expect(request_obj['imp'][0]).to.have.deep.property('bidfloor'); - - expect(request_obj).to.have.deep.property('device'); - expect(request_obj).to.have.deep.property('user'); - expect(request_obj).to.have.deep.property('app'); - expect(request_obj).to.have.deep.property('publisher'); - }); - - it('error register bid', () => { - server.respondWith(JSON.stringify(VALID_RESPONSE)); - marsmediaAdapter.callBids(BIDDER_REQUEST); - server.respond(); - - expect(bidManager.addBidResponse.calledOnce).to.equal(true); - expect(bidManager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - }); - }); - - describe('should handle bad response with - ', () => { - it('broken response', () => { - marsmediaAdapter.callBids(BIDDER_REQUEST); - - server.respondWith('{"id":'); - server.respond(); - - expect(bidManager.addBidResponse.calledOnce).to.equal(true); - expect(bidManager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - }); - - it('empty response', () => { - marsmediaAdapter.callBids(BIDDER_REQUEST); - - server.respondWith('{}'); - server.respond(); - - expect(bidManager.addBidResponse.calledOnce).to.equal(true); - expect(bidManager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - }); - - it('empty bids', () => { - marsmediaAdapter.callBids(BIDDER_REQUEST); - - server.respondWith(JSON.stringify(EMPTY_RESPONSE)); - - server.respond(); - let response = JSON.parse(server.response[2]); - - expect(response).to.have.property('seatbid').that.is.an('array').with.lengthOf(1); - expect(response['seatbid'][0]).to.have.property('bid').to.be.lengthOf(1); - }); - - it('no adm', () => { - server.respondWith(JSON.stringify(VALID_RESPONSE)); - - server.respond(); - let response = JSON.parse(server.response[2]); - - expect(response).to.have.property('seatbid').that.is.an('array').with.lengthOf(1); - expect(response['seatbid'][0]).to.have.property('bid').to.be.lengthOf(1); - expect(response['seatbid'][0]['bid'][0]).to.have.property('adm'); - }); - }); -}); diff --git a/test/spec/modules/memeglobalBidAdapter_spec.js b/test/spec/modules/memeglobalBidAdapter_spec.js deleted file mode 100644 index 0dc2d6f1541..00000000000 --- a/test/spec/modules/memeglobalBidAdapter_spec.js +++ /dev/null @@ -1,170 +0,0 @@ -describe('memeglobal adapter tests', function () { - const expect = require('chai').expect; - const adapter = require('modules/memeglobalBidAdapter'); - const bidmanager = require('src/bidmanager'); - const adLoader = require('src/adloader'); - var bidderName = 'memeglobal'; - - let stubLoadScript; - beforeEach(function () { - stubLoadScript = sinon.stub(adLoader, 'loadScript'); - }); - - afterEach(function () { - stubLoadScript.restore(); - }); - - function getBidSetForBidder() { - return $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === bidderName); - } - - function checkBidsRequestedInit() { - var bidSet = getBidSetForBidder(); - if (!bidSet) { - var bidderRequest = { - start: null, - requestId: null, - bidder: 'memeglobal', - bidderCode: 'memeglobal', - bids: [] - }; - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - } - } - - describe('functions and initialization', function () { - it('should exist and be a function', function () { - expect($$PREBID_GLOBAL$$.mgres).to.exist.and.to.be.a('function'); - }); - - it('callBids with params', function () { - var params = { - bidderCode: 'memeglobal', - bidder: 'memeglobal', - bids: [{ - bidId: '3c9408cdbf2f68', - sizes: [[300, 250]], - bidder: 'memeglobal', - params: { siteId: '3608', adSizes: '300x250' }, - requestId: '10b327aa396609', - placementCode: 'header-bid-tag-0' - } - ] - }; - - adapter().callBids(params); - sinon.assert.calledOnce(stubLoadScript); - }); - - it('callBids empty params', function () { - var params = { - bidderCode: 'memeglobal', - bidder: 'memeglobal', - bids: [{ - bidId: '3c9408cdbf2f68', - sizes: [[300, 250]], - bidder: 'memeglobal', - params: { siteId: '3608', adSizes: '300x250' }, - requestId: '10b327aa396609', - placementCode: 'header-bid-tag-0' - } - ] - }; - - adapter().callBids({}); - expect(stubLoadScript.callCount).to.equal(0); - }); - }); - - describe('memeglobalResponse', function () { - it('should not add bid responses if no bids returned', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - checkBidsRequestedInit(); - - var bid = { - bidId: 'bidId1', - bidder: 'memeglobal', - params: { - tagid: '007' - }, - sizes: [[300, 250]], - placementCode: 'test-1' - } - // no bids returned in the response. - var response = { - 'id': '54321', - 'seatbid': [] - }; - var bidSet = getBidSetForBidder(); - bidSet.bids.push(bid); - - // adapter needs to be called for stub registration. - adapter() - - $$PREBID_GLOBAL$$.mgres(response); - - expect(stubAddBidResponse.getCall(0)).to.equal(null); - // var bidPlacementCode = stubAddBidResponse.getCall(0).args[0]; - // expect(bidPlacementCode).to.equal('test-1'); - // - // var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - // expect(bidObject1.getStatusCode()).to.equal(2); - // expect(bidObject1.bidderCode).to.equal('memeglobal'); - - stubAddBidResponse.calledThrice; - stubAddBidResponse.restore(); - }); - - it('should add a bid response for bids returned and empty bid responses for the rest', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - checkBidsRequestedInit(); - - var bid = { - bidId: 'bidId2', - bidder: 'memeglobal', - params: { - tagid: '315045' - }, - sizes: [[320, 50]], - placementCode: 'test-2' - }; - - // Returning a single bid in the response. - var response = { - 'id': '54321111', - 'seatbid': [ { - 'bid': [ { - 'id': '1111111', - 'impid': 'bidId2', - 'price': 0.09, - 'nurl': 'http://url', - 'adm': 'ad-code', - 'h': 250, - 'w': 300, - 'ext': { } - } ] - } ] - }; - - var bidSet = getBidSetForBidder(); - bidSet.bids.push(bid); - adapter() - $$PREBID_GLOBAL$$.mgres(response); - - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - expect(bidPlacementCode1).to.equal('test-2'); - expect(bidObject1.getStatusCode()).to.equal(1); - expect(bidObject1.bidderCode).to.equal('memeglobal'); - 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'); - - stubAddBidResponse.calledThrice; - - stubAddBidResponse.restore(); - }); - }); -}); diff --git a/test/spec/modules/orbitsoftBidAdapter_spec.js b/test/spec/modules/orbitsoftBidAdapter_spec.js deleted file mode 100644 index 4b24787f56b..00000000000 --- a/test/spec/modules/orbitsoftBidAdapter_spec.js +++ /dev/null @@ -1,354 +0,0 @@ -describe('Orbitsoft Adapter tests', function () { - const expect = require('chai').expect; - const assert = require('chai').assert; - const OrbitsoftAdapter = require('modules/orbitsoftBidAdapter'); - const bidmanager = require('src/bidmanager'); - const adloader = require('src/adloader'); - const CONSTANTS = require('src/constants.json'); - - const contentCallEndPoint = 'http://orbitsoft.com/ads/show/content?'; - const jptCallEndPoint = 'http://orbitsoft.com/ads/show/hb?'; - - before(() => sinon.stub(document.body, 'appendChild')); - after(() => document.body.appendChild.restore()); - - describe('test orbitsoft callback response', function () { - it('should exist and be a function', function () { - expect($$PREBID_GLOBAL$$.handleOASCB).to.exist.and.to.be.a('function'); - }); - - it('should add empty bid responses if no bids returned', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - let adapter = new OrbitsoftAdapter(); - - let bidderRequest = { - bidderCode: 'orbitsoft', - bids: [ - { - bidId: 'bidIdOrbitsoft1', - bidder: 'orbitsoft', - params: { - placementId: '16', - requestUrl: jptCallEndPoint - }, - sizes: [[300, 250]], - placementCode: 'test-div-12345' - } - ] - }; - - // Empty bid response - let response = { - callback_uid: 'bidIdOrbitsoft1', - cpm: 0 - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - $$PREBID_GLOBAL$$.handleOASCB(response); - - let bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - let bidResponse1 = stubAddBidResponse.getCall(0).args[1]; - expect(bidPlacementCode1).to.equal('test-div-12345'); - expect(bidResponse1.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(bidResponse1.bidderCode).to.equal('orbitsoft'); - stubAddBidResponse.restore(); - }); - - it('should add empty bid responses if no bidId returned', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - let adapter = new OrbitsoftAdapter(); - - let bidderRequest = { - bidderCode: 'orbitsoft', - bids: [ - { - bidId: 'bidIdOrbitsoft1', - bidder: 'orbitsoft', - params: { - placementId: '16', - requestUrl: jptCallEndPoint - }, - sizes: [[300, 250]], - placementCode: 'test-div-12345' - } - ] - }; - - // Empty bid response - let response = { - cpm: 0 - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - $$PREBID_GLOBAL$$.handleOASCB(response); - - expect(stubAddBidResponse.getCall(0)).to.equal(null); - stubAddBidResponse.restore(); - }); - }); - - it('should add bid responses if bids are returned', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - let adapter = new OrbitsoftAdapter(); - - let bidderRequest = { - bidderCode: 'orbitsoft', - bids: [ - { - bidId: 'bidIdOrbitsoft1', - bidder: 'orbitsoft', - params: { - placementId: '16', - requestUrl: jptCallEndPoint - }, - sizes: [[300, 250]], - placementCode: 'test-div-12345' - } - ] - }; - - // Bid response - let response = { - callback_uid: 'bidIdOrbitsoft1', - content_url: contentCallEndPoint + 'id=1_201707031440_56069e8e70318303e5869fad86722cb0', - cpm: 0.03, - width: 300, - height: 250 - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - $$PREBID_GLOBAL$$.handleOASCB(response); - - let bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - let bidResponse1 = stubAddBidResponse.getCall(0).args[1]; - let bid1width = 300; - let bid1height = 250; - let cpm = 0.03; - let content_url = contentCallEndPoint + 'id=1_201707031440_56069e8e70318303e5869fad86722cb0'; - expect(bidPlacementCode1).to.equal('test-div-12345'); - expect(bidResponse1.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bidResponse1.bidderCode).to.equal('orbitsoft'); - expect(bidResponse1.width).to.equal(bid1width); - expect(bidResponse1.height).to.equal(bid1height); - expect(bidResponse1.cpm).to.equal(cpm); - expect(bidResponse1.adUrl).to.equal(content_url); - stubAddBidResponse.restore(); - }); - - it('should call loadscript with the correct params', function () { - let adapter = new OrbitsoftAdapter(); - let spyLoadScript = sinon.spy(adloader, 'loadScript'); - let params = { - bids: [ - { - sizes: [[300, 250], [300, 600]], - params: { - placementId: '16', - requestUrl: jptCallEndPoint - } - } - ] - }; - adapter.callBids(params); - - sinon.assert.calledOnce(spyLoadScript); - - let bidUrl = spyLoadScript.getCall(0).args[0]; - expect(bidUrl).to.include(jptCallEndPoint); - expect(bidUrl).to.include('scid=16'); - expect(bidUrl).to.include('size=300x250'); - expect(bidUrl).to.include('loc'); - spyLoadScript.restore(); - }); - - describe('test orbitsoft callback with params', function () { - it('should not call loadscript when inputting with empty params', function () { - let adapter = new OrbitsoftAdapter(); - let spyLoadScript = sinon.spy(adloader, 'loadScript'); - adapter.callBids({}); - assert(!spyLoadScript.called); - spyLoadScript.restore(); - }); - - it('should not call loadscript when inputting without requestUrl param ', function () { - let adapter = new OrbitsoftAdapter(); - let spyLoadScript = sinon.spy(adloader, 'loadScript'); - let params = { - bids: [ - { - params: { - placementId: '16' - } - } - ] - }; - adapter.callBids(params); - assert(!spyLoadScript.called); - spyLoadScript.restore(); - }); - - it('should not call loadscript when inputting with empty params by string ', function () { - let adapter = new OrbitsoftAdapter(); - let spyLoadScript = sinon.spy(adloader, 'loadScript'); - adapter.callBids(''); - assert(!spyLoadScript.called); - spyLoadScript.restore(); - }); - - it('should call loadscript without size in params', function () { - let adapter = new OrbitsoftAdapter(); - let spyLoadScript = sinon.spy(adloader, 'loadScript'); - let params = { - bids: [ - { - params: { - placementId: '16', - requestUrl: jptCallEndPoint - } - } - ] - }; - adapter.callBids(params); - - sinon.assert.calledOnce(spyLoadScript); - - let bidUrl = spyLoadScript.getCall(0).args[0]; - expect(bidUrl).to.include(jptCallEndPoint); - expect(bidUrl).to.include('scid=16'); - expect(bidUrl).to.not.include('size='); - expect(bidUrl).to.include('loc'); - spyLoadScript.restore(); - }); - - it('should add style params to adUrl if bids are returned', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - let adapter = new OrbitsoftAdapter(); - - let bidderRequest = { - bidderCode: 'orbitsoft', - bids: [ - { - bidId: 'bidIdOrbitsoft2', - bidder: 'orbitsoft', - params: { - placementId: '16', - requestUrl: jptCallEndPoint, - style: { - title: { - family: 'Tahoma', - size: 'medium', - weight: 'normal', - style: 'normal', - color: '0053F9' - }, - description: { - family: 'Tahoma', - size: 'medium', - weight: 'normal', - style: 'normal', - color: '0053F9' - }, - url: { - family: 'Tahoma', - size: 'medium', - weight: 'normal', - style: 'normal', - color: '0053F9' - }, - colors: { - background: 'ffffff', - border: 'E0E0E0', - link: '5B99FE' - } - } - }, - sizes: [[300, 250]], - placementCode: 'test-div-12345' - } - ] - }; - - // Bid response with content_url - let response = { - callback_uid: 'bidIdOrbitsoft2', - content_url: contentCallEndPoint + 'id=1_201707031440_56069e8e70318303e5869fad86722cb0', - cpm: 0.03, - width: 300, - height: 250 - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - $$PREBID_GLOBAL$$.handleOASCB(response); - - let bidResponse1 = stubAddBidResponse.getCall(0).args[1]; - let adUrl = bidResponse1.adUrl; - let content_url = contentCallEndPoint + 'id=1_201707031440_56069e8e70318303e5869fad86722cb0'; - expect(adUrl).to.include(content_url); - expect(adUrl).to.include('f1=Tahoma'); - expect(adUrl).to.include('fs1=medium'); - expect(adUrl).to.include('w1=normal'); - expect(adUrl).to.include('s1=normal'); - expect(adUrl).to.include('c3=0053F9'); - expect(adUrl).to.include('f2=Tahoma'); - expect(adUrl).to.include('fs2=medium'); - expect(adUrl).to.include('w2=normal'); - expect(adUrl).to.include('s2=normal'); - expect(adUrl).to.include('c4=0053F9'); - expect(adUrl).to.include('f3=Tahoma'); - expect(adUrl).to.include('fs3=medium'); - expect(adUrl).to.include('w3=normal'); - expect(adUrl).to.include('s3=normal'); - expect(adUrl).to.include('c5=0053F9'); - expect(adUrl).to.include('c2=ffffff'); - expect(adUrl).to.include('c1=E0E0E0'); - expect(adUrl).to.include('c6=5B99FE'); - - stubAddBidResponse.restore(); - }); - - it('should add custom params to adUrl if bids are returned', function () { - let stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - let adapter = new OrbitsoftAdapter(); - - let bidderRequest = { - bidderCode: 'orbitsoft', - bids: [ - { - bidId: 'bidIdOrbitsoft3', - bidder: 'orbitsoft', - params: { - placementId: '16', - requestUrl: jptCallEndPoint, - customParams: { - macro_name: 'macro_value' - } - }, - sizes: [[300, 250]], - placementCode: 'test-div-12345' - } - ] - }; - - // Bid response with custom params - let response = { - callback_uid: 'bidIdOrbitsoft3', - content_url: contentCallEndPoint + 'id=1_201707031440_56069e8e70318303e5869fad86722cb0', - cpm: 0.03, - width: 300, - height: 250 - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - $$PREBID_GLOBAL$$.handleOASCB(response); - - let bidResponse1 = stubAddBidResponse.getCall(0).args[1]; - let adUrl = bidResponse1.adUrl; - let content_url = contentCallEndPoint + 'id=1_201707031440_56069e8e70318303e5869fad86722cb0'; - expect(adUrl).to.include(content_url); - expect(adUrl).to.include('c.macro_name=macro_value'); - - stubAddBidResponse.restore(); - }); - }); -}); diff --git a/test/spec/modules/piximediaBidAdapter_spec.js b/test/spec/modules/piximediaBidAdapter_spec.js deleted file mode 100644 index 14834c81714..00000000000 --- a/test/spec/modules/piximediaBidAdapter_spec.js +++ /dev/null @@ -1,416 +0,0 @@ -describe('Piximedia adapter tests', function () { - var expect = require('chai').expect; - var urlParse = require('url-parse'); - - // var querystringify = require('querystringify'); - - var Adapter = require('modules/piximediaBidAdapter'); - var adLoader = require('src/adloader'); - var bidmanager = require('src/bidmanager'); - var utils = require('src/utils'); - var CONSTANTS = require('src/constants.json'); - - let stubLoadScript; - - beforeEach(function () { - stubLoadScript = sinon.stub(adLoader, 'loadScript'); - }); - - afterEach(function () { - stubLoadScript.restore(); - }); - - describe('creation of prebid url', function () { - if (typeof ($$PREBID_GLOBAL$$._bidsReceived) === 'undefined') { - $$PREBID_GLOBAL$$._bidsReceived = []; - } - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = []; - } - if (typeof ($$PREBID_GLOBAL$$._adsReceived) === 'undefined') { - $$PREBID_GLOBAL$$._adsReceived = []; - } - - it('should call the Piximedia prebid URL once on valid calls', function () { - var params = { - bidderCode: 'piximedia', - bidder: 'piximedia', - bids: [ - { - bidId: '4d3819cffc4d12', - sizes: [[300, 250]], - bidder: 'piximedia', - params: { siteId: 'TEST', placementId: 'TEST', prebidUrl: '//resources.pm/tests/prebid/bids.js' }, - requestId: '59c318fd382219', - placementCode: '/20164912/header-bid-tag-0' - } - ] - }; - - new Adapter().callBids(params); - sinon.assert.calledOnce(stubLoadScript); - }); - - it('should not call the Piximedia prebid URL once on invalid calls', function () { - var params = { - bidderCode: 'piximedia', - bidder: 'piximedia', - bids: [ - { - bidId: '4d3819cffc4d12', - sizes: [[300, 250]], - bidder: 'piximedia', - params: { prebidUrl: '//resources.pm/tests/prebid/bids.js' }, // this is invalid: site and placement ID are missing - requestId: '59c318fd382219', - placementCode: '/20164912/header-bid-tag-0' - } - ] - }; - - new Adapter().callBids(params); - sinon.assert.notCalled(stubLoadScript); - }); - - it('should call the correct Prebid URL when using the default URL', function () { - var params = { - bidderCode: 'piximedia', - bidder: 'piximedia', - bids: [ - { - bidId: '4d3819cffc4d12', - sizes: [[300, 250]], - bidder: 'piximedia', - params: { siteId: 'TEST', placementId: 'TEST' }, - requestId: '59c318fd382219', - placementCode: '/20164912/header-bid-tag-0' - } - ] - }; - - new Adapter().callBids(params); - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledWith(stubLoadScript, bidUrl); - - var parsedBidUrl = urlParse(bidUrl); - - 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'); - }); - - it('should call the correct Prebid URL when using the default URL with a deal and custom data', function () { - var params = { - bidderCode: 'piximedia', - bidder: 'piximedia', - bids: [ - { - bidId: '4d3819cffc4d12', - sizes: [[300, 250]], - bidder: 'piximedia', - params: { siteId: 'TEST', placementId: 'TEST', dealId: 1295, custom: 'bespoke', custom2: function() { return 'bespoke2'; }, custom3: null, custom4: function() {} }, - requestId: '59c318fd382219', - placementCode: '/20164912/header-bid-tag-0' - } - ] - }; - - new Adapter().callBids(params); - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledWith(stubLoadScript, bidUrl); - - var parsedBidUrl = urlParse(bidUrl); - - 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'); - }); - - it('should call the correct Prebid URL when using the default URL and overridding sizes', function () { - var params = { - bidderCode: 'piximedia', - bidder: 'piximedia', - bids: [ - { - bidId: '4d3819cffc4d12', - sizes: [[300, 250]], - bidder: 'piximedia', - params: { siteId: 'TEST', placementId: 'TEST', sizes: [[300, 600], [728, 90]] }, - requestId: '59c318fd382219', - placementCode: '/20164912/header-bid-tag-0' - } - ] - }; - - new Adapter().callBids(params); - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledWith(stubLoadScript, bidUrl); - - var parsedBidUrl = urlParse(bidUrl); - - 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'); - }); - - it('should call the correct Prebid URL when supplying a custom URL', function () { - var params = { - bidderCode: 'piximedia', - bidder: 'piximedia', - bids: [ - { - bidId: '4d3819cffc4d12', - sizes: [[300, 250]], - bidder: 'piximedia', - params: { siteId: 'TEST', placementId: 'TEST', prebidUrl: '//resources.pm/tests/prebid/bids.js' }, - requestId: '59c318fd382219', - placementCode: '/20164912/header-bid-tag-0' - } - ] - }; - - new Adapter().callBids(params); - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledWith(stubLoadScript, bidUrl); - - var parsedBidUrl = urlParse(bidUrl); - - 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'); - }); - }); - - describe('handling of the callback response', function () { - if (typeof ($$PREBID_GLOBAL$$._bidsReceived) === 'undefined') { - $$PREBID_GLOBAL$$._bidsReceived = []; - } - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = []; - } - if (typeof ($$PREBID_GLOBAL$$._adsReceived) === 'undefined') { - $$PREBID_GLOBAL$$._adsReceived = []; - } - - var params = { - bidderCode: 'piximedia', - bidder: 'piximedia', - bids: [ - { - bidId: '4d3819cffc4d12', - sizes: [[300, 250]], - bidder: 'piximedia', - params: { siteId: 'TEST', placementId: 'TEST', prebidUrl: '//resources.pm/tests/prebid/bids.js' }, - requestId: '59c318fd382219', - placementCode: '/20164912/header-bid-tag-0' - } - ] - }; - - it('Piximedia callback function should exist', function () { - expect($$PREBID_GLOBAL$$.handlePiximediaCallback).to.exist.and.to.be.a('function'); - }); - - it('bidmanager.addBidResponse should be called once with correct arguments', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - var stubGetUniqueIdentifierStr = sinon.spy(utils, 'getUniqueIdentifierStr'); - - var response = { - foundbypm: true, - currency: 'EUR', - cpm: 1.23, - dealId: 9948, - width: 300, - height: 250, - html: '
ad
' - }; - - new Adapter().callBids(params); - - var adUnits = []; - var unit = {}; - unit.bids = [params]; - unit.code = '/20164912/header-bid-tag'; - unit.sizes = [[300, 250], [728, 90]]; - adUnits.push(unit); - - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = [params]; - } else { - $$PREBID_GLOBAL$$._bidsRequested.push(params); - } - $$PREBID_GLOBAL$$.adUnits = adUnits; - response.cbid = stubGetUniqueIdentifierStr.returnValues[0]; - - $$PREBID_GLOBAL$$.handlePiximediaCallback(response); - - sinon.assert.calledOnce(stubAddBidResponse); - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - - expect(bidPlacementCode1).to.equal('/20164912/header-bid-tag-0'); - expect(bidObject1.cpm).to.equal(1.23); - expect(bidObject1.ad).to.equal('
ad
'); - expect(bidObject1.width).to.equal(300); - expect(bidObject1.dealId).to.equal(9948); - expect(bidObject1.height).to.equal(250); - expect(bidObject1.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bidObject1.bidderCode).to.equal('piximedia'); - - stubAddBidResponse.restore(); - stubGetUniqueIdentifierStr.restore(); - }); - - it('bidmanager.addBidResponse should be called once with correct arguments on partial response', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - var stubGetUniqueIdentifierStr = sinon.spy(utils, 'getUniqueIdentifierStr'); - - // this time, we do not provide dealId - var response = { - foundbypm: true, - cpm: 1.23, - width: 300, - height: 250, - currency: 'EUR', - html: '
ad
' - }; - - new Adapter().callBids(params); - - var adUnits = []; - var unit = {}; - unit.bids = [params]; - unit.code = '/20164912/header-bid-tag'; - unit.sizes = [[300, 250], [728, 90]]; - adUnits.push(unit); - - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = [params]; - } else { - $$PREBID_GLOBAL$$._bidsRequested.push(params); - } - $$PREBID_GLOBAL$$.adUnits = adUnits; - response.cbid = stubGetUniqueIdentifierStr.returnValues[0]; - - $$PREBID_GLOBAL$$.handlePiximediaCallback(response); - - sinon.assert.calledOnce(stubAddBidResponse); - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - - expect(bidPlacementCode1).to.equal('/20164912/header-bid-tag-0'); - expect(bidObject1.cpm).to.equal(1.23); - expect(bidObject1.ad).to.equal('
ad
'); - expect(bidObject1.width).to.equal(300); - expect(bidObject1.height).to.equal(250); - expect(bidObject1.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bidObject1.bidderCode).to.equal('piximedia'); - - stubAddBidResponse.restore(); - stubGetUniqueIdentifierStr.restore(); - }); - - it('bidmanager.addBidResponse should be called once without any ads', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - var stubGetUniqueIdentifierStr = sinon.spy(utils, 'getUniqueIdentifierStr'); - - var response = { - foundbypm: false - }; - - new Adapter().callBids(params); - - var adUnits = []; - var unit = {}; - unit.bids = [params]; - unit.code = '/20164912/header-bid-tag'; - unit.sizes = [[300, 250], [728, 90]]; - adUnits.push(unit); - - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = [params]; - } else { - $$PREBID_GLOBAL$$._bidsRequested.push(params); - } - $$PREBID_GLOBAL$$.adUnits = adUnits; - response.cbid = stubGetUniqueIdentifierStr.returnValues[0]; - - $$PREBID_GLOBAL$$.handlePiximediaCallback(response); - - sinon.assert.calledOnce(stubAddBidResponse); - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - - expect(bidPlacementCode1).to.equal('/20164912/header-bid-tag-0'); - expect(bidObject1.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(bidObject1.bidderCode).to.equal('piximedia'); - - stubAddBidResponse.restore(); - stubGetUniqueIdentifierStr.restore(); - }); - - it('bidmanager.addBidResponse should not be called on bogus cbid', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - var stubGetUniqueIdentifierStr = sinon.spy(utils, 'getUniqueIdentifierStr'); - - var response = { - foundbypm: false - }; - - new Adapter().callBids(params); - - var adUnits = []; - var unit = {}; - unit.bids = [params]; - unit.code = '/20164912/header-bid-tag'; - unit.sizes = [[300, 250], [728, 90]]; - adUnits.push(unit); - - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = [params]; - } else { - $$PREBID_GLOBAL$$._bidsRequested.push(params); - } - $$PREBID_GLOBAL$$.adUnits = adUnits; - response.cbid = stubGetUniqueIdentifierStr.returnValues[0] + '_BOGUS'; - - $$PREBID_GLOBAL$$.handlePiximediaCallback(response); - - sinon.assert.notCalled(stubAddBidResponse); - - stubAddBidResponse.restore(); - stubGetUniqueIdentifierStr.restore(); - }); - - it('bidmanager.addBidResponse should not be called on bogus response', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - var response = null; // this is bogus: we expect an object - - new Adapter().callBids(params); - - var adUnits = []; - var unit = {}; - unit.bids = [params]; - unit.code = '/20164912/header-bid-tag'; - unit.sizes = [[300, 250], [728, 90]]; - adUnits.push(unit); - - if (typeof ($$PREBID_GLOBAL$$._bidsRequested) === 'undefined') { - $$PREBID_GLOBAL$$._bidsRequested = [params]; - } else { - $$PREBID_GLOBAL$$._bidsRequested.push(params); - } - $$PREBID_GLOBAL$$.adUnits = adUnits; - - $$PREBID_GLOBAL$$.handlePiximediaCallback(response); - - sinon.assert.notCalled(stubAddBidResponse); - - stubAddBidResponse.restore(); - }); - }); -}); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 0403617a846..608ac102ace 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -1,18 +1,18 @@ import { expect } from 'chai'; -import Adapter from 'modules/prebidServerBidAdapter'; +import { PrebidServer as Adapter } from 'modules/prebidServerBidAdapter'; import adapterManager from 'src/adaptermanager'; -import bidmanager from 'src/bidmanager'; -import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; import cookie from 'src/cookie'; import { userSync } from 'src/userSync'; +import { ajax } from 'src/ajax'; +import { config } from 'src/config'; let CONFIG = { accountId: '1', enabled: true, bidders: ['appnexus'], timeout: 1000, - endpoint: CONSTANTS.S2S.DEFAULT_ENDPOINT + endpoint: 'https://prebid.adnxs.com/pbs/v1/auction' }; const REQUEST = { @@ -43,10 +43,7 @@ const REQUEST = { 'bidder': 'appnexus', 'params': { 'placementId': '10433394', - 'member': 123, - 'randomKey': 123456789, - 'single_test': null, - 'myMultiVar': ['myValue', 124578] + 'member': 123 } } ] @@ -54,6 +51,40 @@ const REQUEST = { ] }; +const BID_REQUESTS = [ + { + 'bidderCode': 'appnexus', + 'auctionId': '173afb6d132ba3', + 'bidderRequestId': '3d1063078dfcc8', + 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '10433394', + 'member': 123 + }, + 'bid_id': '123', + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': '4ef956ad-fd83-406d-bd35-e4bb786ab86c', + 'sizes': [ + { + 'w': 300, + 'h': 250 + } + ], + 'bidId': '259fb43aaa06c1', + 'bidderRequestId': '3d1063078dfcc8', + 'auctionId': '173afb6d132ba3' + } + ], + 'auctionStart': 1510852447530, + 'timeout': 5000, + 'src': 's2s', + 'doneCbCallCount': 0 + } +]; + const RESPONSE = { 'tid': '437fbbf5-33f5-487a-8e16-a7112903cfe5', 'status': 'OK', @@ -178,10 +209,17 @@ const RESPONSE_NO_PBS_COOKIE_ERROR = { }; describe('S2S Adapter', () => { - let adapter; + let adapter, + addBidResponse = sinon.spy(), + done = sinon.spy(); beforeEach(() => adapter = new Adapter()); + afterEach(() => { + addBidResponse.reset(); + done.reset(); + }); + describe('request function', () => { let xhr; let requests; @@ -199,13 +237,11 @@ describe('S2S Adapter', () => { }); it('exists converts types', () => { - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); 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'); }); }); @@ -218,13 +254,6 @@ describe('S2S Adapter', () => { sinon.stub(utils, 'insertUserSyncIframe'); sinon.stub(utils, 'logError'); sinon.stub(cookie, 'cookieSet'); - sinon.stub(bidmanager, 'addBidResponse'); - sinon.stub(utils, 'getBidderRequestAllAdUnits').returns({ - bids: [{ - bidId: '123', - placementCode: 'div-gpt-ad-1460505748561-0' - }] - }); sinon.stub(utils, 'getBidRequest').returns({ bidId: '123' }); @@ -232,8 +261,6 @@ describe('S2S Adapter', () => { afterEach(() => { server.restore(); - bidmanager.addBidResponse.restore(); - utils.getBidderRequestAllAdUnits.restore(); utils.getBidRequest.restore(); utils.triggerPixel.restore(); utils.insertUserSyncIframe.restore(); @@ -245,117 +272,85 @@ describe('S2S Adapter', () => { it('registers bids', () => { server.respondWith(JSON.stringify(RESPONSE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); + sinon.assert.calledOnce(addBidResponse); - const response = bidmanager.addBidResponse.firstCall.args[1]; + const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('cpm', 0.5); expect(response).to.have.property('adId', '123'); }); - it('registers no-bid response when ad unit not set', () => { + it('does not call addBidResponse and calls done when ad unit not set', () => { server.respondWith(JSON.stringify(RESPONSE_NO_BID_NO_UNIT)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const ad_unit_code = bidmanager.addBidResponse.firstCall.args[0]; - expect(ad_unit_code).to.equal('div-gpt-ad-1460505748561-0'); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('statusMessage', 'Bid returned empty or error response'); - const bid_request_passed = bidmanager.addBidResponse.firstCall.args[1]; - expect(bid_request_passed).to.have.property('adId', '123'); + sinon.assert.notCalled(addBidResponse); + sinon.assert.calledOnce(done); }); - it('registers no-bid response when server requests cookie sync', () => { + it('does not call addBidResponse and calls done when server requests cookie sync', () => { server.respondWith(JSON.stringify(RESPONSE_NO_COOKIE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const ad_unit_code = bidmanager.addBidResponse.firstCall.args[0]; - expect(ad_unit_code).to.equal('div-gpt-ad-1460505748561-0'); - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('statusMessage', 'Bid returned empty or error response'); - - const bid_request_passed = bidmanager.addBidResponse.firstCall.args[1]; - expect(bid_request_passed).to.have.property('adId', '123'); + sinon.assert.notCalled(addBidResponse); + sinon.assert.calledOnce(done); }); - it('registers no-bid response when ad unit is set', () => { + it('does not call addBidResponse and calls done when ad unit is set', () => { server.respondWith(JSON.stringify(RESPONSE_NO_BID_UNIT_SET)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); - const ad_unit_code = bidmanager.addBidResponse.firstCall.args[0]; - expect(ad_unit_code).to.equal('div-gpt-ad-1460505748561-0'); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('statusMessage', 'Bid returned empty or error response'); + sinon.assert.notCalled(addBidResponse); + sinon.assert.calledOnce(done); }); - it('registers no-bid response when there are less bids than requests', () => { - utils.getBidderRequestAllAdUnits.restore(); - sinon.stub(utils, 'getBidderRequestAllAdUnits').returns({ - bids: [{ - bidId: '123', - placementCode: 'div-gpt-ad-1460505748561-0' - }, { - bidId: '101111', - placementCode: 'div-gpt-ad-1460505748561-1' - }] - }); - + it('registers successful bids and calls done when there are less bids than requests', () => { server.respondWith(JSON.stringify(RESPONSE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - sinon.assert.calledTwice(bidmanager.addBidResponse); + sinon.assert.calledOnce(addBidResponse); + sinon.assert.calledOnce(done); - expect(bidmanager.addBidResponse.firstCall.args[0]).to.equal('div-gpt-ad-1460505748561-0'); - expect(bidmanager.addBidResponse.secondCall.args[0]).to.equal('div-gpt-ad-1460505748561-1'); + expect(addBidResponse.firstCall.args[0]).to.equal('div-gpt-ad-1460505748561-0'); - expect(bidmanager.addBidResponse.firstCall.args[1]).to.have.property('adId', '123'); - expect(bidmanager.addBidResponse.secondCall.args[1]).to.have.property('adId', '101111'); + expect(addBidResponse.firstCall.args[1]).to.have.property('adId', '123'); - expect(bidmanager.addBidResponse.firstCall.args[1]) + expect(addBidResponse.firstCall.args[1]) .to.have.property('statusMessage', 'Bid available'); - expect(bidmanager.addBidResponse.secondCall.args[1]) - .to.have.property('statusMessage', 'Bid returned empty or error response'); }); it('should have dealId in bidObject', () => { server.respondWith(JSON.stringify(RESPONSE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - const response = bidmanager.addBidResponse.firstCall.args[1]; + const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('dealId', 'test-dealid'); }); it('should pass through default adserverTargeting if present in bidObject', () => { server.respondWith(JSON.stringify(RESPONSE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - const response = bidmanager.addBidResponse.firstCall.args[1]; + const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('adserverTargeting').that.deep.equals({'foo': 'bar'}); }); @@ -367,8 +362,8 @@ describe('S2S Adapter', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(rubiconAdapter.registerSyncs); @@ -379,27 +374,27 @@ describe('S2S Adapter', () => { it('registers bid responses when server requests cookie sync', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); + sinon.assert.calledOnce(addBidResponse); - const ad_unit_code = bidmanager.addBidResponse.firstCall.args[0]; + const ad_unit_code = addBidResponse.firstCall.args[0]; expect(ad_unit_code).to.equal('div-gpt-ad-1460505748561-0'); - const response = bidmanager.addBidResponse.firstCall.args[1]; + const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('source', 's2s'); - const bid_request_passed = bidmanager.addBidResponse.firstCall.args[1]; + const bid_request_passed = addBidResponse.firstCall.args[1]; expect(bid_request_passed).to.have.property('adId', '123'); }); it('does cookie sync when no_cookie response', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(utils.triggerPixel); @@ -411,8 +406,8 @@ describe('S2S Adapter', () => { it('logs error when no_cookie response is missing type or url', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE_ERROR)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: CONFIG}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.notCalled(utils.triggerPixel); @@ -423,22 +418,62 @@ describe('S2S Adapter', () => { it('does not call cookieSet cookie sync when no_cookie response && not opted in', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - adapter.setConfig(CONFIG); - adapter.callBids(REQUEST); + let myConfig = Object.assign({}, CONFIG); + + config.setConfig({s2sConfig: myConfig}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.notCalled(cookie.cookieSet); }); it('calls cookieSet cookie sync when no_cookie response && opted in', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); - let config = Object.assign({ - cookieSet: true + let myConfig = Object.assign({ + cookieSetUrl: 'https://acdn.adnxs.com/cookieset/cs.js' }, CONFIG); - adapter.setConfig(config); - adapter.callBids(REQUEST); + config.setConfig({s2sConfig: myConfig}); + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(cookie.cookieSet); }); }); + + describe('s2sConfig', () => { + let logErrorSpy; + + beforeEach(() => { + logErrorSpy = sinon.spy(utils, 'logError'); + }); + + afterEach(() => { + utils.logError.restore(); + }); + + it('should log error when accountId is missing', () => { + const options = { + enabled: true, + bidders: ['appnexus'], + timeout: 1000, + adapter: 'prebidServer', + endpoint: 'https://prebid.adnxs.com/pbs/v1/auction' + }; + + config.setConfig({ s2sConfig: options }); + sinon.assert.calledOnce(logErrorSpy); + }); + + it('should log error when bidders is missing', () => { + const options = { + accountId: '1', + enabled: true, + timeout: 1000, + adapter: 's2s', + endpoint: 'https://prebid.adnxs.com/pbs/v1/auction' + }; + + config.setConfig({ s2sConfig: options }); + sinon.assert.calledOnce(logErrorSpy); + }); + }); }); diff --git a/test/spec/modules/pubgearsBidAdapter_spec.js b/test/spec/modules/pubgearsBidAdapter_spec.js deleted file mode 100644 index 81f890e0dfd..00000000000 --- a/test/spec/modules/pubgearsBidAdapter_spec.js +++ /dev/null @@ -1,287 +0,0 @@ -import { expect } from 'chai'; -import Adapter from 'modules/pubgearsBidAdapter' -import bidmanager from 'src/bidmanager' - -describe('PubGearsAdapter', () => { - var adapter, mockScript, - params = { - bids: [] - } - - beforeEach(() => { - adapter = new Adapter() - mockScript = document.createElement('script') - sinon.spy(mockScript, 'setAttribute') - }) - - describe('request function', () => { - beforeEach(() => { - sinon.spy(document, 'createElement') - }) - - afterEach(() => { - document.createElement.restore && document.createElement.restore() - var s = document.getElementById('pg-header-tag') - if (s) { s.parentNode.removeChild(s) } - }) - - it('has `#callBids()` method', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function') - }) - - it('requires bids to make script', () => { - adapter.callBids({bids: []}) - expect(document.createElement.notCalled).to.be.ok - }) - - it('creates script when passed bids', () => { - adapter.callBids({ - bidderCode: 'pubgears', - bids: [ - { - bidder: 'pubgears', - sizes: [ [300, 250] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - } - ] - }) - - sinon.assert.calledWith(document.createElement, 'script') - }) - - it('should assign attributes to script', () => { - adapter.callBids({ - bidderCode: 'pubgears', - bids: [ - { - bidder: 'pubgears', - sizes: [ [300, 250] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - }, - { - bidder: 'pubgears', - sizes: [ [160, 600] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - } - ] - }) - var script = document.createElement.returnValues[0] - var slots = script.getAttribute('data-bsm-slot-list') - expect(slots).to.equal('testpub.com/combined@300x250 testpub.com/combined@160x600') - expect(script.getAttribute('data-bsm-flag')).to.equal('true') - expect(script.getAttribute('data-bsm-pub')).to.equal('integration') - expect(script.getAttribute('src')).to.equal('//c.pubgears.com/tags/h') - expect(script.id).to.equal('pg-header-tag') - }) - - it('should reuse existing script when called twice', () => { - var params = { - bidderCode: 'pubgears', - bids: [ - { - bidder: 'pubgears', - sizes: [ [300, 250] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - }, - { - bidder: 'pubgears', - sizes: [ [160, 600] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - } - ] - } - adapter.callBids(params) - expect(document.createElement.calledOnce).to.be.true - adapter.callBids(params) - expect(document.createElement.calledOnce).to.be.true - }) - - it('should register event listeners', () => { - var script = document.createElement('script') - script.id = 'pg-header-tag' - var spy = sinon.spy(script, 'addEventListener') - document.body.appendChild(script) - var params = { - bidderCode: 'pubgears', - bids: [ - { - bidder: 'pubgears', - sizes: [ [300, 250] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - }, - { - bidder: 'pubgears', - sizes: [ [160, 600] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - } - ] - } - adapter.callBids(params) - - expect(spy.calledWith('onBidResponse')).to.be.ok - expect(spy.calledWith('onResourceComplete')).to.be.ok - }) - }) - - describe('bids received', () => { - beforeEach(() => { - sinon.spy(bidmanager, 'addBidResponse') - }) - - afterEach(() => { - bidmanager.addBidResponse.restore() - }) - - it('should call bidManager.addBidResponse() when bid received', () => { - var options = { - bubbles: false, - cancelable: false, - detail: { - gross_price: 1000, - resource: { - position: 'atf', - pub_zone: 'testpub.com/combined', - size: '300x250' - } - } - } - - adapter.callBids({ - bidderCode: 'pubgears', - bids: [ - { - bidder: 'pubgears', - sizes: [ [300, 250] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - }, - { - bidder: 'pubgears', - sizes: [ [160, 600] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - } - ] - - }) - var script = document.getElementById('pg-header-tag') - var event = new CustomEvent('onBidResponse', options) - script.dispatchEvent(event) - - expect(bidmanager.addBidResponse.calledOnce).to.be.ok - }) - - it('should send correct bid response object when receiving onBidResponse event', () => { - expect(bidmanager.addBidResponse.calledOnce).to.not.be.ok - var bid = { - bidder: 'pubgears', - sizes: [ [300, 250] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - } - - adapter.callBids({ - bidderCode: 'pubgears', - bids: [ bid ] - }) - - var options = { - bubbles: false, - cancelable: false, - detail: { - gross_price: 1000, - resource: { - position: 'atf', - pub_zone: 'testpub.com/combined', - size: '300x250' - } - } - } - var script = document.getElementById('pg-header-tag') - var event = new CustomEvent('onBidResponse', options) - script.dispatchEvent(event) - - var args = bidmanager.addBidResponse.getCall(1).args - expect(args).to.have.length(2) - var bidResponse = args[1] - expect(bidResponse.ad).to.contain(bid.params.pubZone) - }) - - it('should send $0 bid as no-bid response', () => { - var bid = { - bidder: 'pubgears', - sizes: [ [300, 250] ], - adUnitCode: 'foo123/header-bid-tag', - params: { - publisherName: 'integration', - pubZone: 'testpub.com/combined' - } - } - - adapter.callBids({ - bidderCode: 'pubgears', - bids: [ bid ] - }) - - var options = { - bubbles: false, - cancelable: false, - detail: { - gross_price: 0, - resource: { - position: 'atf', - pub_zone: 'testpub.com/combined', - size: '300x250' - } - } - } - var script = document.getElementById('pg-header-tag') - var event = new CustomEvent('onBidResponse', options) - - bidmanager.addBidResponse.reset() - script.dispatchEvent(event) - - var args = bidmanager.addBidResponse.getCall(1).args - var bidResponse = args[1] - expect(bidResponse).to.be.a('object') - expect(bidResponse.getStatusCode()).to.equal(2) - }) - }) -}) diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js deleted file mode 100644 index c7b8cd5cd8e..00000000000 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ /dev/null @@ -1,276 +0,0 @@ -import { - expect -} from 'chai'; -import * as utils from 'src/utils'; -import PubMaticAdapter from 'modules/pubmaticBidAdapter'; -import bidmanager from 'src/bidmanager'; -import constants from 'src/constants.json'; - -let getDefaultBidRequest = () => { - return { - bidderCode: 'pubmatic', - requestId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', - bidderRequestId: '7101db09af0db2', - start: new Date().getTime(), - bids: [{ - bidder: 'pubmatic', - bidId: '84ab500420319d', - bidderRequestId: '7101db09af0db2', - requestId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', - placementCode: 'DIV_1', - params: { - placement: 1234567, - network: '9599.1' - } - }] - }; -}; - -describe('PubMaticAdapter', () => { - let adapter; - - function createBidderRequest({ - bids, - params - } = {}) { - var bidderRequest = getDefaultBidRequest(); - if (bids && Array.isArray(bids)) { - bidderRequest.bids = bids; - } - if (params) { - bidderRequest.bids.forEach(bid => bid.params = params); - } - return bidderRequest; - } - - beforeEach(() => adapter = new PubMaticAdapter()); - - describe('callBids()', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - - describe('user syncup', () => { - beforeEach(() => { - sinon.stub(utils, 'insertElement'); - }); - - afterEach(() => { - utils.insertElement.restore(); - }); - - it('usersync is initiated', () => { - adapter.callBids(createBidderRequest({ - params: { - publisherId: 9999, - adSlot: 'abcd@728x90', - age: '20' - } - })); - utils.insertElement.calledOnce.should.be.true; - expect(utils.insertElement.getCall(0).args[0].src).to.equal('http://ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p=9999'); - }); - }); - - describe('bid request', () => { - beforeEach(() => { - sinon.stub(utils, 'createContentToExecuteExtScriptInFriendlyFrame', function() { - return ''; - }); - }); - - afterEach(() => { - utils.createContentToExecuteExtScriptInFriendlyFrame.restore(); - }); - - it('requires parameters to be made', () => { - adapter.callBids({}); - utils.createContentToExecuteExtScriptInFriendlyFrame.calledOnce.should.be.false; - }); - - it('for publisherId 9990 call is made to gads.pubmatic.com', () => { - var bidRequest = createBidderRequest({ - params: { - publisherId: 9990, - adSlot: ' abcd@728x90', - age: '20', - wiid: 'abcdefghijk', - profId: '1234', - verId: '12', - pmzoneid: 'abcd123, efg345', - dctr: 'key=1234,5678' - } - }); - adapter.callBids(bidRequest); - var callURL = utils.createContentToExecuteExtScriptInFriendlyFrame.getCall(0).args[0]; - expect(bidRequest.bids[0].params.adSlot).to.equal('abcd@728x90'); - expect(callURL).to.contain('gads.pubmatic.com/AdServer/AdCallAggregator?'); - expect(callURL).to.contain('SAVersion=1100'); - expect(callURL).to.contain('wp=PreBid'); - expect(callURL).to.contain('js=1'); - expect(callURL).to.contain('screenResolution='); - expect(callURL).to.contain('wv=' + constants.REPO_AND_VERSION); - expect(callURL).to.contain('ranreq='); - expect(callURL).to.contain('inIframe='); - expect(callURL).to.contain('pageURL='); - expect(callURL).to.contain('refurl='); - expect(callURL).to.contain('kltstamp='); - expect(callURL).to.contain('timezone='); - expect(callURL).to.contain('age=20'); - expect(callURL).to.contain('adslots=%5Babcd%40728x90%5D'); - expect(callURL).to.contain('kadpageurl='); - expect(callURL).to.contain('wiid=abcdefghijk'); - expect(callURL).to.contain('profId=1234'); - expect(callURL).to.contain('verId=12'); - expect(callURL).to.contain('pmZoneId=abcd123%2C%20efg345'); - expect(callURL).to.contain('dctr=key%3D1234%2C5678'); - }); - - it('for publisherId 9990 call is made to gads.pubmatic.com, age passed as int not being passed ahead', () => { - adapter.callBids(createBidderRequest({ - params: { - publisherId: 9990, - adSlot: 'abcd@728x90', - age: 20, - wiid: 'abcdefghijk', - profId: '1234', - verId: '12', - pmzoneid: {}, - dctr: 1234 - } - })); - var callURL = utils.createContentToExecuteExtScriptInFriendlyFrame.getCall(0).args[0]; - expect(callURL).to.contain('gads.pubmatic.com/AdServer/AdCallAggregator?'); - expect(callURL).to.not.contain('age=20'); - expect(callURL).to.not.contain('dctr=1234'); - }); - - it('for publisherId 9990 call is made to gads.pubmatic.com, invalid data for pmzoneid', () => { - adapter.callBids(createBidderRequest({ - params: { - publisherId: 9990, - adSlot: 'abcd@728x90', - age: '20', - wiid: 'abcdefghijk', - profId: '1234', - verId: '12', - pmzoneid: {}, - dctr: 1234 - } - })); - var callURL = utils.createContentToExecuteExtScriptInFriendlyFrame.getCall(0).args[0]; - expect(callURL).to.contain('gads.pubmatic.com/AdServer/AdCallAggregator?'); - expect(callURL).to.not.contain('pmZoneId='); - }); - }); - - describe('#handlePubmaticCallback: ', () => { - beforeEach(() => { - sinon.stub(utils, 'createContentToExecuteExtScriptInFriendlyFrame', function() { - return ''; - }); - sinon.stub(bidmanager, 'addBidResponse'); - }); - - afterEach(() => { - utils.createContentToExecuteExtScriptInFriendlyFrame.restore(); - bidmanager.addBidResponse.restore(); - }); - - it('exists and is a function', () => { - expect($$PREBID_GLOBAL$$.handlePubmaticCallback).to.exist.and.to.be.a('function'); - }); - - it('empty response, arguments not passed', () => { - adapter.callBids(createBidderRequest({ - params: { - publisherId: 9999, - adSlot: 'abcd@728x90', - age: '20' - } - })); - $$PREBID_GLOBAL$$.handlePubmaticCallback(); - expect(bidmanager.addBidResponse.callCount).to.equal(0); - }); - - it('empty response', () => { - adapter.callBids(createBidderRequest({ - params: { - publisherId: 9999, - adSlot: 'abcd@728x90', - age: '20' - } - })); - $$PREBID_GLOBAL$$.handlePubmaticCallback({}, {}); - sinon.assert.called(bidmanager.addBidResponse); - expect(bidmanager.addBidResponse.firstCall.args[0]).to.equal('DIV_1'); - var theBid = bidmanager.addBidResponse.firstCall.args[1]; - expect(theBid.bidderCode).to.equal('pubmatic'); - expect(theBid.getStatusCode()).to.equal(2); - }); - - it('not empty response', () => { - adapter.callBids(createBidderRequest({ - params: { - publisherId: 9999, - adSlot: 'abcd@728x90:0', - age: '20' - } - })); - $$PREBID_GLOBAL$$.handlePubmaticCallback({ - 'abcd@728x90:0': { - 'ecpm': 10, - 'creative_tag': 'hello', - 'tracking_url': 'http%3a%2f%2fhaso.pubmatic.com%2fads%2f9999%2fGRPBID%2f2.gif%3ftrackid%3d12345', - 'width': 728, - 'height': 90, - 'deal_channel': 5 - } - }, { - 'abcd@728x90:0': 'bidstatus;1;bid;10.0000;bidid;abcd@728x90:0;wdeal;PMERW36842' - }); - sinon.assert.called(bidmanager.addBidResponse); - expect(bidmanager.addBidResponse.firstCall.args[0]).to.equal('DIV_1'); - var theBid = bidmanager.addBidResponse.firstCall.args[1]; - expect(theBid.bidderCode).to.equal('pubmatic'); - expect(theBid.adSlot).to.equal('abcd@728x90:0'); - expect(theBid.cpm).to.equal(10); - expect(theBid.width).to.equal(728); - expect(theBid.height).to.equal(90); - expect(theBid.dealId).to.equal('PMERW36842'); - expect(theBid.dealChannel).to.equal('PREF'); - }); - - it('not empty response, without dealChannel', () => { - adapter.callBids(createBidderRequest({ - params: { - publisherId: 9999, - adSlot: 'abcd@728x90', - age: '20' - } - })); - $$PREBID_GLOBAL$$.handlePubmaticCallback({ - 'abcd@728x90': { - 'ecpm': 10, - 'creative_tag': 'hello', - 'tracking_url': 'http%3a%2f%2fhaso.pubmatic.com%2fads%2f9999%2fGRPBID%2f2.gif%3ftrackid%3d12345', - 'width': 728, - 'height': 90 - } - }, { - 'abcd@728x90': 'bidstatus;1;bid;10.0000;bidid;abcd@728x90:0;wdeal;PMERW36842' - }); - sinon.assert.called(bidmanager.addBidResponse); - expect(bidmanager.addBidResponse.firstCall.args[0]).to.equal('DIV_1'); - var theBid = bidmanager.addBidResponse.firstCall.args[1]; - expect(theBid.bidderCode).to.equal('pubmatic'); - expect(theBid.adSlot).to.equal('abcd@728x90'); - expect(theBid.cpm).to.equal(10); - expect(theBid.width).to.equal(728); - expect(theBid.height).to.equal(90); - expect(theBid.dealId).to.equal('PMERW36842'); - expect(theBid.dealChannel).to.equal(null); - }); - }); - }); -}); diff --git a/test/spec/modules/pulsepointBidAdapter_spec.js b/test/spec/modules/pulsepointBidAdapter_spec.js index 07639310c36..cb99f1b5d98 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -1,163 +1,276 @@ +/* eslint dot-notation:0, quote-props:0 */ import {expect} from 'chai'; -import PulsePointAdapter from '../../../modules/pulsepointBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; +import {spec} from 'modules/pulsepointBidAdapter'; +import {getTopWindowLocation} from 'src/utils'; +import {newBidder} from 'src/adapters/bidderFactory'; describe('PulsePoint Adapter Tests', () => { - let pulsepointAdapter = new PulsePointAdapter(); - let slotConfigs; - let requests = []; - let responses = {}; - - function initPulsepointLib() { - /* Mocked PulsePoint library */ - window.pp = { - requestActions: { - BID: 0 + const slotConfigs = [{ + placementCode: '/DfpAccount1/slot1', + bidId: 'bid12345', + params: { + cp: 'p10000', + ct: 't10000', + cf: '300x250' + } + }, { + placementCode: '/DfpAccount2/slot2', + bidId: 'bid23456', + params: { + cp: 'p10000', + ct: 't20000', + cf: '728x90' + } + }]; + const nativeSlotConfig = [{ + placementCode: '/DfpAccount1/slot3', + bidId: 'bid12345', + nativeParams: { + title: { required: true, len: 200 }, + image: { wmin: 100 }, + sponsoredBy: { } + }, + params: { + cp: 'p10000', + ct: 't10000' + } + }]; + const appSlotConfig = [{ + placementCode: '/DfpAccount1/slot3', + bidId: 'bid12345', + params: { + cp: 'p10000', + ct: 't10000', + app: { + bundle: 'com.pulsepoint.apps', + storeUrl: 'http://pulsepoint.com/apps', + domain: 'pulsepoint.com', } - }; - /* Ad object */ - window.pp.Ad = function(config) { - this.display = function() { - requests.push(config); - config.callback(responses[config.ct]); - }; - }; - } + } + }]; - function resetPulsepointLib() { - window.pp = undefined; - } + it('Verify build request', () => { + const request = spec.buildRequests(slotConfigs); + expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // site object + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.publisher).to.not.equal(null); + expect(ortbRequest.site.publisher.id).to.equal('p10000'); + expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); + expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); + expect(ortbRequest.imp).to.have.lengthOf(2); + // device object + expect(ortbRequest.device).to.not.equal(null); + expect(ortbRequest.device.ua).to.equal(navigator.userAgent); + // slot 1 + expect(ortbRequest.imp[0].tagid).to.equal('t10000'); + 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); + // slot 2 + expect(ortbRequest.imp[1].tagid).to.equal('t20000'); + expect(ortbRequest.imp[1].banner).to.not.equal(null); + expect(ortbRequest.imp[1].banner.w).to.equal(728); + expect(ortbRequest.imp[1].banner.h).to.equal(90); + }); - beforeEach(() => { - initPulsepointLib(); - sinon.stub(bidManager, 'addBidResponse'); - sinon.stub(adLoader, 'loadScript'); + it('Verify parse response', () => { + 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' + }] + }] + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + expect(bids).to.have.lengthOf(1); + // verify first bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + 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.netRevenue).to.equal(true); + expect(bid.currency).to.equal('USD'); + expect(bid.ttl).to.equal(20); + }); - slotConfigs = { - bids: [ - { - placementCode: '/DfpAccount1/slot1', - bidder: 'pulsepoint', - bidId: 'bid12345', - params: { - cp: 'p10000', - ct: 't10000', - cf: '300x250', - param1: 'value1', - param2: 2 - } - }, { - placementCode: '/DfpAccount2/slot2', - bidder: 'pulsepoint', - bidId: 'bid23456', - params: { - cp: 'p20000', - ct: 't20000', - cf: '728x90' + 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'); }); - afterEach(() => { - bidManager.addBidResponse.restore(); - adLoader.loadScript.restore(); - requests = []; - responses = {}; + it('Verify full passback', () => { + const request = spec.buildRequests(slotConfigs); + const bids = spec.interpretResponse({ body: null }, request) + expect(bids).to.have.lengthOf(0); }); - it('Verify requests sent to PulsePoint library', () => { - pulsepointAdapter.callBids(slotConfigs); - expect(requests).to.have.length(2); - // slot 1 - expect(requests[0].cp).to.equal('p10000'); - expect(requests[0].ct).to.equal('t10000'); - expect(requests[0].cf).to.equal('300x250'); - expect(requests[0].ca).to.equal(0); - expect(requests[0].cn).to.equal(1); - expect(requests[0].cu).to.equal('http://bid.contextweb.com/header/tag'); - expect(requests[0].adUnitId).to.equal('/DfpAccount1/slot1'); - expect(requests[0]).to.have.property('callback'); - expect(requests[0].param1).to.equal('value1'); - expect(requests[0].param2).to.equal(2); - // //slot 2 - expect(requests[1].cp).to.equal('p20000'); - expect(requests[1].ct).to.equal('t20000'); - expect(requests[1].cf).to.equal('728x90'); - expect(requests[1].ca).to.equal(0); - expect(requests[1].cn).to.equal(1); - expect(requests[1].cu).to.equal('http://bid.contextweb.com/header/tag'); - expect(requests[1].adUnitId).to.equal('/DfpAccount2/slot2'); - expect(requests[1]).to.have.property('callback'); + it('Verify Native request', () => { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // native impression + expect(ortbRequest.imp[0].tagid).to.equal('t10000'); + expect(ortbRequest.imp[0].banner).to.equal(null); + const nativePart = ortbRequest.imp[0]['native']; + expect(nativePart).to.not.equal(null); + expect(nativePart.ver).to.equal('1.1'); + expect(nativePart.request).to.not.equal(null); + // native request assets + const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request); + expect(nativeRequest).to.not.equal(null); + expect(nativeRequest.assets).to.have.lengthOf(3); + // title asset + expect(nativeRequest.assets[0].id).to.equal(1); + expect(nativeRequest.assets[0].required).to.equal(1); + expect(nativeRequest.assets[0].title).to.not.equal(null); + expect(nativeRequest.assets[0].title.len).to.equal(200); + // data asset + expect(nativeRequest.assets[1].id).to.equal(2); + expect(nativeRequest.assets[1].required).to.equal(0); + expect(nativeRequest.assets[1].title).to.be.undefined; + expect(nativeRequest.assets[1].data).to.not.equal(null); + expect(nativeRequest.assets[1].data.type).to.equal(1); + expect(nativeRequest.assets[1].data.len).to.equal(50); + // image asset + expect(nativeRequest.assets[2].id).to.equal(3); + expect(nativeRequest.assets[2].required).to.equal(0); + expect(nativeRequest.assets[2].title).to.be.undefined; + expect(nativeRequest.assets[2].img).to.not.equal(null); + expect(nativeRequest.assets[2].img.wmin).to.equal(100); + expect(nativeRequest.assets[2].img.hmin).to.equal(150); + expect(nativeRequest.assets[2].img.type).to.equal(3); }); - it('Verify bid', () => { - responses['t10000'] = { - html: 'This is an Ad', - bidCpm: 1.25 + it('Verify Native response', () => { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + const nativeResponse = { + 'native': { + assets: [ + { title: { text: 'Ad Title'} }, + { data: { type: 1, value: 'Sponsored By: Brand' }}, + { img: { type: 3, url: 'http://images.cdn.brand.com/123' } } + ], + link: { url: 'http://brand.clickme.com/' }, + imptrackers: ['http://imp1.trackme.com/', 'http://imp1.contextweb.com/'] + } + }; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: JSON.stringify(nativeResponse) + }] + }] }; - pulsepointAdapter.callBids(slotConfigs); - let placement = bidManager.addBidResponse.firstCall.args[0]; - let bid = bidManager.addBidResponse.firstCall.args[1]; - expect(placement).to.equal('/DfpAccount1/slot1'); - expect(bid.bidderCode).to.equal('pulsepoint'); + const bids = spec.interpretResponse({ body: ortbResponse }, request); + // verify bid + const bid = bids[0]; expect(bid.cpm).to.equal(1.25); - 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.ad).to.be.undefined; + expect(bid.mediaType).to.equal('native'); + const nativeBid = bid['native']; + expect(nativeBid).to.not.equal(null); + expect(nativeBid.title).to.equal('Ad Title'); + expect(nativeBid.sponsoredBy).to.equal('Sponsored By: Brand'); + expect(nativeBid.image).to.equal('http://images.cdn.brand.com/123'); + expect(nativeBid.clickUrl).to.equal(encodeURIComponent('http://brand.clickme.com/')); + expect(nativeBid.impressionTrackers).to.have.lengthOf(2); + expect(nativeBid.impressionTrackers[0]).to.equal('http://imp1.trackme.com/'); + expect(nativeBid.impressionTrackers[1]).to.equal('http://imp1.contextweb.com/'); }); - it('Verify passback', () => { - pulsepointAdapter.callBids(slotConfigs); - let placement = bidManager.addBidResponse.firstCall.args[0]; - let bid = bidManager.addBidResponse.firstCall.args[1]; - expect(placement).to.equal('/DfpAccount1/slot1'); - expect(bid.bidderCode).to.equal('pulsepoint'); - expect(bid).to.not.have.property('ad'); - expect(bid).to.not.have.property('cpm'); - expect(bid.adId).to.equal('bid12345'); + it('Verifies bidder code', () => { + expect(spec.code).to.equal('pulsepoint'); }); - it('Verify PulsePoint library is downloaded if nessesary', () => { - resetPulsepointLib(); - pulsepointAdapter.callBids(slotConfigs); - let libraryLoadCall = adLoader.loadScript.firstCall.args[0]; - let callback = adLoader.loadScript.firstCall.args[1]; - expect(libraryLoadCall).to.equal('http://tag-st.contextweb.com/getjs.static.js'); - expect(callback).to.be.a('function'); + it('Verifies bidder aliases', () => { + expect(spec.aliases).to.have.lengthOf(2); + expect(spec.aliases[0]).to.equal('pulseLite'); + expect(spec.aliases[1]).to.equal('pulsepointLite'); }); - it('Verify Bids get processed after PulsePoint library downloads', () => { - resetPulsepointLib(); - pulsepointAdapter.callBids(slotConfigs); - let callback = adLoader.loadScript.firstCall.args[1]; - let bidCall = bidManager.addBidResponse.firstCall; - expect(callback).to.be.a('function'); - expect(bidCall).to.be.a('null'); - // the library load should initialize pulsepoint lib - initPulsepointLib(); - callback(); - expect(requests.length).to.equal(2); - bidCall = bidManager.addBidResponse.firstCall; - expect(bidCall).to.be.a('object'); - expect(bidCall.args[0]).to.equal('/DfpAccount1/slot1'); - expect(bidCall.args[1]).to.be.a('object'); + it('Verifies supported media types', () => { + expect(spec.supportedMediaTypes).to.have.lengthOf(1); + expect(spec.supportedMediaTypes[0]).to.equal('native'); }); - // related to issue https://github.com/prebid/Prebid.js/issues/866 - it('Verify Passbacks when window.pp is not available', () => { - window.pp = function() {}; - pulsepointAdapter.callBids(slotConfigs); - let placement = bidManager.addBidResponse.firstCall.args[0]; - let bid = bidManager.addBidResponse.firstCall.args[1]; - // verify that we passed back without exceptions, should window.pp be already taken. - expect(placement).to.equal('/DfpAccount1/slot1'); - expect(bid.bidderCode).to.equal('pulsepoint'); - expect(bid).to.not.have.property('ad'); - expect(bid).to.not.have.property('cpm'); - expect(bid.adId).to.equal('bid12345'); + it('Verifies if bid request valid', () => { + expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); + expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); + expect(spec.isBidRequestValid(nativeSlotConfig[0])).to.equal(true); + expect(spec.isBidRequestValid({})).to.equal(false); + expect(spec.isBidRequestValid({ params: {} })).to.equal(false); + expect(spec.isBidRequestValid({ params: { ct: 123 } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { cp: 123 } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { ct: 123, cp: 234 }})).to.equal(true); + }); + + it('Verifies sync options', () => { + expect(spec.getUserSyncs({})).to.be.undefined; + expect(spec.getUserSyncs({ iframeEnabled: false})).to.be.undefined; + const options = spec.getUserSyncs({ iframeEnabled: true}); + expect(options).to.not.be.undefined; + expect(options).to.have.lengthOf(1); + expect(options[0].type).to.equal('iframe'); + expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch'); + }); + + it('Verifies image pixel sync', () => { + const options = spec.getUserSyncs({ pixelEnabled: true}); + expect(options).to.not.be.undefined; + expect(options).to.have.lengthOf(1); + expect(options[0].type).to.equal('image'); + expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch/prebid'); + }); + + it('Verify app requests', () => { + const request = spec.buildRequests(appSlotConfig); + const ortbRequest = JSON.parse(request.data); + // site object + expect(ortbRequest.site).to.equal(null); + expect(ortbRequest.app).to.not.be.null; + expect(ortbRequest.app.publisher).to.not.equal(null); + expect(ortbRequest.app.publisher.id).to.equal('p10000'); + expect(ortbRequest.app.bundle).to.equal('com.pulsepoint.apps'); + expect(ortbRequest.app.storeurl).to.equal('http://pulsepoint.com/apps'); + expect(ortbRequest.app.domain).to.equal('pulsepoint.com'); }); }); diff --git a/test/spec/modules/pulsepointLiteBidAdapter_spec.js b/test/spec/modules/pulsepointLiteBidAdapter_spec.js deleted file mode 100644 index 2c6f5f0681f..00000000000 --- a/test/spec/modules/pulsepointLiteBidAdapter_spec.js +++ /dev/null @@ -1,276 +0,0 @@ -/* eslint dot-notation:0, quote-props:0 */ -import {expect} from 'chai'; -import {spec} from 'modules/pulsepointLiteBidAdapter'; -import bidManager from 'src/bidmanager'; -import {getTopWindowLocation} from 'src/utils'; -import {newBidder} from 'src/adapters/bidderFactory'; - -describe('PulsePoint Lite Adapter Tests', () => { - const slotConfigs = [{ - placementCode: '/DfpAccount1/slot1', - bidId: 'bid12345', - params: { - cp: 'p10000', - ct: 't10000', - cf: '300x250' - } - }, { - placementCode: '/DfpAccount2/slot2', - bidId: 'bid23456', - params: { - cp: 'p10000', - ct: 't20000', - cf: '728x90' - } - }]; - const nativeSlotConfig = [{ - placementCode: '/DfpAccount1/slot3', - bidId: 'bid12345', - nativeParams: { - title: { required: true, len: 200 }, - image: { wmin: 100 }, - sponsoredBy: { } - }, - params: { - cp: 'p10000', - ct: 't10000' - } - }]; - const appSlotConfig = [{ - placementCode: '/DfpAccount1/slot3', - bidId: 'bid12345', - params: { - cp: 'p10000', - ct: 't10000', - app: { - bundle: 'com.pulsepoint.apps', - storeUrl: 'http://pulsepoint.com/apps', - domain: 'pulsepoint.com', - } - } - }]; - - it('Verify build request', () => { - const request = spec.buildRequests(slotConfigs); - expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - // site object - expect(ortbRequest.site).to.not.equal(null); - expect(ortbRequest.site.publisher).to.not.equal(null); - expect(ortbRequest.site.publisher.id).to.equal('p10000'); - expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); - expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); - expect(ortbRequest.imp).to.have.lengthOf(2); - // device object - expect(ortbRequest.device).to.not.equal(null); - expect(ortbRequest.device.ua).to.equal(navigator.userAgent); - // slot 1 - expect(ortbRequest.imp[0].tagid).to.equal('t10000'); - 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); - // slot 2 - expect(ortbRequest.imp[1].tagid).to.equal('t20000'); - expect(ortbRequest.imp[1].banner).to.not.equal(null); - expect(ortbRequest.imp[1].banner.w).to.equal(728); - expect(ortbRequest.imp[1].banner.h).to.equal(90); - }); - - it('Verify parse response', () => { - 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' - }] - }] - }; - const bids = spec.interpretResponse({ body: ortbResponse }, request); - expect(bids).to.have.lengthOf(1); - // verify first bid - const bid = bids[0]; - expect(bid.cpm).to.equal(1.25); - 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.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', () => { - const request = spec.buildRequests(slotConfigs); - const bids = spec.interpretResponse({ body: null }, request) - expect(bids).to.have.lengthOf(0); - }); - - it('Verify Native request', () => { - const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - // native impression - expect(ortbRequest.imp[0].tagid).to.equal('t10000'); - expect(ortbRequest.imp[0].banner).to.equal(null); - const nativePart = ortbRequest.imp[0]['native']; - expect(nativePart).to.not.equal(null); - expect(nativePart.ver).to.equal('1.1'); - expect(nativePart.request).to.not.equal(null); - // native request assets - const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request); - expect(nativeRequest).to.not.equal(null); - expect(nativeRequest.assets).to.have.lengthOf(3); - // title asset - expect(nativeRequest.assets[0].id).to.equal(1); - expect(nativeRequest.assets[0].required).to.equal(1); - expect(nativeRequest.assets[0].title).to.not.equal(null); - expect(nativeRequest.assets[0].title.len).to.equal(200); - // data asset - expect(nativeRequest.assets[1].id).to.equal(2); - expect(nativeRequest.assets[1].required).to.equal(0); - expect(nativeRequest.assets[1].title).to.be.undefined; - expect(nativeRequest.assets[1].data).to.not.equal(null); - expect(nativeRequest.assets[1].data.type).to.equal(1); - expect(nativeRequest.assets[1].data.len).to.equal(50); - // image asset - expect(nativeRequest.assets[2].id).to.equal(3); - expect(nativeRequest.assets[2].required).to.equal(0); - expect(nativeRequest.assets[2].title).to.be.undefined; - expect(nativeRequest.assets[2].img).to.not.equal(null); - expect(nativeRequest.assets[2].img.wmin).to.equal(100); - expect(nativeRequest.assets[2].img.hmin).to.equal(150); - expect(nativeRequest.assets[2].img.type).to.equal(3); - }); - - it('Verify Native response', () => { - const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - const nativeResponse = { - 'native': { - assets: [ - { title: { text: 'Ad Title'} }, - { data: { type: 1, value: 'Sponsored By: Brand' }}, - { img: { type: 3, url: 'http://images.cdn.brand.com/123' } } - ], - link: { url: 'http://brand.clickme.com/' }, - imptrackers: ['http://imp1.trackme.com/', 'http://imp1.contextweb.com/'] - } - }; - const ortbResponse = { - seatbid: [{ - bid: [{ - impid: ortbRequest.imp[0].id, - price: 1.25, - adm: JSON.stringify(nativeResponse) - }] - }] - }; - const bids = spec.interpretResponse({ body: ortbResponse }, request); - // verify bid - const bid = bids[0]; - expect(bid.cpm).to.equal(1.25); - expect(bid.adId).to.equal('bid12345'); - expect(bid.ad).to.be.undefined; - expect(bid.mediaType).to.equal('native'); - const nativeBid = bid['native']; - expect(nativeBid).to.not.equal(null); - expect(nativeBid.title).to.equal('Ad Title'); - expect(nativeBid.sponsoredBy).to.equal('Sponsored By: Brand'); - expect(nativeBid.image).to.equal('http://images.cdn.brand.com/123'); - expect(nativeBid.clickUrl).to.equal(encodeURIComponent('http://brand.clickme.com/')); - expect(nativeBid.impressionTrackers).to.have.lengthOf(2); - expect(nativeBid.impressionTrackers[0]).to.equal('http://imp1.trackme.com/'); - expect(nativeBid.impressionTrackers[1]).to.equal('http://imp1.contextweb.com/'); - }); - - it('Verifies bidder code', () => { - expect(spec.code).to.equal('pulseLite'); - }); - - it('Verifies bidder aliases', () => { - expect(spec.aliases).to.have.lengthOf(1); - expect(spec.aliases[0]).to.equal('pulsepointLite'); - }); - - it('Verifies supported media types', () => { - expect(spec.supportedMediaTypes).to.have.lengthOf(1); - expect(spec.supportedMediaTypes[0]).to.equal('native'); - }); - - it('Verifies if bid request valid', () => { - expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); - expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); - expect(spec.isBidRequestValid(nativeSlotConfig[0])).to.equal(true); - expect(spec.isBidRequestValid({})).to.equal(false); - expect(spec.isBidRequestValid({ params: {} })).to.equal(false); - expect(spec.isBidRequestValid({ params: { ct: 123 } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { cp: 123 } })).to.equal(false); - expect(spec.isBidRequestValid({ params: { ct: 123, cp: 234 }})).to.equal(true); - }); - - it('Verifies sync options', () => { - expect(spec.getUserSyncs({})).to.be.undefined; - expect(spec.getUserSyncs({ iframeEnabled: false})).to.be.undefined; - const options = spec.getUserSyncs({ iframeEnabled: true}); - expect(options).to.not.be.undefined; - expect(options).to.have.lengthOf(1); - expect(options[0].type).to.equal('iframe'); - expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch'); - }); - - it('Verifies image pixel sync', () => { - const options = spec.getUserSyncs({ pixelEnabled: true}); - expect(options).to.not.be.undefined; - expect(options).to.have.lengthOf(1); - expect(options[0].type).to.equal('image'); - expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch/prebid'); - }); - - it('Verify app requests', () => { - const request = spec.buildRequests(appSlotConfig); - const ortbRequest = JSON.parse(request.data); - // site object - expect(ortbRequest.site).to.equal(null); - expect(ortbRequest.app).to.not.be.null; - expect(ortbRequest.app.publisher).to.not.equal(null); - expect(ortbRequest.app.publisher.id).to.equal('p10000'); - expect(ortbRequest.app.bundle).to.equal('com.pulsepoint.apps'); - expect(ortbRequest.app.storeurl).to.equal('http://pulsepoint.com/apps'); - expect(ortbRequest.app.domain).to.equal('pulsepoint.com'); - }); -}); diff --git a/test/spec/modules/realvuBidAdapter_spec.js b/test/spec/modules/realvuBidAdapter_spec.js deleted file mode 100644 index 36517fa723e..00000000000 --- a/test/spec/modules/realvuBidAdapter_spec.js +++ /dev/null @@ -1,61 +0,0 @@ -import {expect} from 'chai'; -import RealVuAdapter from '../../../modules/realvuBidAdapter'; -import bidmanager from '../../../src/bidmanager'; -import adloader from '../../../src/adloader'; - -describe('RealVu Adapter Test', () => { - let adapter; - - const REQUEST = { - bidderCode: 'realvu', - requestId: '0d67ddab-1502-4897-a7bf-e8078e983405', - bidderRequestId: '1b5e314fe79b1d', - bids: [ - { - bidId: '2d86a04312d95d', - bidder: 'realvu', - bidderRequestId: '1b5e314fe79b1d', - // mediaType:undefined, - params: { - partnerId: '1Y', - placementId: '9339508', - }, - placementCode: 'ad_container_1', - // renderer:undefined, - sizes: [[300, 250]], - transactionId: '0d67ddab-1502-4897-a7bf-e8078e983405' - } - ], - start: 1504628062271 - }; - - var bidResponseStub; - var adloaderStub; - - beforeEach(function() { - bidResponseStub = sinon.stub(bidmanager, 'addBidResponse'); - adloaderStub = sinon.stub(adloader, 'loadScript'); - }); - - afterEach(function() { - adloaderStub.restore(); - bidResponseStub.restore(); - }); - - adapter = new RealVuAdapter(); - - it('load boost', () => { - adapter.callBids(REQUEST); - expect(adloaderStub.getCall(0).args[0]).to.contain('realvu_boost.js'); - }); - - it('callBid "yes"', () => { - adapter.boostCall({realvu: 'yes', pin: {pbjs_bid: REQUEST.bids[0]}}); - expect(adloaderStub.getCall(0).args[0]).to.contain('id=9339508'); - }); - - it('callBid "no"', () => { - adapter.boostCall({realvu: 'no', pin: {pbjs_bid: REQUEST.bids[0]}}); - expect(bidResponseStub.getCall(0).args[1].getStatusCode()).to.equal(2); - }); -}); diff --git a/test/spec/modules/roxotBidAdapter_spec.js b/test/spec/modules/roxotBidAdapter_spec.js deleted file mode 100644 index af7bef291e1..00000000000 --- a/test/spec/modules/roxotBidAdapter_spec.js +++ /dev/null @@ -1,123 +0,0 @@ -describe('Roxot adapter tests', function() { - const expect = require('chai').expect; - const adapter = require('modules/roxotBidAdapter'); - const bidmanager = require('src/bidmanager'); - - describe('roxotResponseHandler', function () { - it('should exist and be a function', function () { - expect($$PREBID_GLOBAL$$.roxotResponseHandler).to.exist.and.to.be.a('function'); - }); - - it('should add empty bid responses if no bids returned', function () { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - var bidderRequest = { - bidderCode: 'roxot', - bids: [ - { - bidId: 'id1', - bidder: 'roxot', - sizes: [[320, 50]], - placementCode: 'div-gpt-ad-12345-1' - }, - { - bidId: 'id2', - bidder: 'roxot', - sizes: [[320, 50]], - placementCode: 'div-gpt-ad-12345-2' - }, - ] - }; - - // no bids returned in the response. - var response = { - 'id': '123', - 'bids': [] - }; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // adapter needs to be called, in order for the stub to register. - adapter(); - - $$PREBID_GLOBAL$$.roxotResponseHandler(response); - - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - var bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0]; - var bidObject2 = stubAddBidResponse.getCall(1).args[1]; - - expect(bidPlacementCode1).to.equal('div-gpt-ad-12345-1'); - expect(bidObject1.getStatusCode()).to.equal(2); - expect(bidObject1.bidderCode).to.equal('roxot'); - - expect(bidPlacementCode2).to.equal('div-gpt-ad-12345-2'); - expect(bidObject2.getStatusCode()).to.equal(2); - expect(bidObject2.bidderCode).to.equal('roxot'); - - stubAddBidResponse.restore(); - }); - - it('should add a bid response for bids returned and empty bid responses for the rest', () => { - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - var bidderRequest = { - bidderCode: 'roxot', - bids: [ - { - bidId: 'id1', - bidder: 'roxot', - sizes: [[320, 50]], - placementCode: 'div-gpt-ad-12345-1' - }, - { - bidId: 'id2', - bidder: 'roxot', - sizes: [[320, 50]], - placementCode: 'div-gpt-ad-12345-2' - }, - ] - }; - - // Returning a single bid in the response. - var response = { - 'id': '12345', - 'bids': [ - { - 'bidId': 'id1', - 'cpm': 0.09, - 'nurl': 'http://roxot.example.com', - 'adm': '<>', - 'h': 320, - 'w': 50 - } - ]}; - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // adapter needs to be called, in order for the stub to register. - adapter(); - - $$PREBID_GLOBAL$$.roxotResponseHandler(response); - - var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - var bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0]; - var bidObject2 = stubAddBidResponse.getCall(1).args[1]; - - expect(bidPlacementCode1).to.equal('div-gpt-ad-12345-1'); - expect(bidObject1.getStatusCode()).to.equal(1); - expect(bidObject1.bidderCode).to.equal('roxot'); - expect(bidObject1.cpm).to.equal(0.09); - expect(bidObject1.height).to.equal(320); - expect(bidObject1.width).to.equal(50); - expect(bidObject1.ad).to.equal('<>'); - - expect(bidPlacementCode2).to.equal('div-gpt-ad-12345-2'); - expect(bidObject2.getStatusCode()).to.equal(2); - expect(bidObject2.bidderCode).to.equal('roxot'); - - stubAddBidResponse.restore(); - }); - }); -}); diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 52a87f6397f..49c0dd9011e 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -145,7 +145,7 @@ describe('the rubicon adapter', () => { 'rp_secure': /[01]/, 'rand': '0.1', 'tk_flint': INTEGRATION, - 'tid': 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', + 'x_source.tid': 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', 'p_screen_res': /\d+x\d+/, 'tk_user_key': '12346', 'kw': 'a,b,c', @@ -451,6 +451,7 @@ describe('the rubicon adapter', () => { expect(post.resolution).to.match(/\d+x\d+/); expect(post.account_id).to.equal('14062'); expect(post.integration).to.equal(INTEGRATION); + expect(post['x_source.tid']).to.equal('d45dd707-a418-42ec-b8a7-b70a6c6fab0b'); expect(post).to.have.property('timeout').that.is.a('number'); expect(post.timeout < 5000).to.equal(true); expect(post.stash_creatives).to.equal(true); diff --git a/test/spec/modules/s2sTesting_spec.js b/test/spec/modules/s2sTesting_spec.js index 4ddd7278f4e..26d5eb8884b 100644 --- a/test/spec/modules/s2sTesting_spec.js +++ b/test/spec/modules/s2sTesting_spec.js @@ -1,5 +1,6 @@ import { getSourceBidderMap, calculateBidSources, getSource } from 'modules/s2sTesting'; import { config } from 'src/config'; +import find from 'core-js/library/fn/array/find'; var events = require('src/events'); var CONSTANTS = require('src/constants.json'); @@ -326,7 +327,7 @@ describe('s2sTesting', function () { expect(targeting).to.be.undefined; return; } - expect(targeting.find((kvp) => { + expect(find(targeting, (kvp) => { return kvp.key === `hb_source_${bidder}`; })).to.be.undefined; } diff --git a/test/spec/modules/sharethroughAnalyticsAdapter_spec.js b/test/spec/modules/sharethroughAnalyticsAdapter_spec.js deleted file mode 100644 index 8968e0461fb..00000000000 --- a/test/spec/modules/sharethroughAnalyticsAdapter_spec.js +++ /dev/null @@ -1,90 +0,0 @@ -import sharethroughAnalytics from 'modules/sharethroughAnalyticsAdapter'; -import { expect } from 'chai'; - -describe('sharethrough analytics adapter', () => { - let sandbox; - - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('track', () => { - describe('when event type is bidRequested', () => { - beforeEach(() => { - let eventType = 'bidRequested'; - let args = {'bidderCode': 'sharethrough', 'bids': {'0': {'placementCode': 'fake placement Code'}}}; - sharethroughAnalytics.track({eventType, args}) - }); - - it('placementCodeSet contains a value', () => { - expect(sharethroughAnalytics.placementCodeSet['fake placement Code'] == undefined).to.equal(false) - }); - }); - }); - - describe('bid won handler', () => { - let fireLoseBeaconStub; - - beforeEach(() => { - fireLoseBeaconStub = sandbox.stub(sharethroughAnalytics, 'fireLoseBeacon'); - }); - - describe('when bidderCode is not sharethrough and sharethrough is in bid', () => { - beforeEach(() => { - sharethroughAnalytics.placementCodeSet['div-gpt-ad-1460505748561-0'] = {'adserverRequestId': '0eca470d-fcac-48e6-845a-c86483ccaa0c'} - var args = { - 'bidderCode': 'someoneelse', - 'width': 600, - 'height': 300, - 'statusMessage': 'Bid available', - 'adId': '23fbe93a90c924', - 'cpm': 3.984986853301525, - 'adserverRequestId': '0eca470d-fcac-48e6-845a-c86483ccaa0c', - 'winId': '1c404469-f7bb-4e50-b6f6-a8eaf0808999', - 'pkey': 'xKcxTTHyndFyVx7T8GKSzxPE', - 'ad': '
', - 'requestId': 'dd2420bd-cdc2-4c66-8479-f3499ece73da', - 'responseTimestamp': 1473983655565, - 'requestTimestamp': 1473983655458, - 'bidder': 'sharethrough', - 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'timeToRespond': 107, - 'pbLg': '3.50', - 'pbMg': '3.90', - 'pbHg': '3.98', - 'pbAg': '3.95', - 'pbDg': '3.95', - 'size': '600x300', - 'adserverTargeting': { - 'hb_bidder': 'sharethrough', - 'hb_adid': '23fbe93a90c924', - 'hb_pb': '3.90', - 'hb_size': '600x300' - } - }; - - sharethroughAnalytics.bidWon(args); - }); - - it('should fire lose beacon', () => { - sinon.assert.calledOnce(fireLoseBeaconStub); - }); - }); - }); - - describe('lose beacon is fired', () => { - beforeEach(() => { - sandbox.stub(sharethroughAnalytics, 'fireBeacon'); - sharethroughAnalytics.fireLoseBeacon('someoneelse', 10.0, 'arid', 'losebeacontype'); - }); - - it('should call correct url', () => { - let winUrl = sharethroughAnalytics.fireBeacon.firstCall.args[0]; - expect(winUrl).to.contain(sharethroughAnalytics.STR_BEACON_HOST + 'winnerBidderCode=someoneelse&winnerCpm=10&arid=arid&type=losebeacontype&hbVersion=%24prebid.version%24&strVersion=0.1.0&hbSource=prebid&'); - }); - }); -}); diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js deleted file mode 100644 index bfb89cf4ead..00000000000 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ /dev/null @@ -1,154 +0,0 @@ -describe('smartadserver adapter tests', function () { - var urlParse = require('url-parse'); - var querystringify = require('querystringify'); - var adapter = require('modules/smartadserverBidAdapter'); - var adLoader = require('src/adloader'); - var expect = require('chai').expect; - var bidmanager = require('src/bidmanager'); - var CONSTANTS = require('src/constants.json'); - - var DEFAULT_PARAMS = { - bidderCode: 'smartadserver', - bids: [{ - bidId: 'abcd1234', - sizes: [[300, 250], [300, 200]], - bidder: 'smartadserver', - params: { - domain: 'http://www.smartadserver.com', - siteId: '1234', - pageId: '5678', - formatId: '90', - target: 'test=prebid', - currency: 'EUR', - bidfloor: 0.420 - }, - requestId: 'efgh5678', - placementCode: 'sas_42' - } - ] - }; - - var DEFAULT_PARAMS_WO_OPTIONAL = { - bidderCode: 'smartadserver', - bids: [{ - bidId: 'abcd1234', - sizes: [[300, 250], [300, 200]], - bidder: 'smartadserver', - params: { - domain: 'http://www.smartadserver.com', - siteId: '1234', - pageId: '5678', - formatId: '90' - }, - requestId: 'efgh5678', - placementCode: 'sas_42' - } - ] - }; - - var BID_RESPONSE = { - cpm: 0.42, - ad: 'fake ad content', - width: 300, - height: 250 - }; - - it('set url parameters', function () { - var stubLoadScript = sinon.stub(adLoader, 'loadScript'); - - adapter().callBids(DEFAULT_PARAMS); - - var smartCallback; - for (var k in $$PREBID_GLOBAL$$) { - if (k.lastIndexOf('sas_', 0) === 0) { - smartCallback = k; - break; - } - } - - var bidUrl = stubLoadScript.getCall(0).args[0]; - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - 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('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'); - expect(parsedBidUrlQueryString).to.have.property('tgt').and.to.equal('test=prebid'); - expect(parsedBidUrlQueryString).to.have.property('ccy').and.to.equal('EUR'); - expect(parsedBidUrlQueryString).to.have.property('bidfloor').and.to.equal('0.42'); - expect(parsedBidUrlQueryString).to.have.property('tag').and.to.equal('sas_42'); - expect(parsedBidUrlQueryString).to.have.property('sizes').and.to.equal('300x250,300x200'); - expect(parsedBidUrlQueryString).to.have.property('async').and.to.equal('1'); - - stubLoadScript.restore(); - }); - - it('test optional parameters default value', function () { - var stubLoadScript = sinon.stub(adLoader, 'loadScript'); - - adapter().callBids(DEFAULT_PARAMS_WO_OPTIONAL); - - var bidUrl = stubLoadScript.getCall(0).args[0]; - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - expect(parsedBidUrlQueryString).to.have.property('tgt').and.to.equal(''); - expect(parsedBidUrlQueryString).to.have.property('ccy').and.to.equal('USD'); - - stubLoadScript.restore(); - }); - - it('creates an empty bid response if no bids', function() { - var stubLoadScript = sinon.stub(adLoader, 'loadScript', function(url) { - var bidUrl = stubLoadScript.getCall(0).args[0]; - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - $$PREBID_GLOBAL$$[parsedBidUrlQueryString.pbjscbk.split('.')[1]](null); - }); - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - adapter().callBids(DEFAULT_PARAMS); - - var bidResponsePlacementCode = stubAddBidResponse.getCall(0).args[0]; - var bidResponseAd = stubAddBidResponse.getCall(0).args[1]; - - expect(bidResponsePlacementCode).to.equal(DEFAULT_PARAMS.bids[0].placementCode); - expect(bidResponseAd.getStatusCode()).to.equal(CONSTANTS.STATUS.NO_BID); - expect(bidResponseAd).to.have.property('bidderCode').and.to.equal('smartadserver'); - - stubLoadScript.restore(); - stubAddBidResponse.restore(); - }); - - it('creates a bid response if bid is returned', function() { - var stubLoadScript = sinon.stub(adLoader, 'loadScript', function(url) { - var bidUrl = stubLoadScript.getCall(0).args[0]; - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - $$PREBID_GLOBAL$$[parsedBidUrlQueryString.pbjscbk.split('.')[1]](BID_RESPONSE); - }); - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - adapter().callBids(DEFAULT_PARAMS); - - var bidResponsePlacementCode = stubAddBidResponse.getCall(0).args[0]; - var bidResponseAd = stubAddBidResponse.getCall(0).args[1]; - - expect(bidResponsePlacementCode).to.equal(DEFAULT_PARAMS.bids[0].placementCode); - expect(bidResponseAd.getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bidResponseAd).to.have.property('bidderCode').and.to.equal('smartadserver'); - expect(bidResponseAd).to.have.property('cpm').and.to.equal(BID_RESPONSE.cpm); - expect(bidResponseAd).to.have.property('ad').and.to.equal(BID_RESPONSE.ad); - expect(bidResponseAd).to.have.property('width').and.to.equal(BID_RESPONSE.width); - expect(bidResponseAd).to.have.property('height').and.to.equal(BID_RESPONSE.height); - - stubLoadScript.restore(); - stubAddBidResponse.restore(); - }); -}); diff --git a/test/spec/modules/smartyadsBidAdapter_spec.js b/test/spec/modules/smartyadsBidAdapter_spec.js deleted file mode 100644 index d7c723604a6..00000000000 --- a/test/spec/modules/smartyadsBidAdapter_spec.js +++ /dev/null @@ -1,128 +0,0 @@ -import { expect } from 'chai'; -import Adapter from '../../../modules/smartyadsBidAdapter'; -import adapterManager from 'src/adaptermanager'; -import bidManager from 'src/bidmanager'; -import CONSTANTS from 'src/constants.json'; - -describe('Smartyads adapter tests', function () { - let sandbox; - const adUnit = { // TODO CHANGE - code: 'smartyads', - sizes: [[300, 250], [300, 600], [320, 80]], - bids: [{ - bidder: 'smartyads', - params: { - banner_id: 0 - } - }] - }; - - const response = { - ad_id: 0, - adm: 'Test Response', - cpm: 0.5, - deal: 'bf063e2e025c', - height: 240, - width: 360 - }; - - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('Smartyads callBids validation', () => { - let bids, - server; - - beforeEach(() => { - bids = []; - server = sinon.fakeServer.create(); - - sandbox.stub(bidManager, 'addBidResponse', (elemId, bid) => { - bids.push(bid); - }); - }); - - afterEach(() => { - server.restore(); - }); - - let adapter = adapterManager.bidderRegistry['smartyads']; - - it('Valid bid-request', () => { - sandbox.stub(adapter, 'callBids'); - adapterManager.callBids({ - adUnits: [clone(adUnit)] - }); - - let bidderRequest = adapter.callBids.getCall(0).args[0]; - - expect(bidderRequest).to.have.property('bids') - .that.is.an('array') - .with.lengthOf(1); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .to.have.property('bidder', 'smartyads'); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('sizes') - .that.is.an('array') - .with.lengthOf(3) - .that.deep.equals(adUnit.sizes); - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('params') - .to.have.property('banner_id', 0); - }); - - it('Valid bid-response', () => { - server.respondWith(JSON.stringify( - response - )); - adapterManager.callBids({ - adUnits: [clone(adUnit)] - }); - server.respond(); - - expect(bids).to.be.lengthOf(1); - expect(bids[0].getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bids[0].bidderCode).to.equal('smartyads'); - expect(bids[0].width).to.equal(360); - expect(bids[0].height).to.equal(240); - expect(bids[0].cpm).to.equal(0.5); - expect(bids[0].dealId).to.equal('bf063e2e025c'); - }); - }); - - describe('MAS mapping / ordering', () => { - let masSizeOrdering = Adapter.masSizeOrdering; - - it('should not include values without a proper mapping', () => { - let ordering = masSizeOrdering([[320, 50], [42, 42], [300, 250], [640, 480], [1, 1], [336, 280]]); - expect(ordering).to.deep.equal([15, 16, 43, 65]); - }); - - it('should sort values without any MAS priority sizes in regular ascending order', () => { - let ordering = masSizeOrdering([[320, 50], [640, 480], [336, 280], [200, 600]]); - expect(ordering).to.deep.equal([16, 43, 65, 126]); - }); - - it('should sort MAS priority sizes in the proper order w/ rest ascending', () => { - let ordering = masSizeOrdering([[320, 50], [160, 600], [640, 480], [300, 250], [336, 280], [200, 600]]); - expect(ordering).to.deep.equal([15, 9, 16, 43, 65, 126]); - - ordering = masSizeOrdering([[320, 50], [300, 250], [160, 600], [640, 480], [336, 280], [200, 600], [728, 90]]); - expect(ordering).to.deep.equal([15, 2, 9, 16, 43, 65, 126]); - - ordering = masSizeOrdering([[120, 600], [320, 50], [160, 600], [640, 480], [336, 280], [200, 600], [728, 90]]); - expect(ordering).to.deep.equal([2, 9, 8, 16, 43, 65, 126]); - }) - }); -}); - -function clone(obj) { - return JSON.parse(JSON.stringify(obj)); -} diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js deleted file mode 100644 index 346fc18e637..00000000000 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ /dev/null @@ -1,389 +0,0 @@ -const chai = require('chai'); -const expect = require('chai').expect; -const Adapter = require('modules/sonobiBidAdapter'); -const bidManager = require('src/bidmanager'); -const adLoader = require('src/adloader'); -const utils = require('src/utils'); - -chai.config.includeStack = true; - -describe('Sonobi adapter tests', () => { - // Declared each explicitely so we can loop through and observe each test - const adUnit_p = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_p', - sizes: [[300, 250], [300, 600]], - params: { - placement_id: '1a2b3c4d5e6f1a2b3c4d' - } - }] - }; - const adUnit_pd = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_pd', - sizes: [[300, 250], [300, 600]], - params: { - placement_id: '1a2b3c4d5e6f1a2b3c4d', - dom_id: 'div-gpt-ad-12345-0' - } - }] - }; - const adUnit_pdf = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_pdf', - sizes: [[300, 250], [300, 600]], - params: { - placement_id: '1a2b3c4d5e6f1a2b3c4d', - dom_id: 'div-gpt-ad-12345-0', - floor: '1' - } - }] - }; - const adUnit_a = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_a', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '/7780971/sparks_prebid_MR', - } - }] - }; - - const adUnit_as = { - code: 'sbi_s', - sizes: [[120, 600], [300, 600], [160, 600]], - bids: [{ - bidder: 'sonobi', - params: { - ad_unit: '/7780971/sparks_prebid_LB', - sizes: [[300, 250], [300, 600]] - } - }] - }; - - const adUnit_ad = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_ad', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '/7780971/sparks_prebid_MR', - dom_id: 'div-gpt-ad-12345-0' - } - }] - }; - const adUnit_af = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_af', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '/7780971/sparks_prebid_MR', - floor: '1' - } - }] - }; - const adUnit_adf = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_adf', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '/7780971/sparks_prebid_MR', - dom_id: 'div-gpt-ad-12345-0', - floor: '1' - } - }] - }; - const adUnit_A = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_A', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '/7780971/sparks_prebid_MR', - } - }] - }; - const adUnit_Ad = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_Ad', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '7780971/sparks_prebid_MR', - dom_id: 'div-gpt-ad-12345-0' - } - }] - }; - const adUnit_Af = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_Af', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '7780971/sparks_prebid_MR', - floor: '1' - } - }] - }; - const adUnit_Adf = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_Adf', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '7780971/sparks_prebid_MR', - dom_id: 'div-gpt-ad-12345-0', - floor: '1' - } - }] - }; - // You guys surprise me all the time new and exciting ways to break this simple adapter. - const adUnit_m1hb = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_m1hb', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '1a2b3c4d5e6f1a2b3c4d', - dom_id: 'div-gpt-ad-12345-0' - } - }] - }; - const adUnit_m2hb = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_m2hb', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '/7780971/sparks_prebid_MR', - placement_id: 'OPTIONAL', - dom_id: 'div-gpt-ad-12345-0', - } - }] - }; - const adUnit_m3hb = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_m3hb', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '/7780971/sparks_prebid_MR', - placement_id: '', - dom_id: 'div-gpt-ad-12345-0', - } - }] - }; - const adUnit_m4hb = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_m4hb', - sizes: [[300, 250], [300, 600]], - params: { - ad_unit: '', - placement_id: '1a2b3c4d5e6f1a2b3c4d', - dom_id: 'div-gpt-ad-12345-0' - } - }] - }; - const adUnit_m5hb = { - bidderCode: 'sonobi', - bids: [{ - bidId: 'testbid', - bidder: 'sonobi', - placementCode: 'adUnit_m5hb', - sizes: [[300, 250], [300, 600]], - params: { - placement_id: '/7780971/sparks_prebid_MR', - dom_id: 'div-gpt-ad-12345-0' - } - }] - }; - // FTFY - const sbi_adUnits = { - 'adUnit_p': adUnit_p, - 'adUnit_pd': adUnit_pd, - 'adUnit_pdf': adUnit_pdf, - 'adUnit_a': adUnit_a, - 'adUnit_as': adUnit_as, - 'adUnit_ad': adUnit_ad, - 'adUnit_af': adUnit_af, - 'adUnit_adf': adUnit_adf, - 'adUnit_A': adUnit_A, - 'adUnit_Ad': adUnit_Ad, - 'adUnit_Af': adUnit_Af, - 'adUnit_Adf': adUnit_Adf, - 'adUnit_m1hb': adUnit_m1hb, - 'adUnit_m2hb': adUnit_m2hb, - 'adUnit_m3hb': adUnit_m3hb, - 'adUnit_m4hb': adUnit_m4hb, - 'adUnit_m5hb': adUnit_m5hb - }; - - // Run the same test against all the (now tons of) different configurations - utils._each(sbi_adUnits, (adUnit, adUnitName) => { - describe('should form valid bid requests', () => { - let adapter = new Adapter(); - let stubLoadScript; - let stubFailBid; - let stubGoodBid; - - beforeEach(() => { - stubLoadScript = sinon.stub(adLoader, 'loadScript'); - stubFailBid = sinon.stub(adapter, 'failure'); - stubGoodBid = sinon.stub(adapter, 'success'); - }); - - afterEach(() => { - stubLoadScript.restore(); - stubFailBid.restore(); - stubGoodBid.restore(); - }); - - it('should make trinity key:vals for: ' + adUnitName, () => { - let keymakerBid = adapter.formRequest(adUnit.bids); - // Key matches one of two patterns and chai doesn't have an 'or' clause. - expect(Object.keys(keymakerBid)[0]).to.exist; - expect(Object.keys(keymakerBid)[0]).to.not.be.empty; - expect(keymakerBid[Object.keys(keymakerBid)[0]]).to.exist; - expect(keymakerBid[Object.keys(keymakerBid)[0]]).to.not.be.empty; - // Just having a key and val is sufficient for bidder to attempt to work with it. - }); - - it('should attempt to call bidder for: ' + adUnitName, () => { - adapter.callBids(adUnit); - expect(stubLoadScript.callCount).to.equal(1); - expect(stubFailBid.callCount).to.equal(0); - }); - }); - }); - - describe('should parse bid returns and register bid objects', () => { - let adapter = new Adapter(); - let spyAddBidResponse; - let stubFailBid; - let stubGoodBid; - - const sbi_bid = { - 'slots': - { - 'sbi_a': - { - 'sbi_size': '300x250', - 'sbi_apoc': 'premium', - 'sbi_aid': '159.60.7533347', - 'sbi_mouse': 4.20 - } - }, - 'sbi_dc': 'mco-1-' - }; - - const sbi_video_bid = { - 'slots': - { - 'sbi_a': - { - 'sbi_size': 'outstream', - 'sbi_apoc': 'premium', - 'sbi_aid': '159.60.7533347', - 'sbi_mouse': 4.20, - } - }, - 'sbi_dc': 'mco-1-' - }; - - const sbi_deal_bid = { - 'slots': - { - 'sbi_a': - { - 'sbi_size': '300x250', - 'sbi_apoc': 'premium', - 'sbi_aid': '159.60.7533347', - 'sbi_mouse': 4.20, - 'sbi_dozer': 'apex-test-deal' - } - }, - 'sbi_dc': 'mco-1-' - }; - - const sbi_noBid = { - 'slots': - { - 'sbi_a': {} - }, - 'sbi_dc': 'mco-1-' - }; - - beforeEach(() => { - spyAddBidResponse = sinon.spy(bidManager, 'addBidResponse'); - stubFailBid = sinon.stub(adapter, 'failure'); - stubGoodBid = sinon.stub(adapter, 'success'); - }); - - afterEach(() => { - spyAddBidResponse.restore(); - stubFailBid.restore(); - stubGoodBid.restore(); - }); - - it('should create bid object for good bid return', () => { - adapter.parseResponse(sbi_bid); - expect(spyAddBidResponse.called).to.be.true; - expect(stubFailBid.callCount).to.equal(0); - }); - - it('should create bid object for outstream video bid return', () => { - adapter.parseResponse(sbi_video_bid); - expect(spyAddBidResponse.called).to.be.true; - expect(stubFailBid.callCount).to.equal(0); - }); - - it('should create bid object for deal bid return', () => { - adapter.parseResponse(sbi_deal_bid); - expect(spyAddBidResponse.called).to.be.true; - expect(stubFailBid.callCount).to.equal(0); - }); - - it('should create fail bid object for empty return', () => { - adapter.parseResponse(sbi_noBid); - expect(spyAddBidResponse.called).to.be.true; - expect(stubGoodBid.callCount).to.equal(0); - }); - }); -}); diff --git a/test/spec/modules/spotxBidAdapter_spec.js b/test/spec/modules/spotxBidAdapter_spec.js deleted file mode 100644 index 1b48111b79e..00000000000 --- a/test/spec/modules/spotxBidAdapter_spec.js +++ /dev/null @@ -1,226 +0,0 @@ -import {expect} from 'chai'; -import {assert} from 'chai'; -import Adapter from 'modules/spotxBidAdapter'; -import bidManager from 'src/bidmanager'; -import adLoader from 'src/adloader'; - -const CHANNEL_ID = 85394; -const CACHE_KEY = 'eyJob3N0IjoiZmUwMDEuc3BvdHguZ2FkZ2V0cy5sb2QiLCJja'; - -let bidRequest = { - 'bidderCode': 'spotx', - 'requestId': '4b8bb067-fca9-478b-9207-d24b87fce85c', - 'bidderRequestId': '1bfc89fa86fd1d', - 'timeout': 1000, - 'bids': [ - { - 'bidId': '2626663210bd26', - 'bidder': 'spotx', - 'bidderRequestId': '145a190a61161e', - 'mediaType': 'video', - 'params': { - 'placementId': '123456789', - 'video': { - 'ad_mute': false, - 'autoplay': true, - 'channel_id': CHANNEL_ID, - 'hide_skin': false, - 'slot': null, - 'video_slot': null - } - }, - 'placementCode': 'video1', - 'requestId': '5e1e93aa-55cf-4f73-a56a-8a74d0584c5f', - 'sizes': [[640, 480]], - 'transactionId': 'df629792-c9ae-481e-9ce1-eaa83bde4cdb' - } - ] -}; - -let badBidRequest = { - 'bidderCode': 'spotx', - 'bids': [ - { - 'bidId': '2626663210bd26', - 'bidder': 'spotx', - 'mediaType': 'video', - 'params': { - 'placementId': '123456789', - 'video': { - 'slot': 'contentSpotx', - 'video_slot': 'contentElementSpotx' - } - }, - 'placementCode': 'video1', - } - ] -}; - -var xhrResponse = JSON.stringify({ - 'id': CHANNEL_ID.toString(), - 'cur': 'USD', - 'seatbid': [ - { - 'bid': [ - { - 'id': '47e.fc9b5.90ede6', - 'impid': '1497549328279', - 'impression_guid': 'e2514a4651f311e7b50f113c04e90000', - 'price': '20', - 'adm': '<\/VASTAdTagURI><\/Wrapper><\/Ad><\/VAST>', - 'adomain': 'null', - 'crid': '47e.fc9b5.90ede6', - 'cid': 'null', - 'ext': { - 'cache_key': CACHE_KEY - } - } - ] - } - ] -}); - -describe('spotx adapter tests', () => { - describe('callBids', () => { - let server; - let adapter; - - beforeEach(() => { - adapter = new Adapter(); - - var slot = document.createElement('div'); - slot.setAttribute('id', 'contentSpotx'); - document.body.appendChild(slot); - - var videoSlot = document.createElement('video'); - videoSlot.setAttribute('id', 'contentElementSpotx'); - slot.appendChild(videoSlot); - - var source1 = document.createElement('source'); - source1.setAttribute('src', 'http://rmcdn.2mdn.net/Demo/vast_inspector/android.mp4'); - videoSlot.appendChild(source1); - - bidRequest.bids[0].params.video.slot = slot; - bidRequest.bids[0].params.video.video_slot = videoSlot; - - server = sinon.fakeServer.create(); - server.respondImmediately = true; - }); - - afterEach(() => { - var slot = document.getElementById('contentSpotx'); - while (slot.firstChild) { - slot.removeChild(slot.firstChild); - } - var body = slot.parentElement; - body.removeChild(slot); - - server.restore(); - }); - - it('should load Direct AdOS onto page', () => { - sinon.spy(adLoader, 'loadScript'); - - adapter.callBids(bidRequest); - - sinon.assert.calledOnce(adLoader.loadScript); - expect(adLoader.loadScript.firstCall.args[0]).to.equal('//js.spotx.tv/directsdk/v1/' + CHANNEL_ID + '.js'); - expect(adLoader.loadScript.firstCall.args[1]).to.be.a('function'); - - adLoader.loadScript.restore(); - }); - - it('should not load Direct AdOS onto page if no bid is provided', () => { - sinon.spy(adLoader, 'loadScript'); - - adapter.callBids(); - sinon.assert.notCalled(adLoader.loadScript); - adLoader.loadScript.restore(); - }); - - describe('bid response tests', () => { - let loadScriptStub; - let getAdServerKVPsStub; - - before(() => { - let response = { - spotx_bid: 20, - spotx_ad_key: CACHE_KEY - }; - - getAdServerKVPsStub = sinon.stub(); - getAdServerKVPsStub.onCall(0).returns({ - then: function (successCb) { - return successCb(response); - } - }); - - getAdServerKVPsStub.onCall(1).returns({ - then: function (successCb, failureCb) { - return failureCb(); - } - }); - - window.SpotX = { - DirectAdOS: function(options) { - return { - getAdServerKVPs: getAdServerKVPsStub - } - } - }; - - loadScriptStub = sinon.stub(adLoader, 'loadScript', function(url, callback) { - callback(); - }); - }); - - after(() => { - loadScriptStub.restore(); - }); - - it('should add bid response on success', (done) => { - sinon.stub(bidManager, 'addBidResponse', (placementCode, bid) => { - expect(placementCode).to.equal('video1'); - expect(bid.bidderCode).to.equal('spotx'); - expect(bid.cpm).to.equal(20); - expect(bid.mediaType).to.equal('video'); - expect(bid.statusMessage).to.equal('Bid available'); - expect(bid.vastUrl).to.equal('//search.spotxchange.com/ad/vast.html?key=' + CACHE_KEY); - - bidManager.addBidResponse.restore(); - done(); - }); - - server.respondWith((request) => { - if (request.url.match(/openrtb\/2.3\/dados/) && request.method === 'POST') { - request.respond(200, {}, xhrResponse); - } - }); - - adapter.callBids(bidRequest); - }); - - it('should add failed bid response on error', (done) => { - sinon.stub(bidManager, 'addBidResponse', (placementCode, bid) => { - expect(placementCode).to.equal('video1'); - expect(bid.bidderCode).to.equal('spotx'); - expect(bid.statusMessage).to.equal('Bid returned empty or error response'); - expect(bid.cpm).to.be.undefined; - expect(bid.vastUrl).to.be.undefined; - - bidManager.addBidResponse.restore(); - done(); - }); - - server.respondWith((request) => { - if (request.url.match(/openrtb\/2.3\/dados/) && request.method === 'POST') { - request.respond(204, {}, ''); - } - }); - - adapter.callBids(bidRequest); - }); - }); - }); -}); diff --git a/test/spec/modules/stickyadstvBidAdapter_spec.js b/test/spec/modules/stickyadstvBidAdapter_spec.js deleted file mode 100644 index c0f35b1c406..00000000000 --- a/test/spec/modules/stickyadstvBidAdapter_spec.js +++ /dev/null @@ -1,225 +0,0 @@ -import {expect} from 'chai'; -import {assert} from 'chai'; -import Adapter from '../../../modules/stickyadstvBidAdapter'; -import adLoader from '../../../src/adloader'; - -describe('StickyAdsTV Adapter', function () { - var adapter = void 0; - var sandbox = void 0; - var bidsRequestBuff = void 0; - var bidderRequest = { - bidderCode: 'stickyadstv', - bids: [{ - bidId: 'bidId1', - bidder: 'stickyadstv', - placementCode: 'foo', - sizes: [[300, 250]], - params: { - zoneId: '2003', - format: 'screen-roll' - } - }, { - bidId: 'bidId2', - bidder: 'stickyadstv', - placementCode: 'bar', - sizes: [[728, 90]], - params: { - zoneId: '5562003' - } - }, { - bidId: 'bidId3', - bidder: 'stickyadstv', - placementCode: '', - sizes: [[300, 600]], - params: { - zoneId: '123456' - } - }, { - bidId: 'bidId4', - bidder: 'stickyadstv', - placementCode: 'coo', - sizes: [[300, 600]], - params: { - wrong: 'missing zoneId' - } - }] - }; - - beforeEach(function () { - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - bidsRequestBuff = $$PREBID_GLOBAL$$._bidsRequested; - $$PREBID_GLOBAL$$._bidsRequested = []; - }); - - afterEach(function () { - sandbox.restore(); - $$PREBID_GLOBAL$$._bidsRequested = bidsRequestBuff; - }); - - describe('callBids', function () { - beforeEach(function () { - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(bidderRequest); - }); - - it('should be called twice', function () { - sinon.assert.calledTwice(adLoader.loadScript); - }); - - it('should have load screenroll and mustang script', function () { - var url = void 0; - - url = adLoader.loadScript.firstCall.args[0]; - expect(url).to.equal('//cdn.stickyadstv.com/prime-time/screen-roll.min.js'); - - url = adLoader.loadScript.secondCall.args[0]; - expect(url).to.equal('//cdn.stickyadstv.com/mustang/mustang.min.js'); - }); - }); - - describe('getBid', function () { - let bidResponse; - let loadConfig; - let getPricingCalled; - - beforeEach(function () { - // Mock VastLoader for test purpose - window.com = { - stickyadstv: { - vast: { - VastLoader: function() { - this.getVast = function() { - return { - getPricing: function() { - getPricingCalled = true; - return {currency: 'USD', price: 4.000} - } - }; - }; - - this.load = function(config, listener) { - loadConfig = config; - listener.onSuccess(); - }; - } - }, - screenroll: { - getPlayerSize: function() { - return '123x456'; - } - } - } - }; - - adapter.getBid(bidderRequest.bids[0], function(bidObject) { - bidResponse = bidObject; - }); - }); - - afterEach(function() { - delete window.com.stickyadstv.vast.VastLoader; - delete window.com.stickyadstv.vast; - delete window.com.stickyadstv.screenroll; - delete window.com.stickyadstv; - }); - - it('should return a valid bidObject', function () { - expect(bidResponse).to.have.property('cpm', 4.000); - expect(bidResponse).to.have.property('ad', ""); - expect(bidResponse).to.have.property('bidderCode', 'stickyadstv'); - expect(bidResponse).to.have.property('currencyCode', 'USD'); - expect(bidResponse).to.have.property('width', 300); - expect(bidResponse).to.have.property('height', 250); - expect(bidResponse.getStatusCode()).to.equal(1); - }); - - it('should have called load with proper config', function () { - expect(loadConfig).to.have.property('playerSize', '123x456'); - expect(loadConfig).to.have.property('zoneId', '2003'); - }); - - it('should have called getPricing', function () { - expect(getPricingCalled).to.equal(true); - }); - }); - - describe('formatBidObject', function () { - it('should create a valid bid object', function () { - let result = adapter.formatBidObject('', true, {currency: 'EUR', price: '1.2345'}, '
sample
', 200, 300); - - expect(result).to.have.property('cpm', '1.2345'); - expect(result).to.have.property('ad', '
sample
'); - expect(result).to.have.property('currencyCode', 'EUR'); - expect(result).to.have.property('width', 200); - expect(result).to.have.property('height', 300); - expect(result.getStatusCode()).to.equal(1); - }); - - it('should create a invalid bid object because price is not defined', function () { - let result = adapter.formatBidObject('', true, null, '
sample
', 200, 300); - - expect(result.getStatusCode()).to.equal(2); - }); - - it('should create a invalid bid object', function () { - let result = adapter.formatBidObject('', false, {currency: 'EUR', price: '1.2345'}, '
sample
', 200, 300); - - expect(result.getStatusCode()).to.equal(2); - }); - }); - - describe('formatAdHTML', function () { - it('should create an inBanner ad format', function () { - let result = adapter.formatAdHTML({placementCode: 'placementCodeValue', params: {}}, [200, 300]); - - expect(result).to.equal('
'); - }); - - it('should create an intext ad format', function () { - let result = adapter.formatAdHTML({placementCode: 'placementCodeValue', params: {format: 'intext-roll', auto: 'v2', smartPlay: 'true'}}, [200, 300]); - - expect(result).to.equal(''); - }); - - it('should create a screenroll ad format', function () { - let result = adapter.formatAdHTML({placementCode: 'placementCodeValue', params: {format: 'screen-roll', smartPlay: 'true'}}, [200, 300]); - - expect(result).to.equal(''); - }); - }); - - describe('getBiggerSize', function () { - it('should return the bigger size', function () { - let result = adapter.getBiggerSize([[1, 4000], [4000, 1], [200, 300], [0, 0]]); - - expect(result[0]).to.equal(200); - expect(result[1]).to.equal(300); - }); - }); - - describe('top most window', function () { - it('should return the top most window', function () { - let result = adapter.getTopMostWindow(); - - expect(result).to.equal(window.top); - }); - }); - - describe('get component id', function() { - it('should return valid component ids', function() { - expect(adapter.getComponentId('inbanner')).to.equal('mustang'); - expect(adapter.getComponentId('intext-roll')).to.equal('intext-roll'); - expect(adapter.getComponentId('screen-roll')).to.equal('screen-roll'); - }); - }); - - describe('get API name', function() { - it('should return valid API names', function() { - expect(adapter.getAPIName()).to.equal(''); - expect(adapter.getAPIName('intext-roll')).to.equal('intextroll'); - expect(adapter.getAPIName('screen-roll')).to.equal('screenroll'); - expect(adapter.getAPIName('floorad')).to.equal('floorad'); - }); - }); -}); diff --git a/test/spec/modules/tapsenseBidAdapter_spec.js b/test/spec/modules/tapsenseBidAdapter_spec.js deleted file mode 100644 index 71f61af2a65..00000000000 --- a/test/spec/modules/tapsenseBidAdapter_spec.js +++ /dev/null @@ -1,257 +0,0 @@ -import { expect } from 'chai'; -import Adapter from 'modules/tapsenseBidAdapter'; -import bidmanager from 'src/bidmanager'; -import adloader from 'src/adloader'; -import * as utils from 'src/utils'; - -const DEFAULT_BIDDER_REQUEST = { - 'bidderCode': 'tapsense', - 'bidderRequestId': '141ed07a281ca3', - 'requestId': 'b202e550-b0f7-4fb9-bfb4-1aa80f1795b4', - 'start': new Date().getTime(), - 'bids': [ - { - 'sizes': undefined, // set values in tests - 'bidder': 'tapsense', - 'bidId': '2b211418dd0575', - 'bidderRequestId': '141ed07a281ca3', - 'placementCode': 'thisisatest', - 'params': { - 'ufid': 'thisisaufid', - 'refer': 'thisisarefer', - 'version': '0.0.1', - 'ad_unit_id': 'thisisanadunitid', - 'device_id': 'thisisadeviceid', - 'lat': 'thisislat', - 'long': 'thisisalong', - 'user': 'thisisanidfa', - 'price_floor': 0.01 - } - } - ] -}; - -const SUCCESSFUL_RESPONSE = { - 'count_ad_units': 1, - 'status': { - 'value': 'ok', - }, - 'ad_units': [ - { - html: '', - imp_url: 'https://i.tapsense.com' - } - ], - 'id': 'thisisanid', - 'width': 320, - 'height': 50, - 'time': new Date().getTime() -} - -const UNSUCCESSFUL_RESPONSE = { - 'count_ad_units': 0, - 'status': { - 'value': 'nofill' // will be set in test - }, - 'time': new Date().getTime() -} - -function duplicate(obj) { - return JSON.parse(JSON.stringify(obj)); -} - -function makeSuccessfulRequest(adapter) { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - modifiedReq.bids[0].sizes = [[320, 50], [500, 500]]; - adapter.callBids(modifiedReq); - return modifiedReq.bids; -} - -describe('TapSenseAdapter', () => { - let adapter, sandbox; - beforeEach(() => { - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - afterEach(() => { - sandbox.restore(); - }) - - describe('request function', () => { - beforeEach(() => { - sandbox.stub(adloader, 'loadScript'); - }); - afterEach(() => { - sandbox.restore(); - }); - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - it('requires parameters to make request', () => { - adapter.callBids({}); - sinon.assert.notCalled(adloader.loadScript); - }); - it('does not make a request if missing user', () => { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - delete modifiedReq.bids.user - adapter.callBids(modifiedReq); - sinon.assert.notCalled(adloader.loadScript); - }); - it('does not make a request if missing ad_unit_id', () => { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - delete modifiedReq.bids.ad_unit_id - adapter.callBids(modifiedReq); - sinon.assert.notCalled(adloader.loadScript); - }); - it('does not make a request if ad sizes are incorrect', () => { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - modifiedReq.bids[0].sizes = [[500, 500]]; - adapter.callBids(modifiedReq); - sinon.assert.notCalled(adloader.loadScript); - }); - it('does not make a request if ad sizes are invalid format', () => { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - modifiedReq.bids[0].sizes = 1234; - adapter.callBids(modifiedReq); - sinon.assert.notCalled(adloader.loadScript); - }); - - describe('requesting an ad', () => { - afterEach(() => { - sandbox.restore(); - }) - it('makes a request if valid sizes are provided (nested array)', () => { - makeSuccessfulRequest(adapter); - sinon.assert.calledOnce(adloader.loadScript); - expect(adloader.loadScript.firstCall.args[0]).to.contain( - 'ads04.tapsense.com' - ); - }); - it('handles a singles array for size parameter', () => { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - modifiedReq.bids[0].sizes = [320, 50]; - adapter.callBids(modifiedReq); - expect(adloader.loadScript.firstCall.args[0]).to.contain( - 'ads04.tapsense.com' - ); - }); - it('handles a string for size parameter', () => { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - modifiedReq.bids[0].sizes = '320x50'; - adapter.callBids(modifiedReq); - expect(adloader.loadScript.firstCall.args[0]).to.contain( - 'ads04.tapsense.com' - ); - }); - it('handles a string with multiple sizes for size parameter', () => { - let modifiedReq = duplicate(DEFAULT_BIDDER_REQUEST); - modifiedReq.bids[0].sizes = '320x50,500x500'; - adapter.callBids(modifiedReq); - expect(adloader.loadScript.firstCall.args[0]).to.contain( - 'ads04.tapsense.com' - ); - }); - it('appends bid params as a query string when requesting ad', () => { - makeSuccessfulRequest(adapter); - sinon.assert.calledOnce(adloader.loadScript); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /ufid=thisisaufid&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /refer=thisisarefer&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /version=[^&]+&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /jsonp=1&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /ad_unit_id=thisisanadunitid&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /device_id=thisisadeviceid&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /lat=thisislat&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /long=thisisalong&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /user=thisisanidfa&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /price_floor=0\.01&/ - ); - expect(adloader.loadScript.firstCall.args[0]).to.match( - /callback=$$PREBID_GLOBAL$$\.tapsense\.callback_with_price_.+&/ - ); - }) - }) - }); - - describe('generateCallback', () => { - beforeEach(() => { - sandbox.stub(adloader, 'loadScript'); - }); - afterEach(() => { - sandbox.restore(); - }); - it('generates callback in namespaced object with correct bidder id', () => { - makeSuccessfulRequest(adapter); - expect($$PREBID_GLOBAL$$.tapsense.callback_with_price_2b211418dd0575).to.exist.and.to.be.a('function'); - }) - }); - - describe('response', () => { - beforeEach(() => { - sandbox.stub(bidmanager, 'addBidResponse'); - sandbox.stub(adloader, 'loadScript'); - let bids = makeSuccessfulRequest(adapter); - sandbox.stub(utils, 'getBidRequest', (id) => { - return bids.find((item) => { return item.bidId === id }); - }) - }); - afterEach(() => { - sandbox.restore(); - }); - describe('successful response', () => { - beforeEach(() => { - $$PREBID_GLOBAL$$.tapsense.callback_with_price_2b211418dd0575(SUCCESSFUL_RESPONSE, 1.2); - }); - it('called the bidmanager and registers a bid', () => { - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bidmanager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(1); - }); - it('should have the correct placementCode', () => { - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bidmanager.addBidResponse.firstCall.args[0]).to.equal('thisisatest'); - }); - }); - describe('unsuccessful response', () => { - beforeEach(() => { - $$PREBID_GLOBAL$$.tapsense.callback_with_price_2b211418dd0575(UNSUCCESSFUL_RESPONSE, 1.2); - }) - it('should call the bidmanger and register an invalid bid', () => { - sinon.assert.calledOnce(bidmanager.addBidResponse); - expect(bidmanager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(2); - }); - it('should have the correct placementCode', () => { - expect(bidmanager.addBidResponse.firstCall.args[0]).to.equal('thisisatest'); - }) - }); - describe('no response/timeout', () => { - it('should not register any bids', () => { - sinon.assert.notCalled(bidmanager.addBidResponse); - }) - }); - describe('edge cases', () => { - it('does not register a bid if no price is supplied', () => { - sandbox.stub(utils, 'logMessage'); - $$PREBID_GLOBAL$$.tapsense.callback_with_price_2b211418dd0575(SUCCESSFUL_RESPONSE); - sinon.assert.notCalled(bidmanager.addBidResponse); - }); - }); - }); -}) diff --git a/test/spec/modules/thoughtleadrBidAdapter_spec.js b/test/spec/modules/thoughtleadrBidAdapter_spec.js deleted file mode 100644 index 3cd2a49e888..00000000000 --- a/test/spec/modules/thoughtleadrBidAdapter_spec.js +++ /dev/null @@ -1,108 +0,0 @@ -'use strict'; -var chai_1 = require('chai'); -var ta = require('modules/thoughtleadrBidAdapter'); -var bidfactory = require('src/bidfactory'); -var ajax = require('src/ajax'); -var Adapter = ta; - -describe('thoughtleadr adapter tests', function () { - var sandbox; - var adapter; - var request; - var createBid; - var ajaxMock; - - before(function () { - sandbox = sinon.sandbox.create(); - }); - - beforeEach(function () { - createBid = sandbox.spy(bidfactory, 'createBid'); - adapter = new Adapter(); - request = { - bidderCode: 'thoughtleadr', - bids: [{ - bidder: 'thoughtleadr', - placementCode: 'abc-123', - sizes: [[300, 250], [400, 400]], - params: { - placementId: 'test-placement', - }, - }], - }; - }); - - afterEach(function () { - sandbox.restore(); - }); - - describe('handleBids', function () { - it('should filter invalid bids', function () { - request.bids.unshift({ - bidder: 'thoughtleadr', - placementCode: 'abc-123', - sizes: [[300, 250], [400, 400]], - params: {}, - }); - request.bids.push({ - bidder: 'thoughtleadr', - placementCode: 'abc-123', - sizes: [[300, 250], [400, 400]], - params: { - incorrectParam: 123, - }, - }); - var requestPlacement = sinon.spy(adapter, 'requestPlacement'); - adapter.callBids(request); - chai_1.expect(requestPlacement.callCount).to.be.equal(1); - chai_1.expect(requestPlacement.getCall(0).args[0]).to.be.equal(request.bids[1]); - }); - }); - - describe('requestPlacement', function () { - it('should request header-bid.json', function () { - ajaxMock = sandbox.stub(ajax, 'ajax', function (url, cb) { - cb(JSON.stringify({ - header_bid_token: 'asd', - media_type: 'article', - amount: 2 - })); - }); - adapter.callBids(request); - chai_1.expect(ajaxMock.callCount).to.be.equal(1); - chai_1.expect(ajaxMock.firstCall.args[0]).to.contains( - '//a.thoughtleadr.com/v4/test-placement/header-bid.json?uid='); - chai_1.expect(createBid.firstCall.args[0]).to.be.equal(1); - }); - - it('should request header-bid.json without bids', function () { - ajaxMock = sandbox.stub(ajax, 'ajax', function (url, cb) { - cb(JSON.stringify({})); - }); - - adapter.callBids(request); - chai_1.expect(ajaxMock.callCount).to.be.equal(1); - chai_1.expect(ajaxMock.firstCall.args[0]).to.contains( - '//a.thoughtleadr.com/v4/test-placement/header-bid.json?uid='); - chai_1.expect(createBid.firstCall.args[0]).to.be.equal(2); - }); - - it('should sync cookies', function () { - ajaxMock = sandbox.stub(ajax, 'ajax', function (url, cb) { - cb(JSON.stringify({ - header_bid_token: 'asd', - media_type: 'article', - amount: 2, - cookie_syncs: [''] - })); - }); - adapter.callBids(request); - - var element = document.getElementById('tldr-cookie-sync-div'); - var iframes = element.getElementsByTagName('iframe'); - chai_1.expect(iframes.length).to.be.equal(1); - - chai_1.expect(iframes[0].contentDocument.body.innerHTML).to.be.equal(''); - }); - }); -}); diff --git a/test/spec/modules/tremorBidAdapter_spec.js b/test/spec/modules/tremorBidAdapter_spec.js deleted file mode 100644 index c09c1112b3e..00000000000 --- a/test/spec/modules/tremorBidAdapter_spec.js +++ /dev/null @@ -1,173 +0,0 @@ -import {expect} from 'chai'; -import Adapter from 'modules/tremorBidAdapter'; -import bidmanager from 'src/bidmanager'; - -const AD_CODE = 'ssp-!demo!-lufip'; -const SUPPLY_CODE = 'ssp-%21demo%21-rm6rh'; -const SIZES = [640, 480]; -const REQUEST = { - 'code': 'video1', - 'sizes': [640, 480], - 'mediaType': 'video', - 'bids': [{ - 'bidder': 'tremor', - 'params': { - 'mediaId': 'MyCoolVideo', - 'mediaUrl': '', - 'mediaTitle': '', - 'contentLength': '', - 'floor': '', - 'efloor': '', - 'custom': '', - 'categories': '', - 'keywords': '', - 'blockDomains': '', - 'c2': '', - 'c3': '', - 'c4': '', - 'skip': '', - 'skipmin': '', - 'skipafter': '', - 'delivery': '', - 'placement': '', - 'videoMinBitrate': '', - 'videoMaxBitrate': '' - } - }] -}; - -const RESPONSE = { - 'cur': 'USD', - 'id': '3dba13e35f3d42f998bc7e65fd871889', - 'seatbid': [{ - 'seat': 'TremorVideo', - 'bid': [{ - 'adomain': [], - 'price': 0.50000, - 'id': '3dba13e35f3d42f998bc7e65fd871889', - 'adm': '\n Tremor Video Test MP4 Creative \n\n \n\n\n\n\n\n \n\n \n\n', - 'impid': '1' - }] - }] -}; - -describe('TremorBidAdapter', () => { - let adapter; - - beforeEach(() => adapter = new Adapter()); - - describe('request function', () => { - let xhr; - let requests; - - beforeEach(() => { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = request => requests.push(request); - }); - - afterEach(() => xhr.restore()); - - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - - it('requires paramters to make request', () => { - adapter.callBids({}); - expect(requests).to.be.empty; - }); - - it('requires adCode && supplyCode', () => { - let backup = REQUEST.bids[0].params; - REQUEST.bids[0].params = {adCode: AD_CODE}; - adapter.callBids(REQUEST); - expect(requests).to.be.empty; - REQUEST.bids[0].params = backup; - }); - - it('requires proper sizes to make a bid request', () => { - let backupBid = REQUEST; - backupBid.sizes = []; - adapter.callBids(backupBid); - expect(requests).to.be.empty; - }); - - it('generates a proper ad call URL', () => { - REQUEST.bids[0].params.adCode = AD_CODE; - REQUEST.bids[0].params.supplyCode = SUPPLY_CODE; - REQUEST.bids[0].sizes = SIZES; - adapter.callBids(REQUEST); - const requestUrl = requests[0].url; - let srcPageURl = ('&srcPageUrl=' + encodeURIComponent(document.location.href)); - expect(requestUrl).to.equal('http://ssp-%21demo%21-rm6rh.ads.tremorhub.com/ad/tag?adCode=ssp-!demo!-lufip&playerWidth=640&playerHeight=480' + srcPageURl + '&mediaId=MyCoolVideo&fmt=json'); - }); - - it('generates a proper ad call URL given a different size format', () => { - REQUEST.bids[0].params.adCode = AD_CODE; - REQUEST.bids[0].params.supplyCode = SUPPLY_CODE; - REQUEST.bids[0].sizes = [SIZES]; - adapter.callBids(REQUEST); - const requestUrl = requests[0].url; - let srcPageURl = ('&srcPageUrl=' + encodeURIComponent(document.location.href)); - expect(requestUrl).to.equal('http://ssp-%21demo%21-rm6rh.ads.tremorhub.com/ad/tag?adCode=ssp-!demo!-lufip&playerWidth=640&playerHeight=480' + srcPageURl + '&mediaId=MyCoolVideo&fmt=json'); - }); - }); - - describe('response handler', () => { - let server; - - beforeEach(() => { - server = sinon.fakeServer.create(); - sinon.stub(bidmanager, 'addBidResponse'); - }); - - afterEach(() => { - server.restore(); - bidmanager.addBidResponse.restore(); - }); - - it('registers bids', () => { - server.respondWith(JSON.stringify(RESPONSE)); - - adapter.callBids(REQUEST); - server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('statusMessage', 'Bid available'); - expect(response).to.have.property('cpm', 0.50000); - }); - - it('handles nobid responses', () => { - server.respondWith(JSON.stringify({ - 'cur': 'USD', - 'id': 'ff83ce7e00df41c9bce79b651afc7c51', - 'seatbid': [] - })); - - adapter.callBids(REQUEST); - server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property( - 'statusMessage', - 'Bid returned empty or error response' - ); - }); - - it('handles JSON.parse errors', () => { - server.respondWith(''); - - adapter.callBids(REQUEST); - server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property( - 'statusMessage', - 'Bid returned empty or error response' - ); - }); - }); -}); diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js deleted file mode 100644 index 95658883fd0..00000000000 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ /dev/null @@ -1,226 +0,0 @@ -import {expect} from 'chai'; -import Adapter from '../../../modules/tripleliftBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; -import {parse as parseURL} from '../../../src/url'; - -describe('triplelift adapter', () => { - let bidsRequestedOriginal; - let adapter; - let sandbox; - - const bidderRequest = { - bidderCode: 'triplelift', - bids: [ - { - bidId: 'bidId1', - bidder: 'triplelift', - placementCode: 'foo', - sizes: [[728, 90]], - params: { - inventoryCode: 'codeA' - } - }, - { - bidId: 'bidId2', - bidder: 'triplelift', - placementCode: 'bar', - sizes: [[300, 600]], - params: { - inventoryCode: 'codeB', - floor: 1 - } - } - ] - }; - - beforeEach(() => { - bidsRequestedOriginal = $$PREBID_GLOBAL$$._bidsRequested; - $$PREBID_GLOBAL$$._bidsRequested = []; - - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - - $$PREBID_GLOBAL$$._bidsRequested = bidsRequestedOriginal; - }); - - describe('callBids', () => { - let firstBidScriptURL; - let secondBidScriptURL; - - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(bidderRequest); - - firstBidScriptURL = adLoader.loadScript.firstCall.args[0]; - secondBidScriptURL = adLoader.loadScript.secondCall.args[0] - }); - - it('should load a script for each bid request', () => { - sinon.assert.calledTwice(adLoader.loadScript); - - let route = 'http://tlx.3lift.com/header/auction?'; - expect(firstBidScriptURL).to.contain(route); - 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_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_id', 'bidId2'); - expect(secondScriptParams).to.have.property('inv_code', 'codeB'); - expect(secondScriptParams).to.have.property('size', '300x600'); - expect(secondScriptParams).to.have.property('floor', '1'); - expect(secondScriptParams).to.have.property('referrer'); - }); - }); - - describe('TLCB', () => { - it('should exist and be a function', () => { - expect($$PREBID_GLOBAL$$.TLCB).to.exist.and.to.be.a('function'); - }); - }); - - describe('add bids to the manager', () => { - let firstBid; - let secondBid; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // respond - let bidderReponse1 = { - 'ad': '', - 'callback_id': 'bidId1', - 'cpm': 0.20, - 'height': 90, - 'iurl': '', - 'width': 728 - }; - - let bidderReponse2 = { - 'ad': '', - 'callback_id': 'bidId2', - 'cpm': 0.30, - 'height': 600, - 'iurl': '', - 'width': 300, - 'deal_id': 'dealA' - }; - - $$PREBID_GLOBAL$$.TLCB(bidderReponse1); - $$PREBID_GLOBAL$$.TLCB(bidderReponse2); - - firstBid = bidManager.addBidResponse.firstCall.args[1]; - secondBid = bidManager.addBidResponse.secondCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledTwice(bidManager.addBidResponse); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidManager.addBidResponse.firstCall.args[0]; - let secondPlacementCode = bidManager.addBidResponse.secondCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - expect(secondPlacementCode).to.eql('bar'); - }); - - it('should include the bid request bidId as the adId', () => { - expect(firstBid).to.have.property('adId', 'bidId1'); - expect(secondBid).to.have.property('adId', 'bidId2'); - }); - - it('should have a good statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(1); - expect(secondBid.getStatusCode()).to.eql(1); - }); - - it('should add the CPM to the bid object', () => { - expect(firstBid).to.have.property('cpm', 0.20); - expect(secondBid).to.have.property('cpm', 0.30); - }); - - it('should add the bidder code to the bid object', () => { - expect(firstBid).to.have.property('bidderCode', 'triplelift'); - expect(secondBid).to.have.property('bidderCode', 'triplelift'); - }); - - it('should include the ad on the bid object', () => { - expect(firstBid).to.have.property('ad'); - expect(secondBid).to.have.property('ad'); - }); - - it('should include the size on the bid object', () => { - expect(firstBid).to.have.property('width', 728); - expect(firstBid).to.have.property('height', 90); - expect(secondBid).to.have.property('width', 300); - expect(secondBid).to.have.property('height', 600); - }); - - it('should include the dealId on the bid object if present', () => { - expect(firstBid).to.have.property('dealId', undefined); - expect(secondBid).to.have.property('dealId', 'dealA'); - }); - }); - - describe('add empty bids if no bid returned', () => { - let firstBid; - let secondBid; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // respond - let bidderReponse1 = {'status': 'no_bid', 'callback_id': 'bidId1'}; - let bidderReponse2 = {'status': 'no_bid', 'callback_id': 'bidId2'}; - - $$PREBID_GLOBAL$$.TLCB(bidderReponse1); - $$PREBID_GLOBAL$$.TLCB(bidderReponse2); - - firstBid = bidManager.addBidResponse.firstCall.args[1]; - secondBid = bidManager.addBidResponse.secondCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledTwice(bidManager.addBidResponse); - }); - - it('should include the bid request bidId as the adId', () => { - expect(firstBid).to.have.property('adId', 'bidId1'); - expect(secondBid).to.have.property('adId', 'bidId2'); - }); - - it('should have an error statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(2); - expect(secondBid.getStatusCode()).to.eql(2); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidManager.addBidResponse.firstCall.args[0]; - let secondPlacementCode = bidManager.addBidResponse.secondCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - expect(secondPlacementCode).to.eql('bar'); - }); - - it('should add the bidder code to the bid object', () => { - expect(firstBid).to.have.property('bidderCode', 'triplelift'); - expect(secondBid).to.have.property('bidderCode', 'triplelift'); - }); - }); -}); diff --git a/test/spec/modules/twengaBidAdapter_spec.js b/test/spec/modules/twengaBidAdapter_spec.js deleted file mode 100644 index dcead6c4578..00000000000 --- a/test/spec/modules/twengaBidAdapter_spec.js +++ /dev/null @@ -1,119 +0,0 @@ -describe('twenga adapter tests', function () { - var urlParse = require('url-parse'); - var querystringify = require('querystringify'); - var Adapter = require('modules/twengaBidAdapter'); - var adLoader = require('src/adloader'); - var expect = require('chai').expect; - var bidmanager = require('src/bidmanager'); - var CONSTANTS = require('src/constants.json'); - - var DEFAULT_PARAMS = { - bidderCode: 'twenga', - bids: [{ - bidId: 'tw_abcd1234', - sizes: [[300, 250], [300, 200]], - bidder: 'twenga', - params: { - placementId: 'test', - siteId: 1234, - publisherId: 5678, - currency: 'USD', - bidFloor: 0.5, - country: 'DE' - }, - requestId: 'tw_efgh5678', - placementCode: 'tw_42' - }] - }; - - var BID_RESPONSE = { - result: { - cpm: 10000, - width: 300, - height: 250, - ad: '//rtb.t.c4tw.net', - creative_id: 'test' - }, - callback_uid: 'tw_abcd1234' - }; - - it('sets url parameters', function () { - var stubLoadScript = sinon.stub(adLoader, 'loadScript'); - - (new Adapter()).callBids(DEFAULT_PARAMS); - - var bidUrl = stubLoadScript.getCall(0).args[0]; - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - expect(parsedBidUrl.hostname).to.equal('rtb.t.c4tw.net'); - 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_uid').and.to.equal('tw_abcd1234'); - expect(parsedBidUrlQueryString).to.have.property('id').and.to.equal('test'); - - stubLoadScript.restore(); - }); - - var stringToFunction = function (s) { - var scope = global; - var scopeSplit = s.split('.'); - for (var i = 0; i < scopeSplit.length - 1; i++) { - scope = scope[scopeSplit[i]]; - if (scope == undefined) return; - } - return scope[scopeSplit[scopeSplit.length - 1]]; - }; - - it('creates an empty bid response if no bids', function() { - var stubLoadScript = sinon.stub(adLoader, 'loadScript', function(url) { - var bidUrl = stubLoadScript.getCall(0).args[0]; - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - var callback = stringToFunction(parsedBidUrlQueryString.callback); - expect(callback).to.exist.and.to.be.a('function'); - callback(undefined); - }); - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - (new Adapter()).callBids(DEFAULT_PARAMS); - - expect(stubAddBidResponse.getCall(0)).to.be.null; - - stubAddBidResponse.restore(); - stubLoadScript.restore(); - }); - - it('creates a bid response if bid is returned', function() { - var stubLoadScript = sinon.stub(adLoader, 'loadScript', function(url) { - var bidUrl = stubLoadScript.getCall(0).args[0]; - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - $$PREBID_GLOBAL$$._bidsRequested - .push({ bidderCode: DEFAULT_PARAMS.bidderCode, - bids: [{ bidId: parsedBidUrlQueryString.callback_uid, - placementCode: DEFAULT_PARAMS.bids[0].placementCode }]}); - - var callback = stringToFunction(parsedBidUrlQueryString.callback); - expect(callback).to.exist.and.to.be.a('function'); - callback(BID_RESPONSE); - }); - var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - - (new Adapter()).callBids(DEFAULT_PARAMS); - - var bidResponseAd = stubAddBidResponse.getCall(0).args[1]; - - expect(bidResponseAd).to.have.property('cpm').and.to.equal(BID_RESPONSE.result.cpm / 10000); - expect(bidResponseAd).to.have.property('adUrl').and.to.equal(BID_RESPONSE.result.ad); - expect(bidResponseAd).to.have.property('width').and.to.equal(BID_RESPONSE.result.width); - expect(bidResponseAd).to.have.property('height').and.to.equal(BID_RESPONSE.result.height); - - stubAddBidResponse.restore(); - stubLoadScript.restore(); - }); -}); diff --git a/test/spec/modules/ucfunnelBidAdapter_spec.js b/test/spec/modules/ucfunnelBidAdapter_spec.js deleted file mode 100644 index d8ddfc041b6..00000000000 --- a/test/spec/modules/ucfunnelBidAdapter_spec.js +++ /dev/null @@ -1,110 +0,0 @@ -import { expect } from 'chai'; -import Adapter from 'modules/ucfunnelBidAdapter'; -import adapterManager from 'src/adaptermanager'; -import bidManager from 'src/bidmanager'; -import CONSTANTS from 'src/constants.json'; - -describe('ucfunnel adapter tests', function () { - let sandbox; - const adUnit = { // TODO CHANGE - code: 'ucfunnel', - sizes: [[300, 250]], - bids: [{ - bidder: 'ucfunnel', - params: { - adid: 'test-ad-83444226E44368D1E32E49EEBE6D29', - width: 300, - height: 250 - } - }] - }; - - const response = { - ad_id: 'ad-83444226E44368D1E32E49EEBE6D29', - adm: '
', - cpm: 0.01, - height: 250, - width: 300 - }; - - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('ucfunnel callBids validation', () => { - let bids, - server; - - beforeEach(() => { - bids = []; - server = sinon.fakeServer.create(); - - sandbox.stub(bidManager, 'addBidResponse', (elemId, bid) => { - bids.push(bid); - }); - }); - - afterEach(() => { - server.restore(); - }); - - let adapter = adapterManager.bidderRegistry['ucfunnel']; - - it('Valid bid-request', () => { - sandbox.stub(adapter, 'callBids'); - adapterManager.callBids({ - adUnits: [clone(adUnit)] - }); - - let bidderRequest = adapter.callBids.getCall(0).args[0]; - - expect(bidderRequest).to.have.property('bids') - .that.is.an('array') - .with.lengthOf(1); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .to.have.property('bidder', 'ucfunnel'); - - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('sizes') - .that.is.an('array') - .with.lengthOf(1) - .that.deep.equals(adUnit.sizes); - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('params') - .to.have.property('adid', 'test-ad-83444226E44368D1E32E49EEBE6D29'); - expect(bidderRequest).to.have.deep.property('bids[0]') - .with.property('params') - .to.have.property('width', 300); - }); - - it('Valid bid-response', () => { - server.respondWith(JSON.stringify( - response - )); - adapterManager.callBids({ - adUnits: [clone(adUnit)] - }); - server.respond(); - - expect(bids).to.be.lengthOf(1); - expect(bids[0].getStatusCode()).to.equal(CONSTANTS.STATUS.GOOD); - expect(bids[0].bidderCode).to.equal('ucfunnel'); - expect(bids[0].width).to.equal(300); - expect(bids[0].height).to.equal(250); - expect(bids[0].cpm).to.equal(0.01); - }); - }); -}); - -function clone(obj) { - try { - return JSON.parse(JSON.stringify(obj)); - } catch (e) { - return {}; - } -} diff --git a/test/spec/modules/unrulyBidAdapter_spec.js b/test/spec/modules/unrulyBidAdapter_spec.js deleted file mode 100644 index 067f3ea46d0..00000000000 --- a/test/spec/modules/unrulyBidAdapter_spec.js +++ /dev/null @@ -1,278 +0,0 @@ -/* globals describe, it, beforeEach, afterEach, sinon */ -import { expect } from 'chai' -import bidfactory from 'src/bidfactory' -import bidmanager from 'src/bidmanager' -import * as utils from 'src/utils' -import { STATUS } from 'src/constants' -import { Renderer } from 'src/Renderer' -import createUnrulyAdapter from 'modules/unrulyBidAdapter' - -describe('UnrulyAdapter', () => { - function createBidRequestBid({ placementCode }) { - return { - 'bidder': 'unruly', - 'params': { - 'uuid': '74544e00-d43b-4f3a-a799-69d22ce979ce', - 'siteId': 794599, - 'placementId': '5768085' - }, - 'placementCode': placementCode, - 'mediaTypes': { video: { context: 'outstream' } }, - 'transactionId': '62890707-3770-497c-a3b8-d905a2d0cb98', - 'sizes': [ - 640, - 480 - ], - 'bidId': '23b86d8f6335ce', - 'bidderRequestId': '1d5b7474eb5416', - 'requestId': '406fe12b-fa3b-4bd3-b3c8-043951b4dac1' - } - } - - function createParams(...bids) { - return { - 'bidderCode': 'unruly', - 'requestId': '406fe12b-fa3b-4bd3-b3c8-043951b4dac1', - 'bidderRequestId': '1d5b7474eb5416', - 'bids': bids, - 'start': 1495794517251, - 'auctionStart': 1495794517250, - 'timeout': 3000 - } - } - - function createOutStreamExchangeBid({ placementCode, statusCode = 1 }) { - return { - 'ext': { - 'statusCode': statusCode, - 'renderer': { - 'id': 'unruly_inarticle', - 'config': {}, - 'url': 'https://video.unrulymedia.com/native/prebid-loader.js' - }, - 'placementCode': placementCode - }, - 'cpm': 20, - 'bidderCode': 'unruly', - 'width': 323, - 'vastUrl': 'https://targeting.unrulymedia.com/in_article?uuid=74544e00-d43b-4f3a-a799-69d22ce979ce&supported_mime_type=application/javascript&supported_mime_type=video/mp4&tj=%7B%22site%22%3A%7B%22lang%22%3A%22en-GB%22%2C%22ref%22%3A%22%22%2C%22page%22%3A%22http%3A%2F%2Fdemo.unrulymedia.com%2FinArticle%2Finarticle_nypost_upbeat%2Ftravel_magazines.html%22%2C%22domain%22%3A%22demo.unrulymedia.com%22%7D%2C%22user%22%3A%7B%22profile%22%3A%7B%22quantcast%22%3A%7B%22segments%22%3A%5B%7B%22id%22%3A%22D%22%7D%2C%7B%22id%22%3A%22T%22%7D%5D%7D%7D%7D%7D&video_width=618&video_height=347', - 'bidId': 'foo', - 'height': 323 - } - } - - function createInStreamExchangeBid({ placementCode, statusCode = 1 }) { - return { - 'ext': { - 'statusCode': statusCode, - 'placementCode': placementCode - }, - 'cpm': 20, - 'bidderCode': 'unruly', - 'width': 323, - 'vastUrl': 'https://targeting.unrulymedia.com/in_article?uuid=74544e00-d43b-4f3a-a799-69d22ce979ce&supported_mime_type=application/javascript&supported_mime_type=video/mp4&tj=%7B%22site%22%3A%7B%22lang%22%3A%22en-GB%22%2C%22ref%22%3A%22%22%2C%22page%22%3A%22http%3A%2F%2Fdemo.unrulymedia.com%2FinArticle%2Finarticle_nypost_upbeat%2Ftravel_magazines.html%22%2C%22domain%22%3A%22demo.unrulymedia.com%22%7D%2C%22user%22%3A%7B%22profile%22%3A%7B%22quantcast%22%3A%7B%22segments%22%3A%5B%7B%22id%22%3A%22D%22%7D%2C%7B%22id%22%3A%22T%22%7D%5D%7D%7D%7D%7D&video_width=618&video_height=347', - 'bidId': 'foo', - 'height': 323 - } - } - - function createExchangeResponse(...bids) { - return { - 'bids': bids - } - } - - let adapter - let server - let sandbox - let fakeRenderer - - beforeEach(() => { - adapter = createUnrulyAdapter() - adapter.exchangeUrl = 'http://localhost:9000/prebid' - - sandbox = sinon.sandbox.create() - sandbox.stub(bidmanager, 'addBidResponse') - sandbox.stub(bidfactory, 'createBid') - sandbox.stub(utils, 'logError') - - fakeRenderer = { - setRender: sinon.stub() - } - - sandbox.stub(Renderer, 'install') - Renderer.install.returns(fakeRenderer) - - server = sinon.fakeServer.create() - }) - - afterEach(() => { - sandbox.restore() - server.restore() - delete parent.window.unruly - }) - - describe('callBids', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function') - }) - - it('requires bids to make request', () => { - adapter.callBids({}) - expect(server.requests).to.be.empty - }) - - it('requires at least one bid to make request', () => { - adapter.callBids({ bids: [] }) - expect(server.requests).to.be.empty - }) - - it('passes bids through to exchange', () => { - const params = createParams(createBidRequestBid({ placementCode: 'placement1' })) - - adapter.callBids(params) - - expect(server.requests).to.have.length(1) - expect(server.requests[0].url).to.equal('http://localhost:9000/prebid') - - const requestBody = JSON.parse(server.requests[0].requestBody) - expect(requestBody).to.deep.equal({ - 'bidRequests': params.bids - }) - }) - - it('creates a bid response using status code from exchange for each bid and passes in the exchange response', () => { - const params = createParams(createBidRequestBid({ placementCode: 'placement1' })) - - const exchangeBid1 = createOutStreamExchangeBid({ placementCode: 'placement1' }) - const exchangeBid2 = createOutStreamExchangeBid({ placementCode: 'placement2', statusCode: 2 }) - const exchangeResponse = createExchangeResponse(exchangeBid1, exchangeBid2) - - server.respondWith(JSON.stringify(exchangeResponse)) - bidfactory.createBid.returns({}) - - adapter.callBids(params) - server.respond() - - sinon.assert.calledTwice(bidfactory.createBid) - sinon.assert.calledWith(bidfactory.createBid, exchangeBid1.ext.statusCode, exchangeResponse.bids[0]) - sinon.assert.calledWith(bidfactory.createBid, exchangeBid2.ext.statusCode, exchangeResponse.bids[1]) - }) - - it('adds the bid response to the bid manager', () => { - const fakeBid = {} - - const params = createParams(createBidRequestBid({ placementCode: 'placement1' })) - const exchangeBid = createOutStreamExchangeBid({ placementCode: 'placement1' }) - const exchangeResponse = createExchangeResponse(exchangeBid) - - server.respondWith(JSON.stringify(exchangeResponse)) - bidfactory.createBid.withArgs(exchangeBid.ext.statusCode).returns(fakeBid) - - adapter.callBids(params) - server.respond() - - sinon.assert.calledOnce(bidmanager.addBidResponse) - sinon.assert.calledWith(bidmanager.addBidResponse, exchangeBid.ext.placementCode, fakeBid) - }) - - describe('on invalid exchange response', () => { - it('should create NO_BID response for each bid request bid', () => { - const bidRequestBid1 = createBidRequestBid({ placementCode: 'placement1' }) - const bidRequestBid2 = createBidRequestBid({ placementCode: 'placement2' }) - const params = createParams(bidRequestBid1, bidRequestBid2) - const expectedBid = { 'some': 'props' } - - server.respondWith('this is not json') - bidfactory.createBid.withArgs(STATUS.NO_BID).returns(expectedBid) - - adapter.callBids(params) - server.respond() - - sinon.assert.calledOnce(utils.logError) - sinon.assert.calledTwice(bidmanager.addBidResponse) - sinon.assert.calledWith(bidmanager.addBidResponse, bidRequestBid1.placementCode, expectedBid) - sinon.assert.calledWith(bidmanager.addBidResponse, bidRequestBid2.placementCode, expectedBid) - }) - }) - - describe('InStream', () => { - it('merges bid response defaults', () => { - const params = createParams(createBidRequestBid({ placementCode: 'placement1' })) - - const fakeBidDefaults = { some: 'default' } - const fakeBid = Object.assign({}, fakeBidDefaults) - - const exchangeBid = createInStreamExchangeBid({ placementCode: 'placement1' }) - const exchangeResponse = createExchangeResponse(exchangeBid) - server.respondWith(JSON.stringify(exchangeResponse)) - - bidfactory.createBid.withArgs(exchangeBid.ext.statusCode).returns(fakeBid) - - adapter.callBids(params) - server.respond() - - sinon.assert.notCalled(Renderer.install) - expect(fakeBid).to.deep.equal(Object.assign( - {}, - fakeBidDefaults, - exchangeBid - )) - }) - }) - - describe('OutStream', () => { - it('merges bid response defaults with exchange bid and renderer', () => { - const params = createParams(createBidRequestBid({ placementCode: 'placement1' })) - - const fakeBidDefaults = { some: 'default' } - const fakeBid = Object.assign({}, fakeBidDefaults) - - const exchangeBid = createOutStreamExchangeBid({ placementCode: 'placement1' }) - const exchangeResponse = createExchangeResponse(exchangeBid) - server.respondWith(JSON.stringify(exchangeResponse)) - - bidfactory.createBid.withArgs(exchangeBid.ext.statusCode).returns(fakeBid) - - const fakeRenderer = {} - Renderer.install.withArgs(Object.assign( - {}, - exchangeBid.ext.renderer, - { callback: sinon.match.func } - )).returns(fakeRenderer) - - adapter.callBids(params) - server.respond() - - expect(fakeBid).to.deep.equal(Object.assign( - {}, - fakeBidDefaults, - exchangeBid, - { renderer: fakeRenderer } - )) - }) - - it('bid is placed on the bid queue when render is called', () => { - const params = createParams(createBidRequestBid({ placementCode: 'placement1' })) - - const fakeBidDefaults = { some: 'default' } - const fakeBid = Object.assign({}, fakeBidDefaults) - - const exchangeBid = createOutStreamExchangeBid({ placementCode: 'placement1' }) - const exchangeResponse = createExchangeResponse(exchangeBid) - server.respondWith(JSON.stringify(exchangeResponse)) - - bidfactory.createBid.withArgs(exchangeBid.ext.statusCode).returns(fakeBid) - - adapter.callBids(params) - server.respond() - - sinon.assert.calledOnce(fakeRenderer.setRender) - fakeRenderer.setRender.firstCall.args[0]() - - expect(window.top).to.have.deep.property('unruly.native.prebid.uq'); - expect(window.top.unruly.native.prebid.uq).to.deep.equal([['render', fakeBid]]) - }) - }) - }) -}) diff --git a/test/spec/modules/vertozBidAdapter_spec.js b/test/spec/modules/vertozBidAdapter_spec.js deleted file mode 100644 index 87d0ec8c842..00000000000 --- a/test/spec/modules/vertozBidAdapter_spec.js +++ /dev/null @@ -1,140 +0,0 @@ -import {expect} from 'chai'; -import {assert} from 'chai'; -import Adapter from '../../../modules/vertozBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; - -describe('Vertoz Adapter', () => { - let adapter; - let sandbox; - let bidsRequestBuff; - const bidderRequest = { - bidderCode: 'vertoz', - bids: [{ - bidId: 'bidId1', - bidder: 'vertoz', - placementCode: 'foo', - sizes: [ - [300, 250] - ], - params: { - placementId: 'VZ-HB-123' - } - }, { - bidId: 'bidId2', - bidder: 'vertoz', - placementCode: 'bar', - sizes: [ - [728, 90] - ], - params: { - placementId: 'VZ-HB-456' - } - }, { - bidId: 'bidId3', - bidder: 'vertoz', - placementCode: 'coo', - sizes: [ - [300, 600] - ], - params: { - placementId: '' - } - }] - }; - - beforeEach(() => { - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - bidsRequestBuff = $$PREBID_GLOBAL$$._bidsRequested; - $$PREBID_GLOBAL$$._bidsRequested = []; - }); - - afterEach(() => { - sandbox.restore(); - $$PREBID_GLOBAL$$._bidsRequested = bidsRequestBuff; - }); - - describe('callBids', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(bidderRequest); - }); - - it('should be called twice', () => { - sinon.assert.calledTwice(adLoader.loadScript); - }); - }); - - describe('Bid response', () => { - let vzBidRequest; - let bidderReponse = { - 'vzhPlacementId': 'VZ-HB-123', - 'bid': '0fac1b8a-6ba0-4641-bd57-2899b1bedeae_0', - 'adWidth': '300', - 'adHeight': '250', - 'cpm': '1.00000000000000', - 'ad': '
', - 'slotBidId': 'bidId1', - 'nurl': '', - 'statusText': 'vertoz:success' - }; - - beforeEach(() => { - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - }); - - describe('success', () => { - let firstBidReg; - let adSpaceId; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - $$PREBID_GLOBAL$$.vzResponse(bidderReponse); - firstBidReg = bidManager.addBidResponse.firstCall.args[1]; - adSpaceId = bidManager.addBidResponse.firstCall.args[0]; - }); - - it('cpm to have property 1.000000', () => { - expect(firstBidReg).to.have.property('cpm', 1.00); - }); - it('adSpaceId should exist and be equal to placementCode', () => { - expect(adSpaceId).to.equal('foo'); - }); - it('should have property ad', () => { - expect(firstBidReg).to.have.property('ad'); - }); - it('should include the size to the bid object', () => { - expect(firstBidReg).to.have.property('width', '300'); - expect(firstBidReg).to.have.property('height', '250'); - }); - }); - - describe('failure', () => { - let secondBidReg; - let adSpaceId; - let bidderResponse = { - 'vzhPlacementId': 'VZ-HB-456', - 'slotBidId': 'bidId2', - 'statusText': 'vertoz:NO_BIDS' - } - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - $$PREBID_GLOBAL$$.vzResponse(bidderResponse); - secondBidReg = bidManager.addBidResponse.firstCall.args[1]; - adSpaceId = bidManager.addBidResponse.firstCall.args[0]; - }); - - it('should not have cpm property', () => { - expect(secondBidReg.cpm).to.be.undefined; - }); - it('adSpaceId should exist and be equal to placementCode', () => { - expect(adSpaceId).to.equal('bar'); - }); - it('should not have ad property', () => { - expect(secondBidReg.ad).to.be.undefined; - }); - }); - }); -}); diff --git a/test/spec/modules/wideorbitBidAdapter_spec.js b/test/spec/modules/wideorbitBidAdapter_spec.js deleted file mode 100644 index 9ace04883e6..00000000000 --- a/test/spec/modules/wideorbitBidAdapter_spec.js +++ /dev/null @@ -1,497 +0,0 @@ -describe('wideorbit adapter tests', function () { - var expect = require('chai').expect; - var urlParse = require('url-parse'); - - // FYI: querystringify will perform encoding/decoding - var querystringify = require('querystringify'); - - var adapter = require('modules/wideorbitBidAdapter'); - var adLoader = require('src/adloader'); - var bidmanager = require('src/bidmanager'); - - describe('creation of bid url', function () { - let stubLoadScript; - - beforeEach(function () { - stubLoadScript = sinon.stub(adLoader, 'loadScript'); - }); - - afterEach(function () { - stubLoadScript.restore(); - }); - - it('should be called only once', function () { - var params = { - bidderCode: 'wideorbit', - bids: [ - { - bidder: 'wideorbit', - params: { - pbId: 1, - pId: 101 - }, - placementCode: 'div-gpt-ad-12345-1' - }, - { - bidder: 'wideorbit', - params: { - pbId: 1, - site: 'Site 1', - page: 'Page 1', - width: 100, - height: 200, - subPublisher: 'Sub Publisher 1' - }, - placementCode: 'div-gpt-ad-12345-2' - } - ] - }; - - adapter().callBids(params); - - sinon.assert.calledOnce(stubLoadScript); - }); - - it('should fix parameters name', function () { - var params = { - bidderCode: 'wideorbit', - bids: [ - { - bidder: 'wideorbit', - params: { - PBiD: 1, - PID: 101, - ReferRer: 'http://www.foo.com?param1=param1¶m2=param2' - }, - placementCode: 'div-gpt-ad-12345-1' - }, - { - bidder: 'wideorbit', - params: { - pbid: 1, - SiTe: 'Site 1', - Page: 'Page 1', - widTH: 100, - HEIGHT: 200, - SUBPublisher: 'Sub Publisher 1' - }, - placementCode: 'div-gpt-ad-12345-2' - } - ] - }; - - adapter().callBids(params); - - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledWith(stubLoadScript, bidUrl); - - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - expect(parsedBidUrl.hostname).to.equal('p1.atemda.com') - expect(parsedBidUrl.pathname).to.equal('/JSAdservingMP.ashx') - expect(parsedBidUrlQueryString).to.have.property('pc').and.to.equal('2'); - expect(parsedBidUrlQueryString).to.have.property('pbId').and.to.equal('1'); - expect(parsedBidUrlQueryString).to.have.property('jsv').and.to.equal('1.0'); - expect(parsedBidUrlQueryString).to.have.property('tsv').and.to.equal('1.0'); - 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('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'); - expect(parsedBidUrlQueryString).to.have.property('url').and.to.equal('http://www.foo.com?param1=param1¶m2=param2'); - - expect(parsedBidUrlQueryString).to.have.property('gid0').and.to.equal('div-gpt-ad-12345-1'); - expect(parsedBidUrlQueryString).to.have.property('rpos0').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('ecpm0').and.to.equal(''); - - expect(parsedBidUrlQueryString).to.have.property('gid1').and.to.equal('div-gpt-ad-12345-2'); - expect(parsedBidUrlQueryString).to.have.property('rpos1').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('ecpm1').and.to.equal(''); - - expect(parsedBidUrlQueryString).to.have.property('pId0').and.to.equal('101'); - expect(parsedBidUrlQueryString).to.have.property('rank0').and.to.equal('0'); - - expect(parsedBidUrlQueryString).to.have.property('wsName1').and.to.equal('Site 1'); - expect(parsedBidUrlQueryString).to.have.property('wName1').and.to.equal('Page 1'); - expect(parsedBidUrlQueryString).to.have.property('rank1').and.to.equal('1'); - expect(parsedBidUrlQueryString).to.have.property('bfDim1').and.to.equal('100x200'); - expect(parsedBidUrlQueryString).to.have.property('subp1').and.to.equal('Sub Publisher 1'); - }); - - describe('placement by name', function () { - it('should be called with specific parameters for two bids', function () { - var params = { - bidderCode: 'wideorbit', - bids: [ - { - bidder: 'wideorbit', - params: { - pbId: 1, - site: 'Site 1', - page: 'Page 1', - width: 100, - height: 200, - subPublisher: 'Sub Publisher 1', - atf: true - }, - placementCode: 'div-gpt-ad-12345-1' - }, - { - bidder: 'wideorbit', - params: { - pbId: 1, - site: 'Site 2', - page: 'Page 2', - width: 200, - height: 300, - rank: 123, - ecpm: 1.8 - }, - placementCode: 'div-gpt-ad-12345-2' - } - ] - }; - - adapter().callBids(params); - - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledWith(stubLoadScript, bidUrl); - - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - expect(parsedBidUrl.hostname).to.equal('p1.atemda.com') - expect(parsedBidUrl.pathname).to.equal('/JSAdservingMP.ashx') - expect(parsedBidUrlQueryString).to.have.property('pc').and.to.equal('2'); - expect(parsedBidUrlQueryString).to.have.property('pbId').and.to.equal('1'); - expect(parsedBidUrlQueryString).to.have.property('jsv').and.to.equal('1.0'); - expect(parsedBidUrlQueryString).to.have.property('tsv').and.to.equal('1.0'); - 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('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'); - expect(parsedBidUrlQueryString).to.have.property('url').and.to.be.empty; - - expect(parsedBidUrlQueryString).to.have.property('gid0').and.to.equal('div-gpt-ad-12345-1'); - expect(parsedBidUrlQueryString).to.have.property('rpos0').and.to.equal('1001'); - expect(parsedBidUrlQueryString).to.have.property('ecpm0').and.to.equal(''); - - expect(parsedBidUrlQueryString).to.have.property('gid1').and.to.equal('div-gpt-ad-12345-2'); - expect(parsedBidUrlQueryString).to.have.property('rpos1').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('ecpm1').and.to.equal('1.8'); - - expect(parsedBidUrlQueryString).to.have.property('wsName0').and.to.equal('Site 1'); - expect(parsedBidUrlQueryString).to.have.property('wName0').and.to.equal('Page 1'); - expect(parsedBidUrlQueryString).to.have.property('rank0').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('bfDim0').and.to.equal('100x200'); - expect(parsedBidUrlQueryString).to.have.property('subp0').and.to.equal('Sub Publisher 1'); - - expect(parsedBidUrlQueryString).to.have.property('wsName1').and.to.equal('Site 2'); - expect(parsedBidUrlQueryString).to.have.property('wName1').and.to.equal('Page 2'); - expect(parsedBidUrlQueryString).to.have.property('rank1').and.to.equal('123'); - expect(parsedBidUrlQueryString).to.have.property('bfDim1').and.to.equal('200x300'); - expect(parsedBidUrlQueryString).to.have.property('subp1').and.to.equal(''); - }); - }); - - describe('placement by id', function () { - it('should be called with specific parameters for two bids', function () { - var params = { - bidderCode: 'wideorbit', - bids: [ - { - bidder: 'wideorbit', - params: { - pbId: 1, - pId: 101, - atf: true, - ecpm: 0.8 - }, - placementCode: 'div-gpt-ad-12345-1' - }, - { - bidder: 'wideorbit', - params: { - pbId: 1, - pId: 102, - rank: 123 - }, - placementCode: 'div-gpt-ad-12345-2' - } - ] - }; - - adapter().callBids(params); - - var bidUrl = stubLoadScript.getCall(0).args[0]; - - sinon.assert.calledWith(stubLoadScript, bidUrl); - - var parsedBidUrl = urlParse(bidUrl); - var parsedBidUrlQueryString = querystringify.parse(parsedBidUrl.query); - - expect(parsedBidUrl.hostname).to.equal('p1.atemda.com') - expect(parsedBidUrl.pathname).to.equal('/JSAdservingMP.ashx') - expect(parsedBidUrlQueryString).to.have.property('pc').and.to.equal('2'); - expect(parsedBidUrlQueryString).to.have.property('pbId').and.to.equal('1'); - expect(parsedBidUrlQueryString).to.have.property('jsv').and.to.equal('1.0'); - expect(parsedBidUrlQueryString).to.have.property('tsv').and.to.equal('1.0'); - 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('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'); - expect(parsedBidUrlQueryString).to.have.property('url').and.to.be.empty; - - expect(parsedBidUrlQueryString).to.have.property('gid0').and.to.equal('div-gpt-ad-12345-1'); - expect(parsedBidUrlQueryString).to.have.property('rpos0').and.to.equal('1001'); - expect(parsedBidUrlQueryString).to.have.property('ecpm0').and.to.equal('0.8'); - - expect(parsedBidUrlQueryString).to.have.property('gid1').and.to.equal('div-gpt-ad-12345-2'); - expect(parsedBidUrlQueryString).to.have.property('rpos1').and.to.equal('0'); - expect(parsedBidUrlQueryString).to.have.property('ecpm1').and.to.equal(''); - - expect(parsedBidUrlQueryString).to.have.property('pId0').and.to.equal('101'); - expect(parsedBidUrlQueryString).to.have.property('rank0').and.to.equal('0'); - - expect(parsedBidUrlQueryString).to.have.property('pId1').and.to.equal('102'); - expect(parsedBidUrlQueryString).to.have.property('rank1').and.to.equal('123'); - }); - }); - }); - - // describe('handling of the callback response', function () { - // - // var placements = [ - // { - // ExtPlacementId: 'div-gpt-ad-12345-1', - // Type: 'DirectHTML', - // Bid: 1.3, - // Width: 50, - // Height: 100, - // Source: '
The AD 1 itself...
', - // TrackingCodes: [ - // 'https://www.admeta.com/1.gif' - // ] - // }, - // { - // ExtPlacementId: 'div-gpt-ad-12345-2', - // Type: 'DirectHTML', - // Bid: 1.5, - // Width: 100, - // Height: 200, - // Source: '
The AD 2 itself...
', - // TrackingCodes: [ - // 'http://www.admeta.com/2a.gif', - // '' - // ] - // }, - // { - // ExtPlacementId: 'div-gpt-ad-12345-3', - // Type: 'Other', - // Bid: 1.7, - // Width: 150, - // Height: 250, - // Source: '
The AD 3 itself...
', - // TrackingCodes: [ - // 'http://www.admeta.com/3.gif' - // ] - // } - // ]; - // - // it('callback function should exist', function () { - // expect($$PREBID_GLOBAL$$.handleWideOrbitCallback).to.exist.and.to.be.a('function'); - // }); - // - // it('bidmanager.addBidResponse should be called thrice with correct arguments', function () { - // - // var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - // - // var params = { - // bidderCode: 'wideorbit', - // bids: [ - // { - // bidder: 'wideorbit', - // params: { - // pbId: 1, - // pId: 101 - // }, - // placementCode: 'div-gpt-ad-12345-1' - // }, - // { - // bidder: 'wideorbit', - // params: { - // pbId: 1, - // site: 'Site 1', - // page: 'Page 1', - // width: 100, - // height: 200, - // subPublisher: 'Sub Publisher 1' - // }, - // placementCode: 'div-gpt-ad-12345-2' - // }, - // { - // bidder: 'wideorbit', - // params: { - // pbId: 1, - // pId: 102 - // }, - // placementCode: 'div-gpt-ad-12345-3' - // }, - // ] - // }; - // - // var response = { - // UserMatchings: [ - // { - // Type: 'redirect', - // Url: 'http%3A%2F%2Fwww.admeta.com%2F1.gif' - // } - // ], - // Placements: placements - // }; - // - // adapter().callBids(params); - // $$PREBID_GLOBAL$$.handleWideOrbitCallback(response); - // - // var bidPlacementCode1 = stubAddBidResponse.getCall(0).args[0]; - // var bidObject1 = stubAddBidResponse.getCall(0).args[1]; - // var bidPlacementCode2 = stubAddBidResponse.getCall(1).args[0]; - // var bidObject2 = stubAddBidResponse.getCall(1).args[1]; - // var bidPlacementCode3 = stubAddBidResponse.getCall(2).args[0]; - // var bidObject3 = stubAddBidResponse.getCall(2).args[1]; - // - // expect(bidPlacementCode1).to.equal('div-gpt-ad-12345-1'); - // expect(bidObject1.cpm).to.equal(1.3); - // expect(bidObject1.ad).to.equal('
The AD 1 itself...
'); - // expect(bidObject1.width).to.equal(50); - // expect(bidObject1.height).to.equal(100); - // expect(bidObject1.getStatusCode()).to.equal(1); - // expect(bidObject1.bidderCode).to.equal('wideorbit'); - // - // expect(bidPlacementCode2).to.equal('div-gpt-ad-12345-2'); - // expect(bidObject2.cpm).to.equal(1.50); - // expect(bidObject2.ad).to.equal('
The AD 2 itself...
'); - // expect(bidObject2.width).to.equal(100); - // expect(bidObject2.height).to.equal(200); - // expect(bidObject2.getStatusCode()).to.equal(1); - // expect(bidObject2.bidderCode).to.equal('wideorbit'); - // - // expect(bidPlacementCode3).to.equal('div-gpt-ad-12345-3'); - // expect(bidObject3.getStatusCode()).to.equal(2); - // expect(bidObject3.bidderCode).to.equal('wideorbit'); - // - // sinon.assert.calledWith(stubAddBidResponse, bidPlacementCode1, bidObject1); - // sinon.assert.calledWith(stubAddBidResponse, bidPlacementCode2, bidObject2); - // sinon.assert.calledWith(stubAddBidResponse, bidPlacementCode3, bidObject3); - // - // sinon.assert.calledThrice(stubAddBidResponse); - // - // stubAddBidResponse.restore(); - // - // }); - // - // it('should append an image to the head when type is set to redirect', function () { - // - // var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - // - // var response = { - // UserMatchings: [ - // { - // Type: 'redirect', - // Url: 'http%3A%2F%2Fwww.admeta.com%2F1.gif' - // } - // ], - // Placements: placements - // }; - // - // $$PREBID_GLOBAL$$.handleWideOrbitCallback(response); - // - // var imgElement = document.querySelectorAll("head img")[0]; - // - // expect(imgElement).to.exist; - // expect(imgElement.src).to.equal('http://www.admeta.com/1.gif'); - // - // stubAddBidResponse.restore(); - // }); - // - // it('should append an iframe to the head when type is set to iframe', function () { - // - // var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - // - // var response = { - // UserMatchings: [ - // { - // Type: 'iframe', - // Url: 'http%3A%2F%2Fwww.admeta.com%2F1.ashx' - // } - // ], - // Placements: placements - // }; - // - // $$PREBID_GLOBAL$$.handleWideOrbitCallback(response); - // - // var iframeElement = document.querySelectorAll("head iframe")[0]; - // - // expect(iframeElement).to.exist; - // expect(iframeElement.src).to.equal('http://www.admeta.com/1.ashx'); - // - // stubAddBidResponse.restore(); - // - // }); - // - // it('should append an script to the head when type is set to js', function () { - // - // var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - // - // var response = { - // UserMatchings: [ - // { - // Type: 'js', - // Url: 'http%3A%2F%2Fwww.admeta.com%2F1.js' - // } - // ], - // Placements: placements - // }; - // - // $$PREBID_GLOBAL$$.handleWideOrbitCallback(response); - // - // var scriptElement = document.querySelectorAll("head script")[0]; - // - // expect(scriptElement).to.exist; - // expect(scriptElement.src).to.equal('http://www.admeta.com/1.js'); - // - // stubAddBidResponse.restore(); - // }); - // - // it('should do nothing when type is set to unrecognized type', function () { - // - // var stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); - // - // var response = { - // UserMatchings: [ - // { - // Type: 'unrecognized', - // Url: 'http%3A%2F%2Fwww.admeta.com%2F1.js' - // } - // ], - // Placements: placements - // }; - // - // $$PREBID_GLOBAL$$.handleWideOrbitCallback(response); - // - // stubAddBidResponse.restore(); - // }); - // - // }); -}); diff --git a/test/spec/modules/widespaceBidAdapter_spec.js b/test/spec/modules/widespaceBidAdapter_spec.js deleted file mode 100644 index 75486baa25b..00000000000 --- a/test/spec/modules/widespaceBidAdapter_spec.js +++ /dev/null @@ -1,226 +0,0 @@ -import { expect } from 'chai'; -import adLoader from '../../../src/adloader'; -import bidManager from '../../../src/bidmanager'; -import Adapter from '../../../modules/widespaceBidAdapter'; - -const ENDPOINT = '//engine.widespace.com/map/engine/hb/dynamic'; - -const TEST = { - BIDDER_CODE: 'widespace', - CPM: 2.0, - PLACEMENT_CODE: 'aPlacementCode', - SID: 'f666bfaf-69cf-4ed9-9262-08247bb274e4', - CUR: 'EUR' -}; - -const BID_REQUEST = { - 'bidderCode': TEST.BIDDER_CODE, - 'requestId': 'e155185b-3eac-4f3c-8182-cdb57a69df3c', - 'bidderRequestId': '38993e482321e7', - 'bids': [ - { - 'bidder': TEST.BIDDER_CODE, - 'params': { - 'sid': TEST.SID, - 'cur': TEST.CUR - }, - 'placementCode': TEST.PLACEMENT_CODE, - 'sizes': [ - [320, 320], - [320, 250] - ], - 'bidId': '45c7f5afb996c1', - 'bidderRequestId': '7101db09af0db3', - 'requestId': 'e155185b-3eac-4f3c-8182-cdb57a69df3d' - } - ], - 'start': 1479664180396, - 'timeout': 5000 -}; - -let bidRequestWithDemoData = BID_REQUEST; - -const BID_RESPONSE = [{ - 'status': 'ok', - 'reqId': '140590112507', - 'adId': 13963, - 'width': 320, - 'height': 320, - 'cpm': 2.0, - 'currency': 'EUR', - 'code': '

This is a banner

', - 'callbackUid': '45c7f5afb996c1', - 'callback': 'pbjs.widespaceHandleCB' -}]; - -const BID_NOAD_RESPONSE = [{ - 'status': 'noad', - 'reqId': '143509454349', - 'adId': 22, - 'width': 1, - 'height': 1, - 'cpm': 0.0, - 'currency': 'EUR', - 'code': '', - 'callbackUid': '45c7f5afb996c1', - 'callback': 'pbjs.widespaceHandleCB' -}] - -describe('WidespaceAdapter', () => { - let adapter; - let sandbox; - - beforeEach(() => { - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - describe('callBids', () => { - it('should exists and be a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - - describe('with valid request parameters', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(BID_REQUEST); - }); - - it('should call the endpoint once per valid bid', () => { - sinon.assert.callCount(adLoader.loadScript, 1); - }); - - it('should include required request parameters', () => { - const endpointRequest = expect(adLoader.loadScript.firstCall.args[0]); - endpointRequest.to.include('sid'); - endpointRequest.to.include('hb'); - endpointRequest.to.include('hb.ver'); - endpointRequest.to.include('hb.callbackUid'); - endpointRequest.to.include('hb.callback'); - endpointRequest.to.include('hb.sizes'); - endpointRequest.to.include('hb.name'); - }); - }); - - describe('with valid request parameters (demo data)', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - bidRequestWithDemoData = BID_REQUEST; - }); - - it('should include required request parameters', () => { - bidRequestWithDemoData.bids[0].params.demo = { - gender: 'F', - country: 'UK', - region: 'Greater London', - postal: 'W1U 8EW', - city: 'London', - yob: 1981 - }; - - adapter.callBids(bidRequestWithDemoData); - - const endpointRequest = expect(adLoader.loadScript.firstCall.args[0]); - endpointRequest.to.include('hb.demo.gender'); - endpointRequest.to.include('hb.demo.country'); - endpointRequest.to.include('hb.demo.region'); - endpointRequest.to.include('hb.demo.postal'); - endpointRequest.to.include('hb.demo.city'); - endpointRequest.to.include('hb.demo.yob'); - }); - - it('should not include "hb.demo.gender" as a request parameter, if it hasn\'t been specified', () => { - bidRequestWithDemoData.bids[0].params.demo = { - country: 'UK', - region: 'Greater London', - postal: 'W1U 8EW', - city: 'London', - yob: 1981 - }; - - adapter.callBids(bidRequestWithDemoData); - - const endpointRequest = expect(adLoader.loadScript.firstCall.args[0]); - endpointRequest.to.not.include('hb.demo.gender'); - }); - }); - - describe('with unvalid request parameters', () => { - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - }); - - it('should not call the endpoint with if there is no request parameters', () => { - adapter.callBids({}); - sinon.assert.callCount(adLoader.loadScript, 0); - }); - }); - }); - - describe('widespaceHandleCB', () => { - it('should exist and be a function', () => { - expect($$PREBID_GLOBAL$$.widespaceHandleCB).to.exist.and.to.be.a('function'); - }); - }); - - describe('respond with a successful bid', () => { - let successfulBid, - placementCode; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - sandbox.stub(adLoader, 'loadScript'); - - adapter.callBids(BID_REQUEST); - $$PREBID_GLOBAL$$._bidsRequested.push(BID_REQUEST); - $$PREBID_GLOBAL$$.widespaceHandleCB(BID_RESPONSE); - - successfulBid = bidManager.addBidResponse.firstCall.args[1]; - placementCode = bidManager.addBidResponse.firstCall.args[0]; - }); - - it('should add one bid', () => { - sinon.assert.calledOnce(bidManager.addBidResponse); - }); - - it('should use the CPM returned by the server', () => { - expect(successfulBid).to.have.property('cpm', TEST.CPM); - }); - - it('should have an OK statusCode', () => { - expect(successfulBid.getStatusCode()).to.eql(1); - }); - - it('should have a valid size', () => { - const bidSize = [successfulBid.width, successfulBid.height] - expect(bidSize).to.eql(BID_REQUEST.bids[0].sizes[0]); - }); - - it('should recive right placementCode', () => { - expect(placementCode).to.eql(TEST.PLACEMENT_CODE); - }); - }); - - describe('respond with a no-ad', () => { - let noadBid; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - sandbox.stub(adLoader, 'loadScript'); - - adapter.callBids(BID_REQUEST); - $$PREBID_GLOBAL$$._bidsRequested.push(BID_REQUEST); - $$PREBID_GLOBAL$$.widespaceHandleCB(BID_NOAD_RESPONSE); - - noadBid = bidManager.addBidResponse.firstCall.args[1]; - }); - - it('should have an error statusCode', () => { - expect(noadBid.getStatusCode()).to.eql(2); - }); - }); -}); diff --git a/test/spec/modules/yieldbotBidAdapter_spec.js b/test/spec/modules/yieldbotBidAdapter_spec.js deleted file mode 100644 index f7bbcbdb414..00000000000 --- a/test/spec/modules/yieldbotBidAdapter_spec.js +++ /dev/null @@ -1,518 +0,0 @@ -import {expect} from 'chai'; -import YieldbotAdapter from 'modules/yieldbotBidAdapter'; -import bidManager from 'src/bidmanager'; -import adLoader from 'src/adloader'; -import {deepClone} from 'src/utils'; - -const bidderRequest = { - bidderCode: 'yieldbot', - bidder: 'yieldbot', - bidderRequestId: '187a340cb9ccc5', - bids: [ - { - bidId: '2640ad280208cc', - sizes: [[300, 250], [300, 600]], - bidder: 'yieldbot', - bidderRequestId: '187a340cb9ccc0', - params: { psn: '1234', slot: 'medrec' }, - requestId: '5f297a1f-3163-46c2-854f-b55fd2e74ec0', - placementCode: '/4294967296/adunit0' - }, - { - bidId: '35751f10be5b6b', - sizes: [[728, 90], [970, 90]], - bidder: 'yieldbot', - bidderRequestId: '187a340cb9ccc1', - params: { psn: '1234', slot: 'leaderboard' }, - requestId: '5f297a1f-3163-46c2-854f-b55fd2e74ec1', - placementCode: '/4294967296/adunit1' - }, - { - bidId: '2640ad280208cd', - sizes: [[300, 250]], - bidder: 'yieldbot', - bidderRequestId: '187a340cb9ccc2', - params: { psn: '1234', slot: 'medrec' }, - requestId: '5f297a1f-3163-46c2-854f-b55fd2e74ec2', - placementCode: '/4294967296/adunit2' - }, - ] -}; - -const YB_BID_FIXTURE = { - medrec: { - ybot_ad: 'y', - ybot_slot: 'medrec', - ybot_cpm: '200', - ybot_size: '300x250' - }, - leaderboard: { - ybot_ad: 'n' - }, - noop: { - ybot_ad: 'y', - ybot_slot: 'noop', - ybot_cpm: '200', - ybot_size: '300x250' - } -}; - -function createYieldbotMockLib() { - window.yieldbot = { - _initialized: false, - pub: (psn) => {}, - defineSlot: (slotName, optionalDomIdOrConfigObject, optionalTime) => {}, - enableAsync: () => {}, - go: () => {}, - nextPageview: (slots, callback) => {}, - getSlotCriteria: (slotName) => {} - }; -} - -function restoreYieldbotMockLib() { - window.yieldbot = null; -} - -function mockYieldbotBidRequest() { - window.ybotq = window.ybotq || []; - window.ybotq.forEach(fn => { - fn.apply(window.yieldbot); - }); - window.ybotq = []; -} - -const localSetupTestRegex = /localSetupTest$/; -const MAKE_BID_REQUEST = true; -let sandbox; -let bidManagerStub; -let yieldbotLibStub; - -/** - * Test initialization hook. Makes initial adapter and mock bid requests
- * unless the test is a special case with "localSetupTest".
- * 1. All suite tests are initialized with required mocks and stubs
- * 2. If the test title does not end in "localSetupTest", adapter and - * mock bid requests are executed - * 3. Test titles ending in "localSetupTest" are special case tests and are - * expected to call setupTest(object, MAKE_BID_REQUEST) where - * applicable - * @param {object} testRequest bidder request bids fixture - * @param {boolean} force trigger adapter callBids and Yieldbot library request - * @private - */ -function setupTest(testRequest, force = false) { - sandbox = sinon.sandbox.create(); - - createYieldbotMockLib(); - - sandbox.stub(adLoader, 'loadScript'); - - yieldbotLibStub = {}; - yieldbotLibStub.nextPageview = sandbox.stub(window.yieldbot, 'nextPageview'); - yieldbotLibStub.defineSlot = sandbox.stub(window.yieldbot, 'defineSlot'); - yieldbotLibStub.pub = sandbox.stub(window.yieldbot, 'pub'); - yieldbotLibStub.enableAsync = sandbox.stub(window.yieldbot, 'enableAsync'); - - yieldbotLibStub.getSlotCriteria = - sandbox.stub( - window.yieldbot, - 'getSlotCriteria', - (slotName) => { - return YB_BID_FIXTURE[slotName] || {ybot_ad: 'n'}; - }); - - yieldbotLibStub.go = - sandbox.stub( - window.yieldbot, - 'go', - () => { - window.yieldbot._initialized = true; - }); - - bidManagerStub = sandbox.stub(bidManager, 'addBidResponse'); - - const ybAdapter = new YieldbotAdapter(); - let request = testRequest || deepClone(bidderRequest); - if ((this && !this.currentTest.parent.title.match(localSetupTestRegex)) || force === MAKE_BID_REQUEST) { - ybAdapter.callBids(request); - mockYieldbotBidRequest(); - } - return { adapter: ybAdapter, localRequest: request }; -} - -function restoreTest() { - sandbox.restore(); - restoreYieldbotMockLib(); -} - -describe('Yieldbot adapter tests', function() { - let adapter; - let localRequest; - beforeEach(function () { - const testSetupCtx = setupTest.call(this); - adapter = testSetupCtx.adapter; - localRequest = testSetupCtx.localRequest; - }); - - afterEach(function() { - restoreTest(); - }); - - describe('getUniqueSlotSizes', function() { - it('should return [] for string sizes', function() { - const sizes = adapter.getUniqueSlotSizes('widthxheight'); - expect(sizes).to.deep.equal([]); - }); - - it('should return [] for Object sizes', function() { - const sizes = adapter.getUniqueSlotSizes({width: 300, height: 250}); - expect(sizes).to.deep.equal([]); - }); - - it('should return [] for boolean sizes', function() { - const sizes = adapter.getUniqueSlotSizes(true); - expect(sizes).to.deep.equal([]); - }); - - it('should return [] for undefined sizes', function() { - const sizes = adapter.getUniqueSlotSizes(undefined); - expect(sizes).to.deep.equal([]); - }); - - it('should return [] for function sizes', function() { - const sizes = adapter.getUniqueSlotSizes(function () {}); - expect(sizes).to.deep.equal([]); - }); - - it('should return [] for number sizes', function() { - const sizes = adapter.getUniqueSlotSizes(1111); - expect(sizes).to.deep.equal([]); - }); - - it('should return [] for array of numbers', function() { - const sizes = adapter.getUniqueSlotSizes([300, 250]); - expect(sizes).to.deep.equal([]); - }); - - it('should return array of unique strings', function() { - const sizes = adapter.getUniqueSlotSizes(['300x250', '300x600', '728x90', '300x250']); - expect(sizes).to.deep.equal([['300', '250'], ['300', '600'], ['728', '90']]); - }); - - it('should return array of unique strings for string elements only', function() { - const sizes = adapter.getUniqueSlotSizes(['300x250', ['threexfour']]); - expect(sizes).to.deep.equal([['300', '250']]); - }); - - it('should return array of unique strings, including non-numeric', function() { - const sizes = adapter.getUniqueSlotSizes(['300x250', 'threexfour', 'fivexsix']); - expect(sizes).to.deep.equal([['300', '250'], ['three', 'four'], ['five', 'si']]); - }); - }); - - describe('callBids', function() { - it('should request the yieldbot library', function() { - sinon.assert.calledOnce(adLoader.loadScript); - sinon.assert.calledWith(adLoader.loadScript, '//cdn.yldbt.com/js/yieldbot.intent.js'); - }); - - it('should set a yieldbot psn', function() { - sinon.assert.called(yieldbotLibStub.pub); - sinon.assert.calledWith(yieldbotLibStub.pub, '1234'); - }); - - it('should not repeat multiply defined slot sizes', function() { - sinon.assert.calledTwice(yieldbotLibStub.defineSlot); - sinon.assert.neverCalledWith(yieldbotLibStub.defineSlot, 'medrec', {sizes: [['300', '250'], ['300', '600'], ['300', '250']]}); - }); - - it('should define yieldbot slots', function() { - sinon.assert.calledTwice(yieldbotLibStub.defineSlot); - sinon.assert.calledWith(yieldbotLibStub.defineSlot, 'medrec', {sizes: [['300', '250'], ['300', '600']]}); - sinon.assert.calledWith(yieldbotLibStub.defineSlot, 'leaderboard', {sizes: [['728', '90'], ['970', '90']]}); - }); - - it('should not use inherited Object properties, localSetupTest', function() { - let oProto = Object.prototype; - oProto.superProp = ['300', '250']; - - expect(Object.prototype.superProp).to.be.an('array'); - localRequest.bids.forEach((bid) => { - expect(bid.superProp).to.be.an('array'); - }); - - expect(YB_BID_FIXTURE.medrec.superProp).to.deep.equal(['300', '250']); - expect(YB_BID_FIXTURE.leaderboard.superProp).to.deep.equal(['300', '250']); - - restoreTest(); - setupTest(localRequest, MAKE_BID_REQUEST); - - sinon.assert.neverCalledWith(yieldbotLibStub.defineSlot, 'superProp', {sizes: ['300', '250']}); - sinon.assert.calledWith(yieldbotLibStub.defineSlot, 'medrec', {sizes: [['300', '250'], ['300', '600']]}); - sinon.assert.calledWith(yieldbotLibStub.defineSlot, 'leaderboard', {sizes: [['728', '90'], ['970', '90']]}); - - delete oProto.superProp; - expect(Object.prototype.superProp).to.be.an('undefined'); - }); - - it('should enable yieldbot async mode', function() { - sinon.assert.called(yieldbotLibStub.enableAsync); - }); - - it('should add bid response after yieldbot request callback', function() { - const plc1 = bidManagerStub.firstCall.args[0]; - expect(plc1).to.equal(localRequest.bids[0].placementCode); - - const pb_bid1 = bidManagerStub.firstCall.args[1]; - expect(pb_bid1.bidderCode).to.equal('yieldbot'); - expect(pb_bid1.cpm).to.equal(2); - expect(pb_bid1.ybot_ad).to.equal('y'); - expect(pb_bid1.ybot_slot).to.equal('medrec'); - expect(pb_bid1.ybot_cpm).to.equal('200'); - expect(pb_bid1.ybot_size).to.equal('300x250'); - - expect(pb_bid1.width).to.equal('300'); - expect(pb_bid1.height).to.equal('250'); - expect(pb_bid1.ad).to.match(/src="\/\/cdn\.yldbt\.com\/js\/yieldbot\.intent\.js/); - expect(pb_bid1.ad).to.match(/yieldbot\.renderAd\('medrec:300x250'\)/); - - const plc2 = bidManagerStub.secondCall.args[0]; - expect(plc2).to.equal(localRequest.bids[1].placementCode); - - const pb_bid2 = bidManagerStub.secondCall.args[1]; - expect(pb_bid2.bidderCode).to.equal('yieldbot'); - expect(pb_bid2.width).to.equal(0); - expect(pb_bid2.height).to.equal(0); - expect(pb_bid2.statusMessage).to.match(/empty.*response/); - }); - - it('should validate slot dimensions, localSetupTest', function() { - let invalidSizeBid = { - bidId: '2640ad280208ce', - sizes: [[728, 90], [300, 250], [970, 90]], - bidder: 'yieldbot', - bidderRequestId: '187a340cb9ccc3', - params: { psn: '1234', slot: 'medrec' }, - requestId: '5f297a1f-3163-46c2-854f-b55fd2e74ec3', - placementCode: '/4294967296/adunit3' - }; - - const bidResponseMedrec = { - bidderCode: 'yieldbot', - width: '300', - height: '250', - statusMessage: 'Bid available', - cpm: 2, - ybot_ad: 'y', - ybot_slot: 'medrec', - ybot_cpm: '200', - ybot_size: '300x250' - }; - - localRequest.bids = [invalidSizeBid]; - restoreTest(); - setupTest(localRequest, MAKE_BID_REQUEST); - - let bidManagerFirstCall = bidManagerStub.firstCall; - - expect(bidManagerFirstCall.args[0]).to.equal('/4294967296/adunit3'); - expect(bidManagerFirstCall.args[1]).to.include(bidResponseMedrec); - }); - - it('should make slot bid available once only', function() { - const bidResponseMedrec = { - bidderCode: 'yieldbot', - width: '300', - height: '250', - statusMessage: 'Bid available', - cpm: 2, - ybot_ad: 'y', - ybot_slot: 'medrec', - ybot_cpm: '200', - ybot_size: '300x250' - }; - - const bidResponseNone = { - bidderCode: 'yieldbot', - width: 0, - height: 0, - statusMessage: 'Bid returned empty or error response' - }; - - let firstCall = bidManagerStub.firstCall; - let secondCall = bidManagerStub.secondCall; - let thirdCall = bidManagerStub.thirdCall; - - expect(firstCall.args[0]).to.equal('/4294967296/adunit0'); - expect(firstCall.args[1]).to.include(bidResponseMedrec); - - expect(secondCall.args[0]).to.equal('/4294967296/adunit1'); - expect(secondCall.args[1]).to.include(bidResponseNone); - - expect(thirdCall.args[0]).to.equal('/4294967296/adunit2'); - expect(thirdCall.args[1]).to.include(bidResponseNone); - }); - }); - - describe('callBids, refresh', function() { - it('should use yieldbot.nextPageview after first callBids', function() { - expect(window.yieldbot._initialized).to.equal(true); - - adapter.callBids(localRequest); - mockYieldbotBidRequest(); - sinon.assert.calledOnce(yieldbotLibStub.nextPageview); - }); - - it('should call yieldbot.nextPageview with slot config of requested bids', function() { - expect(window.yieldbot._initialized).to.equal(true); - sinon.assert.calledWith(yieldbotLibStub.defineSlot, 'medrec'); - sinon.assert.calledWith(yieldbotLibStub.defineSlot, 'leaderboard'); - - const refreshBids = localRequest.bids.filter((object) => { return object.placementCode === '/4294967296/adunit1'; }); - let refreshRequest = deepClone(localRequest); - refreshRequest.bids = refreshBids; - expect(refreshRequest.bids.length).to.equal(1); - - adapter.callBids(refreshRequest); - mockYieldbotBidRequest(); - - const expectedSlots = { 'leaderboard': [['728', '90'], ['970', '90']] }; - - sinon.assert.calledWithExactly(yieldbotLibStub.nextPageview, expectedSlots); - }); - - it('should not repeat multiply defined slot sizes', function() { - // placementCode: '/4294967296/adunit0' - // placementCode: '/4294967296/adunit2' - // Both placements declare medrec:300x250 - adapter.callBids(localRequest); - mockYieldbotBidRequest(); - - sinon.assert.calledOnce(yieldbotLibStub.nextPageview); - const expectedSlots = { 'leaderboard': [['728', '90'], ['970', '90']], 'medrec': [['300', '250'], ['300', '600']]}; - sinon.assert.calledWithExactly(yieldbotLibStub.nextPageview, expectedSlots); - }); - - it('should not add empty bidResponse on callBids without bidsRequested', function() { - expect(window.yieldbot._initialized).to.equal(true); - expect(bidManagerStub.calledThrice).to.equal(true); - - adapter.callBids({}); - mockYieldbotBidRequest(); - - expect(bidManagerStub.calledThrice).to.equal(true); // the initial bids - sinon.assert.notCalled(yieldbotLibStub.nextPageview); - }); - - it('should validate slot dimensions', function() { - localRequest.bids.map(bid => { - bid.sizes = [[640, 480], [1024, 768]]; - }); - - const bidResponseNone = { - bidderCode: 'yieldbot', - width: 0, - height: 0, - statusMessage: 'Bid returned empty or error response' - }; - - adapter.callBids(localRequest); - mockYieldbotBidRequest(); - - expect(bidManagerStub.getCalls().length).to.equal(6); - - let lastNextPageview = yieldbotLibStub.nextPageview.lastCall; - let nextPageviewSlots = lastNextPageview.args[0]; - expect(nextPageviewSlots.medrec).to.deep.equal([['640', '480'], ['1024', '768']]); - expect(nextPageviewSlots.leaderboard).to.deep.equal([['640', '480'], ['1024', '768']]); - - let fourthCall = bidManagerStub.getCall(3); - let fifthCall = bidManagerStub.getCall(4); - let sixthCall = bidManagerStub.getCall(5); - - expect(fourthCall.args[0]).to.equal('/4294967296/adunit0'); - expect(fourthCall.args[1]).to.include(bidResponseNone); - - expect(fifthCall.args[0]).to.equal('/4294967296/adunit1'); - expect(fifthCall.args[1]).to.include(bidResponseNone); - - expect(sixthCall.args[0]).to.equal('/4294967296/adunit2'); - expect(sixthCall.args[1]).to.include(bidResponseNone); - }); - - it('should not make requests for previously requested bids', function() { - const bidResponseMedrec = { - bidderCode: 'yieldbot', - width: '300', - height: '250', - statusMessage: 'Bid available', - cpm: 2, - ybot_ad: 'y', - ybot_slot: 'medrec', - ybot_cpm: '200', - ybot_size: '300x250' - }; - - const bidResponseNone = { - bidderCode: 'yieldbot', - width: 0, - height: 0, - statusMessage: 'Bid returned empty or error response' - }; - - // Refresh #1 - adapter.callBids(localRequest); - mockYieldbotBidRequest(); - - expect(bidManagerStub.getCalls().length).to.equal(6); - - let lastNextPageview = yieldbotLibStub.nextPageview.lastCall; - let nextPageviewSlots = lastNextPageview.args[0]; - expect(nextPageviewSlots.medrec).to.deep.equal([['300', '250'], ['300', '600']]); - expect(nextPageviewSlots.leaderboard).to.deep.equal([['728', '90'], ['970', '90']]); - - let fourthCall = bidManagerStub.getCall(3); - let fifthCall = bidManagerStub.getCall(4); - let sixthCall = bidManagerStub.getCall(5); - - expect(fourthCall.args[0]).to.equal('/4294967296/adunit0'); - expect(fourthCall.args[1]).to.include(bidResponseMedrec); - - expect(fifthCall.args[0]).to.equal('/4294967296/adunit1'); - expect(fifthCall.args[1]).to.include(bidResponseNone); - - expect(sixthCall.args[0]).to.equal('/4294967296/adunit2'); - expect(sixthCall.args[1]).to.include(bidResponseNone); - - localRequest.bids.map(bid => { - bid.sizes = [[640, 480], [1024, 768]]; - }); - let bidForNinethCall = localRequest.bids[localRequest.bids.length - 1]; - bidForNinethCall.sizes = [[300, 250]]; - - // Refresh #2 - adapter.callBids(localRequest); - mockYieldbotBidRequest(); - - expect(bidManagerStub.getCalls().length).to.equal(9); - - lastNextPageview = yieldbotLibStub.nextPageview.lastCall; - nextPageviewSlots = lastNextPageview.args[0]; - expect(nextPageviewSlots.medrec).to.deep.equal([['640', '480'], ['1024', '768'], ['300', '250']]); - expect(nextPageviewSlots.leaderboard).to.deep.equal([['640', '480'], ['1024', '768']]); - - let seventhCall = bidManagerStub.getCall(6); - let eighthCall = bidManagerStub.getCall(7); - let ninethCall = bidManagerStub.getCall(8); - - expect(seventhCall.args[0]).to.equal('/4294967296/adunit0'); - expect(seventhCall.args[1]).to.include(bidResponseNone); - - expect(eighthCall.args[0]).to.equal('/4294967296/adunit1'); - expect(eighthCall.args[1]).to.include(bidResponseNone); - - expect(ninethCall.args[0]).to.equal('/4294967296/adunit2'); - expect(ninethCall.args[1]).to.include(bidResponseMedrec); - }); - }); -}); diff --git a/test/spec/modules/yieldmoBidAdapter_spec.js b/test/spec/modules/yieldmoBidAdapter_spec.js deleted file mode 100644 index d2a533be17e..00000000000 --- a/test/spec/modules/yieldmoBidAdapter_spec.js +++ /dev/null @@ -1,209 +0,0 @@ -import {expect} from 'chai'; -import Adapter from '../../../modules/yieldmoBidAdapter'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; -import {parse as parseURL} from '../../../src/url'; - -describe('Yieldmo adapter', () => { - let bidsRequestedOriginal; - let adapter; - let sandbox; - - const bidderRequest = { - bidderCode: 'yieldmo', - bids: [ - { - bidId: 'bidId1', - bidder: 'yieldmo', - placementCode: 'foo', - sizes: [[728, 90]] - }, - { - bidId: 'bidId2', - bidder: 'yieldmo', - placementCode: 'bar', - sizes: [[300, 600], [300, 250]] - } - ] - }; - - beforeEach(() => { - bidsRequestedOriginal = $$PREBID_GLOBAL$$._bidsRequested; - $$PREBID_GLOBAL$$._bidsRequested = []; - - adapter = new Adapter(); - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - - $$PREBID_GLOBAL$$._bidsRequested = bidsRequestedOriginal; - }); - - describe('callBids', () => { - let bidRequestURL; - - beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(bidderRequest); - - bidRequestURL = adLoader.loadScript.firstCall.args[0]; - }); - - it('should load a script with passed bid params', () => { - let route = 'http://ads.yieldmo.com/exchange/prebid?'; - let requestParams = parseURL(bidRequestURL).search; - let parsedPlacementParams = JSON.parse(decodeURIComponent(requestParams.p)); - - sinon.assert.calledOnce(adLoader.loadScript); - expect(bidRequestURL).to.contain(route); - - // placement 1 - expect(parsedPlacementParams[0]).to.have.property('callback_id', 'bidId1'); - expect(parsedPlacementParams[0]).to.have.property('placement_id', 'foo'); - expect(parsedPlacementParams[0].sizes[0][0]).to.equal(728); - expect(parsedPlacementParams[0].sizes[0][1]).to.equal(90); - - // placement 2 - expect(parsedPlacementParams[1]).to.have.property('callback_id', 'bidId2'); - expect(parsedPlacementParams[1]).to.have.property('placement_id', 'bar'); - expect(parsedPlacementParams[1].sizes[0][0]).to.equal(300); - expect(parsedPlacementParams[1].sizes[0][1]).to.equal(600); - expect(parsedPlacementParams[1].sizes[1][0]).to.equal(300); - 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('page_url'); - }); - }); - - describe('YMCB', () => { - it('should exist and be a function', () => { - expect($$PREBID_GLOBAL$$.YMCB).to.exist.and.to.be.a('function'); - }); - }); - - describe('add bids to the manager', () => { - let firstBid; - let secondBid; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // respond - let bidderReponse = [{ - 'cpm': 3.45455, - 'width': 300, - 'height': 250, - 'callback_id': 'bidId1', - 'ad': 'HELLO YIELDMO AD' - }, { - 'cpm': 4.35455, - 'width': 400, - 'height': 350, - 'callback_id': 'bidId2', - 'ad': 'HELLO YIELDMO AD' - }]; - - $$PREBID_GLOBAL$$.YMCB(bidderReponse); - - firstBid = bidManager.addBidResponse.firstCall.args[1]; - secondBid = bidManager.addBidResponse.secondCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledTwice(bidManager.addBidResponse); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidManager.addBidResponse.firstCall.args[0]; - let secondPlacementCode = bidManager.addBidResponse.secondCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - expect(secondPlacementCode).to.eql('bar'); - }); - - it('should have a good statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(1); - expect(secondBid.getStatusCode()).to.eql(1); - }); - - it('should add the CPM to the bid object', () => { - expect(firstBid).to.have.property('cpm', 3.45455); - expect(secondBid).to.have.property('cpm', 4.35455); - }); - - it('should add the bidder code to the bid object', () => { - expect(firstBid).to.have.property('bidderCode', 'yieldmo'); - expect(secondBid).to.have.property('bidderCode', 'yieldmo'); - }); - - it('should include the ad on the bid object', () => { - expect(firstBid).to.have.property('ad'); - expect(secondBid).to.have.property('ad'); - }); - - it('should include the size on the bid object', () => { - expect(firstBid).to.have.property('width', 300); - expect(firstBid).to.have.property('height', 250); - expect(secondBid).to.have.property('width', 400); - expect(secondBid).to.have.property('height', 350); - }); - }); - - describe('add empty bids if no bid returned', () => { - let firstBid; - let secondBid; - - beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - - $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); - - // respond - let bidderReponse = [{ - 'status': 'no_bid', - 'callback_id': 'bidId1' - }, { - 'status': 'no_bid', - 'callback_id': 'bidId2' - }]; - - $$PREBID_GLOBAL$$.YMCB(bidderReponse); - - firstBid = bidManager.addBidResponse.firstCall.args[1]; - secondBid = bidManager.addBidResponse.secondCall.args[1]; - }); - - it('should add a bid object for each bid', () => { - sinon.assert.calledTwice(bidManager.addBidResponse); - }); - - it('should include the bid request bidId as the adId', () => { - expect(firstBid).to.have.property('adId', 'bidId1'); - expect(secondBid).to.have.property('adId', 'bidId2'); - }); - - it('should have an error statusCode', () => { - expect(firstBid.getStatusCode()).to.eql(2); - expect(secondBid.getStatusCode()).to.eql(2); - }); - - it('should pass the correct placement code as first param', () => { - let firstPlacementCode = bidManager.addBidResponse.firstCall.args[0]; - let secondPlacementCode = bidManager.addBidResponse.secondCall.args[0]; - - expect(firstPlacementCode).to.eql('foo'); - expect(secondPlacementCode).to.eql('bar'); - }); - - it('should add the bidder code to the bid object', () => { - expect(firstBid).to.have.property('bidderCode', 'yieldmo'); - expect(secondBid).to.have.property('bidderCode', 'yieldmo'); - }); - }); -}); diff --git a/test/spec/renderer_spec.js b/test/spec/renderer_spec.js index 282c4841ac0..4761a914bb8 100644 --- a/test/spec/renderer_spec.js +++ b/test/spec/renderer_spec.js @@ -2,19 +2,26 @@ import { expect } from 'chai'; import { Renderer } from 'src/Renderer'; describe('Renderer: A renderer installed on a bid response', () => { - const testRenderer1 = Renderer.install({ - url: 'https://httpbin.org/post', - config: { test: 'config1' }, - id: 1 - }); - const testRenderer2 = Renderer.install({ - url: 'https://httpbin.org/post', - config: { test: 'config2' }, - id: 2 - }); + let testRenderer1; + let testRenderer2; + let spyRenderFn; + let spyEventHandler; + + beforeEach(() => { + testRenderer1 = Renderer.install({ + url: 'https://httpbin.org/post', + config: { test: 'config1' }, + id: 1 + }); + testRenderer2 = Renderer.install({ + url: 'https://httpbin.org/post', + config: { test: 'config2' }, + id: 2 + }); - const spyRenderFn = sinon.spy(); - const spyEventHandler = sinon.spy(); + spyRenderFn = sinon.spy(); + spyEventHandler = sinon.spy(); + }); it('is an instance of Renderer', () => { expect(testRenderer1 instanceof Renderer).to.equal(true); @@ -34,12 +41,11 @@ describe('Renderer: A renderer installed on a bid response', () => { it('sets a render function with setRender method', () => { testRenderer1.setRender(spyRenderFn); expect(typeof testRenderer1.render).to.equal('function'); - testRenderer1.render(); expect(spyRenderFn.called).to.equal(true); }); - it('sets event handlers with setEventHandlers method', () => { + it('sets event handlers with setEventHandlers method and handles events with installed handlers', () => { testRenderer1.setEventHandlers({ testEvent: spyEventHandler }); @@ -47,16 +53,13 @@ describe('Renderer: A renderer installed on a bid response', () => { expect(testRenderer1.handlers).to.deep.equal({ testEvent: spyEventHandler }); - }); - it('handles events with installed handlers', () => { testRenderer1.handleVideoEvent({ id: 1, eventName: 'testEvent' }); expect(spyEventHandler.called).to.equal(true); }); it('pushes commands to queue if renderer is not loaded', () => { testRenderer1.push(spyRenderFn); - expect(testRenderer1.cmd.length).to.equal(1); // clear queue for next tests @@ -70,6 +73,7 @@ describe('Renderer: A renderer installed on a bid response', () => { testRenderer1.push(func); expect(testRenderer1.cmd.length).to.equal(0); + sinon.assert.calledOnce(func); }); diff --git a/test/spec/sizeMapping_spec.js b/test/spec/sizeMapping_spec.js index 471d3ba2752..24a6063cf7d 100644 --- a/test/spec/sizeMapping_spec.js +++ b/test/spec/sizeMapping_spec.js @@ -1,123 +1,195 @@ import { expect } from 'chai'; -import * as sizeMapping from 'src/sizeMapping'; - -var validAdUnit = { - 'sizes': [300, 250], - 'sizeMapping': [ - { - 'minWidth': 1024, - 'sizes': [[300, 250], [728, 90]] - }, - { - 'minWidth': 480, - 'sizes': [120, 60] - }, - { - 'minWidth': 0, - 'sizes': [20, 20] - } - ] -}; - -var invalidAdUnit = { - 'sizes': [300, 250], - 'sizeMapping': {} // wrong type -}; - -var invalidAdUnit2 = { - 'sizes': [300, 250], - 'sizeMapping': [{ - foo: 'bar' // bad - }] -}; - -let mockWindow = {}; - -function resetMockWindow() { - mockWindow = { - document: { - body: { - clientWidth: 1024 - }, - documentElement: { - clientWidth: 1024 +import { resolveStatus, setSizeConfig } from 'src/sizeMapping'; +import includes from 'core-js/library/fn/array/includes'; + +describe('sizeMapping', () => { + var testSizes = [[970, 90], [728, 90], [300, 250], [300, 100], [80, 80]]; + + var sizeConfig = [{ + 'mediaQuery': '(min-width: 1200px)', + 'sizesSupported': [ + [970, 90], + [728, 90], + [300, 250] + ] + }, { + 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', + 'sizesSupported': [ + [728, 90], + [300, 250], + [300, 100] + ] + }, { + 'mediaQuery': '(min-width: 0px) and (max-width: 767px)', + 'sizesSupported': [] + }]; + + var sizeConfigWithLabels = [{ + 'mediaQuery': '(min-width: 1200px)', + 'labels': ['desktop'] + }, { + 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', + 'sizesSupported': [ + [728, 90], + [300, 250] + ], + 'labels': ['tablet', 'phone'] + }, { + 'mediaQuery': '(min-width: 0px) and (max-width: 767px)', + 'sizesSupported': [ + [300, 250], + [300, 100] + ], + 'labels': ['phone'] + }]; + + let sandbox, + matchMediaOverride; + + beforeEach(() => { + setSizeConfig(sizeConfig); + + sandbox = sinon.sandbox.create(); + + matchMediaOverride = {matches: false}; + + sandbox.stub(window, 'matchMedia', (...args) => { + if (typeof matchMediaOverride === 'function') { + return matchMediaOverride.apply(window, args); } - }, - innerWidth: 1024 - }; -} - -describe('sizeMapping', function() { - beforeEach(resetMockWindow); - - it('minWidth should be inclusive', function() { - mockWindow.innerWidth = 1024; - sizeMapping.setWindow(mockWindow); - let sizes = sizeMapping.mapSizes(validAdUnit); - expect(sizes).to.deep.equal([[300, 250], [728, 90]]); + return matchMediaOverride; + }); }); - it('mapSizes 1029 width', function() { - mockWindow.innerWidth = 1029; - sizeMapping.setWindow(mockWindow); - let sizes = sizeMapping.mapSizes(validAdUnit); - expect(sizes).to.deep.equal([[300, 250], [728, 90]]); - expect(validAdUnit.sizes).to.deep.equal([300, 250]); - }); + afterEach(() => { + setSizeConfig([]); - it('mapSizes 400 width', function() { - mockWindow.innerWidth = 400; - sizeMapping.setWindow(mockWindow); - let sizes = sizeMapping.mapSizes(validAdUnit); - expect(sizes).to.deep.equal([20, 20]); - expect(validAdUnit.sizes).to.deep.equal([300, 250]); + sandbox.restore(); }); - it('mapSizes - invalid adUnit - should return sizes', function() { - mockWindow.innerWidth = 1029; - sizeMapping.setWindow(mockWindow); - let sizes = sizeMapping.mapSizes(invalidAdUnit); - expect(sizes).to.deep.equal([300, 250]); - expect(invalidAdUnit.sizes).to.deep.equal([300, 250]); - - mockWindow.innerWidth = 400; - sizeMapping.setWindow(mockWindow); - sizes = sizeMapping.mapSizes(invalidAdUnit); - expect(sizes).to.deep.equal([300, 250]); - expect(invalidAdUnit.sizes).to.deep.equal([300, 250]); - }); + describe('when handling sizes', () => { + it('when one mediaQuery block matches, it should filter the adUnit.sizes passed in', () => { + matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; - it('mapSizes - should return desktop (largest) sizes if screen width not detected', function() { - mockWindow.innerWidth = 0; - mockWindow.document.body.clientWidth = 0; - mockWindow.document.documentElement.clientWidth = 0; - sizeMapping.setWindow(mockWindow); - let sizes = sizeMapping.mapSizes(validAdUnit); - expect(sizes).to.deep.equal([[300, 250], [728, 90]]); - expect(validAdUnit.sizes).to.deep.equal([300, 250]); - }); + let status = resolveStatus(undefined, testSizes, sizeConfig); - it('mapSizes - should return sizes if sizemapping improperly defined ', function() { - mockWindow.innerWidth = 0; - mockWindow.document.body.clientWidth = 0; - mockWindow.document.documentElement.clientWidth = 0; - sizeMapping.setWindow(mockWindow); - let sizes = sizeMapping.mapSizes(invalidAdUnit2); - expect(sizes).to.deep.equal([300, 250]); - expect(validAdUnit.sizes).to.deep.equal([300, 250]); - }); + expect(status).to.deep.equal({ + active: true, + sizes: [[970, 90], [728, 90], [300, 250]] + }) + }); + + it('when multiple mediaQuery block matches, it should filter a union of the matched sizesSupported', () => { + matchMediaOverride = (str) => includes([ + '(min-width: 1200px)', + '(min-width: 768px) and (max-width: 1199px)' + ], str) ? {matches: true} : {matches: false}; + + let status = resolveStatus(undefined, testSizes, sizeConfig); + expect(status).to.deep.equal({ + active: true, + sizes: [[970, 90], [728, 90], [300, 250], [300, 100]] + }) + }); + + it('if no mediaQueries match, it should allow all sizes specified', () => { + matchMediaOverride = () => ({matches: false}); + + let status = resolveStatus(undefined, testSizes, sizeConfig); + expect(status).to.deep.equal({ + active: true, + sizes: testSizes + }) + }); - it('getScreenWidth', function() { - mockWindow.innerWidth = 900; - mockWindow.document.body.clientWidth = 900; - mockWindow.document.documentElement.clientWidth = 900; - expect(sizeMapping.getScreenWidth(mockWindow)).to.equal(900); + it('if a mediaQuery matches and has sizesSupported: [], it should filter all sizes', () => { + matchMediaOverride = (str) => str === '(min-width: 0px) and (max-width: 767px)' ? {matches: true} : {matches: false}; + + let status = resolveStatus(undefined, testSizes, sizeConfig); + expect(status).to.deep.equal({ + active: false, + sizes: [] + }) + }); + + it('if a mediaQuery matches and no sizesSupported specified, it should not effect adUnit.sizes', () => { + matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; + + let status = resolveStatus(undefined, testSizes, sizeConfigWithLabels); + expect(status).to.deep.equal({ + active: true, + sizes: testSizes + }) + }); }); - it('getScreenWidth - should return 0 if it cannot deteremine size', function() { - mockWindow.innerWidth = null; - mockWindow.document.body.clientWidth = null; - mockWindow.document.documentElement.clientWidth = null; - expect(sizeMapping.getScreenWidth(mockWindow)).to.equal(0); + describe('when handling labels', () => { + it('should activate/deactivate adUnits/bidders based on sizeConfig.labels', () => { + matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; + + let status = resolveStatus({ + labels: ['desktop'] + }, testSizes, sizeConfigWithLabels); + + expect(status).to.deep.equal({ + active: true, + sizes: testSizes + }); + + status = resolveStatus({ + labels: ['tablet'] + }, testSizes, sizeConfigWithLabels); + + expect(status).to.deep.equal({ + active: false, + sizes: testSizes + }); + }); + + it('should active/deactivate adUnits/bidders based on requestBids labels', () => { + let activeLabels = ['us-visitor', 'desktop', 'smart']; + + let status = resolveStatus({ + labels: ['uk-visitor'], + activeLabels + }, testSizes, sizeConfigWithLabels); + + expect(status).to.deep.equal({ + active: false, + sizes: testSizes + }); + + status = resolveStatus({ + labels: ['us-visitor'], + activeLabels + }, testSizes, sizeConfigWithLabels); + + expect(status).to.deep.equal({ + active: true, + sizes: testSizes + }); + + status = resolveStatus({ + labels: ['us-visitor', 'tablet'], + labelAll: true, + activeLabels + }, testSizes, sizeConfigWithLabels); + + expect(status).to.deep.equal({ + active: false, + sizes: testSizes + }); + + status = resolveStatus({ + labels: ['us-visitor', 'desktop'], + labelAll: true, + activeLabels + }, testSizes, sizeConfigWithLabels); + + expect(status).to.deep.equal({ + active: true, + sizes: testSizes + }); + }); }); }); diff --git a/test/spec/unit/bidmanager_spec.js b/test/spec/unit/bidmanager_spec.js deleted file mode 100644 index 290bf06733e..00000000000 --- a/test/spec/unit/bidmanager_spec.js +++ /dev/null @@ -1,259 +0,0 @@ -import { expect } from 'chai'; -import { config } from 'src/config'; -import constants from 'src/constants'; -import events from 'src/events'; - -import * as bidManager from 'src/bidmanager'; -import useVideoCacheStubs from 'test/mocks/videoCacheStub'; -import adUnit from 'test/fixtures/video/adUnit'; -import bidRequest from 'test/fixtures/video/bidRequest'; -import urlBidResponse from 'test/fixtures/video/vastUrlResponse'; -import payloadBidResponse from 'test/fixtures/video/vastPayloadResponse'; - -function adjustCpm(cpm) { - return cpm + 1; -} - -describe('The Bid Manager', () => { - before(() => { - $$PREBID_GLOBAL$$.cbTimeout = 5000; - $$PREBID_GLOBAL$$.timeoutBuffer = 50; - }); - - describe('addBidResponse() function,', () => { - /** - * Add the bidResponse fixture as a bid into the auction, and run some assertions - * to verify: - * - * 1. Whether or not that bid got added. - * 2. Whether or not the "end of auction" callbacks got called. - */ - function testAddVideoBid(expectBidAdded, expectCallbackCalled, videoCacheStubProvider, usePayloadResponse) { - return function() { - const usePrebidCache = config.getConfig('usePrebidCache'); - const bidToUse = usePayloadResponse ? payloadBidResponse : urlBidResponse; - const mockResponse = Object.assign({}, bidToUse); - const callback = sinon.spy(); - bidManager.addOneTimeCallback(callback); - - mockResponse.getSize = function() { - return `${this.height}x${this.width}`; - }; - bidManager.addBidResponse(adUnit.code, mockResponse); - - const expectedBidsReceived = expectBidAdded ? 1 : 0; - expect($$PREBID_GLOBAL$$._bidsReceived.length).to.equal(expectedBidsReceived); - - const storeStub = videoCacheStubProvider().store; - if (usePrebidCache) { - expect(storeStub.calledOnce).to.equal(true); - expect(storeStub.getCall(0).args[0][0]).to.equal(mockResponse); - } else { - expect(storeStub.called).to.equal(false); - } - - if (expectedBidsReceived === 1) { - const bid = $$PREBID_GLOBAL$$._bidsReceived[0]; - - // Ensures that the BidAdjustment listeners execute before the bid goes into the auction. - expect(bid.cpm).to.equal(adjustCpm(0.1)); - - if (usePayloadResponse) { - expect(bid.vastXml).to.equal(''); - if (usePrebidCache) { - expect(bid.vastUrl).to.equal(`https://prebid.adnxs.com/pbc/v1/cache?uuid=FAKE_UUID`); - } - } else { - expect(bid.vastUrl).to.equal('www.myVastUrl.com'); - } - if (usePrebidCache) { - expect(bid.videoCacheKey).to.equal('FAKE_UUID'); - } - } - if (expectCallbackCalled) { - expect(callback.calledOnce).to.equal(true); - } else { - expect(callback.called).to.equal(false); - } - }; - } - - /** - * Initialize the global state so that the auction-space looks like we want it to. - * - * @param {Array} adUnits The array of ad units which should appear in this auction. - * @param {function} bidRequestTweaker A function which accepts a basic bidRequest, and - * transforms it to prepare it for auction. - */ - function prepAuction(adUnits, bidRequestTweaker) { - function bidAdjuster(bid) { - if (bid.hasOwnProperty('cpm')) { - bid.hadCpmDuringBidAdjustment = true; - } - if (bid.hasOwnProperty('adUnitCode')) { - bid.hadAdUnitCodeDuringBidAdjustment = true; - } - if (bid.hasOwnProperty('timeToRespond')) { - bid.hadTimeToRespondDuringBidAdjustment = true; - } - if (bid.hasOwnProperty('requestTimestamp')) { - bid.hadRequestTimestampDuringBidAdjustment = true; - } - if (bid.hasOwnProperty('responseTimestamp')) { - bid.hadResponseTimestampDuringBidAdjustment = true; - } - bid.cpm = adjustCpm(bid.cpm); - } - beforeEach(() => { - let thisBidRequest = bidRequest; - if (bidRequestTweaker) { - thisBidRequest = JSON.parse(JSON.stringify(bidRequest)); - bidRequestTweaker(thisBidRequest); - } - - events.on(constants.EVENTS.BID_ADJUSTMENT, bidAdjuster); - - $$PREBID_GLOBAL$$.adUnits = adUnits; - $$PREBID_GLOBAL$$._bidsRequested = [thisBidRequest]; - $$PREBID_GLOBAL$$._bidsReceived = []; - $$PREBID_GLOBAL$$._adUnitCodes = $$PREBID_GLOBAL$$.adUnits.map(unit => unit.code); - }); - - afterEach(() => { - events.off(constants.EVENTS.BID_ADJUSTMENT, bidAdjuster); - }); - } - - function auctionStart(timedOut) { - return timedOut - ? new Date().getTime() - $$PREBID_GLOBAL$$.cbTimeout - $$PREBID_GLOBAL$$.timeoutBuffer - 1 - : new Date().getTime(); - } - - function testAddExpectMoreBids(stubProvider) { - return () => { - // Set up the global state so that we expect two bids, and the auction started just now - // (so as to reduce the chance of timeout. This assumes that the unit test runs run in < 5000 ms). - prepAuction( - [adUnit, Object.assign({}, adUnit, { code: 'video2' })], - (bidRequest) => { - const tweakedBidRequestBid = Object.assign({}, bidRequest.bids[0], { placementCode: 'video2' }); - bidRequest.bids.push(tweakedBidRequestBid); - bidRequest.start = auctionStart(false); - }); - - it("should add video bids, but shouldn't call the end-of-auction callbacks yet", - testAddVideoBid(true, false, stubProvider, false)); - }; - } - - describe('when prebid-cache is enabled', () => { - before(() => { - config.setConfig({ - usePrebidCache: true, - }); - }); - - describe('when the cache is functioning properly', () => { - let stubProvider = useVideoCacheStubs({ - store: [{ uuid: 'FAKE_UUID' }], - }); - - describe('when more bids are expected after this one', testAddExpectMoreBids(stubProvider)); - - describe('when this is the last bid expected in the auction', () => { - // Set up the global state so that we expect only one bid, and the auction started just now - // (so as to reduce the chance of timeout. This assumes that the unit test runs run in < 5000 ms). - prepAuction([adUnit], (bidRequest) => bidRequest.start = auctionStart(false)); - - it("shouldn't add invalid bids", () => { - bidManager.addBidResponse('', { }); - bidManager.addBidResponse('testCode', { mediaType: 'video' }); - bidManager.addBidResponse('testCode', { mediaType: 'native' }); - expect($$PREBID_GLOBAL$$._bidsReceived.length).to.equal(0); - }); - - it('should add bids with a vastUrl and then execute the callbacks signaling the end of the auction', - testAddVideoBid(true, true, stubProvider, false)); - - it('should add bids with a vastXml and then execute the callbacks signaling the end of the auction', - testAddVideoBid(true, true, stubProvider, true)); - - it('should gracefully do nothing when adUnitCode is undefined', () => { - bidManager.addBidResponse(undefined, {}); - expect($$PREBID_GLOBAL$$._bidsReceived.length).to.equal(0); - }); - - it('should gracefully do nothing when bid is undefined', () => { - bidManager.addBidResponse('mock/code'); - expect($$PREBID_GLOBAL$$._bidsReceived.length).to.equal(0); - }); - - it('should attach properties for analytics *before* the BID_ADJUSTMENT event listeners are called', () => { - const copy = Object.assign({}, urlBidResponse); - copy.getSize = function() { - return `${this.height}x${this.width}`; - }; - delete copy.cpm; - bidManager.addBidResponse(adUnit.code, copy); - expect(copy).to.have.property('hadCpmDuringBidAdjustment', true); - expect(copy).to.have.property('hadAdUnitCodeDuringBidAdjustment', true); - expect(copy).to.have.property('hadTimeToRespondDuringBidAdjustment', true); - expect(copy).to.have.property('hadRequestTimestampDuringBidAdjustment', true); - expect(copy).to.have.property('hadResponseTimestampDuringBidAdjustment', true); - }); - }); - - describe('when the auction has timed out', () => { - // Set up the global state to expect two bids, and mock an auction which happened long enough - // in the past that it will *seem* like this bid is arriving after the timeouts. - prepAuction( - [adUnit, Object.assign({}, adUnit, { code: 'video2' })], - (bidRequest) => { - const tweakedBidRequestBid = Object.assign({}, bidRequest.bids[0], { placementCode: 'video2' }); - bidRequest.bids.push(tweakedBidRequestBid); - bidRequest.start = auctionStart(true); - }); - - // Because of the preconditions, this makes sure that the end-of-auction callbacks get called when - // the auction hits the timeout. - it('should add the bid, but also execute the callbacks signaling the end of the auction', - testAddVideoBid(true, true, stubProvider, false)); - }); - }); - - describe('when the cache is failing for some reason,', () => { - let stubProvider = useVideoCacheStubs({ - store: new Error('Unable to save to the cache'), - }); - - describe('when the auction still has time left', () => { - prepAuction([adUnit], (bidRequest) => bidRequest.start = auctionStart(false)); - - it("shouldn't add the bid to the auction, and shouldn't execute the end-of-auction callbacks", - testAddVideoBid(false, false, stubProvider, false)); - }); - - describe('when the auction has timed out', () => { - prepAuction([adUnit], (bidRequest) => bidRequest.start = auctionStart(true)); - it("shouldn't add the bid to the auction, but should execute the end-of-auction callbacks", - testAddVideoBid(false, true, stubProvider, false)); - }) - }); - }); - - describe('when prebid-cache is disabled', () => { - let stubProvider = useVideoCacheStubs({ - store: [{ uuid: 'FAKE_UUID' }], - }); - - before(() => { - config.setConfig({ - usePrebidCache: false, - }); - }); - - describe('when more bids are expected after this one', testAddExpectMoreBids(stubProvider)); - }); - }); -}); diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 30452d9725a..21ab14ea99e 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -3,7 +3,11 @@ import AdapterManager from 'src/adaptermanager'; import { getAdUnits } from 'test/fixtures/fixtures'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils'; +import { config } from 'src/config'; import { registerBidder } from 'src/adapters/bidderFactory'; +import { setSizeConfig } from 'src/sizeMapping'; +import find from 'core-js/library/fn/array/find'; +import includes from 'core-js/library/fn/array/includes'; var s2sTesting = require('../../../../modules/s2sTesting'); var events = require('../../../../src/events'); @@ -17,21 +21,15 @@ const CONFIG = { }; var prebidServerAdapterMock = { bidder: 'prebidServer', - callBids: sinon.stub(), - setConfig: sinon.stub(), - queueSync: sinon.stub() + callBids: sinon.stub() }; var adequantAdapterMock = { bidder: 'adequant', - callBids: sinon.stub(), - setConfig: sinon.stub(), - queueSync: sinon.stub() + callBids: sinon.stub() }; var appnexusAdapterMock = { bidder: 'appnexus', - callBids: sinon.stub(), - setConfig: sinon.stub(), - queueSync: sinon.stub() + callBids: sinon.stub() }; describe('adapterManager tests', () => { @@ -45,6 +43,44 @@ describe('adapterManager tests', () => { }); it('should log an error if a bidder is used that does not exist', () => { + let bidRequests = [{ + 'bidderCode': 'appnexus', + 'requestId': '1863e370099523', + 'bidderRequestId': '2946b569352ef2', + 'tid': '34566b569352ef2', + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '4799418', + 'test': 'me' + }, + 'adUnitCode': '/19968336/header-bid-tag1', + 'sizes': [[728, 90], [970, 70]], + 'bidId': '392b5a6b05d648', + 'bidderRequestId': '2946b569352ef2', + 'requestId': '1863e370099523', + 'startTime': 1462918897462, + 'status': 1, + 'transactionId': 'fsafsa' + }, + { + 'bidder': 'fakeBidder', + 'params': { + 'placementId': '4799418' + }, + 'adUnitCode': '/19968336/header-bid-tag-0', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '4dccdc37746135', + 'bidderRequestId': '2946b569352ef2', + 'requestId': '1863e370099523', + 'startTime': 1462918897463, + 'status': 1, + 'transactionId': 'fsafsa' + } + ], + 'start': 1462918897460 + }]; const adUnits = [{ code: 'adUnit-code', bids: [ @@ -53,7 +89,7 @@ describe('adapterManager tests', () => { ] }]; - AdapterManager.callBids({adUnits}); + AdapterManager.callBids(adUnits, bidRequests); sinon.assert.called(utils.logError); }); @@ -64,7 +100,9 @@ describe('adapterManager tests', () => { let count = () => cnt++; events.on(CONSTANTS.EVENTS.BID_REQUESTED, count); AdapterManager.bidderRegistry['appnexus'] = appnexusAdapterMock; - AdapterManager.callBids({adUnits: getAdUnits()}); + let adUnits = getAdUnits(); + let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); + AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); expect(cnt).to.equal(1); sinon.assert.calledOnce(appnexusAdapterMock.callBids); appnexusAdapterMock.callBids.reset(); @@ -75,17 +113,81 @@ describe('adapterManager tests', () => { describe('S2S tests', () => { beforeEach(() => { - AdapterManager.setS2SConfig(CONFIG); + config.setConfig({s2sConfig: CONFIG}); AdapterManager.bidderRegistry['prebidServer'] = prebidServerAdapterMock; prebidServerAdapterMock.callBids.reset(); }); it('invokes callBids on the S2S adapter', () => { - AdapterManager.callBids({adUnits: getAdUnits()}); + let bidRequests = [{ + 'bidderCode': 'appnexus', + 'requestId': '1863e370099523', + 'bidderRequestId': '2946b569352ef2', + 'tid': '34566b569352ef2', + 'src': 's2s', + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '4799418', + 'test': 'me' + }, + 'adUnitCode': '/19968336/header-bid-tag1', + 'sizes': [ + [ + 728, + 90 + ], + [ + 970, + 90 + ] + ], + 'bidId': '392b5a6b05d648', + 'bidderRequestId': '2946b569352ef2', + 'requestId': '1863e370099523', + 'startTime': 1462918897462, + 'status': 1, + 'transactionId': 'fsafsa' + }, + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '4799418' + }, + 'adUnitCode': '/19968336/header-bid-tag-0', + 'sizes': [ + [ + 300, + 250 + ], + [ + 300, + 600 + ] + ], + 'bidId': '4dccdc37746135', + 'bidderRequestId': '2946b569352ef2', + 'requestId': '1863e370099523', + 'startTime': 1462918897463, + 'status': 1, + 'transactionId': 'fsafsa' + } + ], + 'start': 1462918897460 + }]; + + AdapterManager.callBids( + getAdUnits(), + bidRequests, + () => {}, + () => () => {} + ); sinon.assert.calledOnce(prebidServerAdapterMock.callBids); }); + // Enable this test when prebidServer adapter is made 1.0 compliant it('invokes callBids with only s2s bids', () => { const adUnits = getAdUnits(); // adUnit without appnexus bidder @@ -102,7 +204,70 @@ describe('adapterManager tests', () => { } ] }); - AdapterManager.callBids({adUnits: adUnits}); + + let bidRequests = [{ + 'bidderCode': 'appnexus', + 'requestId': '1863e370099523', + 'bidderRequestId': '2946b569352ef2', + 'tid': '34566b569352ef2', + 'src': 's2s', + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '4799418', + 'test': 'me' + }, + 'adUnitCode': '/19968336/header-bid-tag1', + 'sizes': [ + [ + 728, + 90 + ], + [ + 970, + 90 + ] + ], + 'bidId': '392b5a6b05d648', + 'bidderRequestId': '2946b569352ef2', + 'requestId': '1863e370099523', + 'startTime': 1462918897462, + 'status': 1, + 'transactionId': 'fsafsa' + }, + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '4799418' + }, + 'adUnitCode': '/19968336/header-bid-tag-0', + 'sizes': [ + [ + 300, + 250 + ], + [ + 300, + 600 + ] + ], + 'bidId': '4dccdc37746135', + 'bidderRequestId': '2946b569352ef2', + 'requestId': '1863e370099523', + 'startTime': 1462918897463, + 'status': 1, + 'transactionId': 'fsafsa' + } + ], + 'start': 1462918897460 + }]; + AdapterManager.callBids( + adUnits, + bidRequests, + () => {}, + () => () => {} + ); const requestObj = prebidServerAdapterMock.callBids.firstCall.args[0]; expect(requestObj.ad_units.length).to.equal(2); sinon.assert.calledOnce(prebidServerAdapterMock.callBids); @@ -122,14 +287,18 @@ describe('adapterManager tests', () => { }); it('should fire for s2s requests', () => { - AdapterManager.callBids({adUnits: getAdUnits()}); + let adUnits = getAdUnits(); + let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); + AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); expect(cnt).to.equal(1); sinon.assert.calledOnce(prebidServerAdapterMock.callBids); }); it('should fire for simultaneous s2s and client requests', () => { AdapterManager.bidderRegistry['adequant'] = adequantAdapterMock; - AdapterManager.callBids({adUnits: getAdUnits()}); + let adUnits = getAdUnits(); + let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); + AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); expect(cnt).to.equal(2); sinon.assert.calledOnce(prebidServerAdapterMock.callBids); sinon.assert.calledOnce(adequantAdapterMock.callBids); @@ -139,38 +308,20 @@ describe('adapterManager tests', () => { }); }); // end s2s tests - describe('The setBidderSequence() function', () => { - let spy; - - beforeEach(() => { - spy = sinon.spy(utils, 'logWarn') - }); - - afterEach(() => { - utils.logWarn.restore(); - }); - - it('should log a warning on invalid values', () => { - AdapterManager.setBidderSequence('unrecognized sequence'); - expect(spy.calledOnce).to.equal(true); - }); - - it('should not log warnings when given recognized values', () => { - AdapterManager.setBidderSequence('fixed'); - AdapterManager.setBidderSequence('random'); - expect(spy.called).to.equal(false); - }); - }) - describe('s2sTesting', () => { function getTestAdUnits() { // copy adUnits return JSON.parse(JSON.stringify(getAdUnits())); } + function callBids(adUnits = getTestAdUnits()) { + let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); + AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); + } + function checkServerCalled(numAdUnits, numBids) { sinon.assert.calledOnce(prebidServerAdapterMock.callBids); - var requestObj = prebidServerAdapterMock.callBids.firstCall.args[0]; + let requestObj = prebidServerAdapterMock.callBids.firstCall.args[0]; expect(requestObj.ad_units.length).to.equal(numAdUnits); for (let i = 0; i < numAdUnits; i++) { expect(requestObj.ad_units[i].bids.filter((bid) => { @@ -184,16 +335,15 @@ describe('adapterManager tests', () => { expect(adapter.callBids.firstCall.args[0].bids.length).to.equal(numBids); } - var TESTING_CONFIG; - var stubGetSourceBidderMap; + let TESTING_CONFIG = utils.deepClone(CONFIG); + Object.assign(TESTING_CONFIG, { + bidders: ['appnexus', 'adequant'], + testing: true + }); + let stubGetSourceBidderMap; beforeEach(() => { - TESTING_CONFIG = Object.assign(CONFIG, { - bidders: ['appnexus', 'adequant'], - testing: true - }); - - AdapterManager.setS2SConfig(CONFIG); + config.setConfig({s2sConfig: TESTING_CONFIG}); AdapterManager.bidderRegistry['prebidServer'] = prebidServerAdapterMock; AdapterManager.bidderRegistry['adequant'] = adequantAdapterMock; AdapterManager.bidderRegistry['appnexus'] = appnexusAdapterMock; @@ -206,13 +356,13 @@ describe('adapterManager tests', () => { }); afterEach(() => { + config.setConfig({s2sConfig: {}}); s2sTesting.getSourceBidderMap.restore(); }); it('calls server adapter if no sources defined', () => { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: [], [s2sTesting.SERVER]: []}); - AdapterManager.setS2SConfig(TESTING_CONFIG); - AdapterManager.callBids({adUnits: getTestAdUnits()}); + callBids(); // server adapter checkServerCalled(2, 2); @@ -226,8 +376,7 @@ describe('adapterManager tests', () => { it('calls client adapter if one client source defined', () => { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus'], [s2sTesting.SERVER]: []}); - AdapterManager.setS2SConfig(TESTING_CONFIG); - AdapterManager.callBids({adUnits: getTestAdUnits()}); + callBids(); // server adapter checkServerCalled(2, 2); @@ -241,8 +390,21 @@ describe('adapterManager tests', () => { it('calls client adapters if client sources defined', () => { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); - AdapterManager.setS2SConfig(TESTING_CONFIG); - AdapterManager.callBids({adUnits: getTestAdUnits()}); + callBids(); + + // server adapter + checkServerCalled(2, 2); + + // appnexus + checkClientCalled(appnexusAdapterMock, 2); + + // adequant + checkClientCalled(adequantAdapterMock, 2); + }); + + it('calls client adapters if client sources defined', () => { + stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); + callBids(); // server adapter checkServerCalled(2, 2); @@ -256,13 +418,12 @@ describe('adapterManager tests', () => { it('does not call server adapter for bidders that go to client', () => { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); - AdapterManager.setS2SConfig(TESTING_CONFIG); var adUnits = getTestAdUnits(); adUnits[0].bids[0].finalSource = s2sTesting.CLIENT; adUnits[0].bids[1].finalSource = s2sTesting.CLIENT; adUnits[1].bids[0].finalSource = s2sTesting.CLIENT; adUnits[1].bids[1].finalSource = s2sTesting.CLIENT; - AdapterManager.callBids({adUnits}); + callBids(adUnits); // server adapter sinon.assert.notCalled(prebidServerAdapterMock.callBids); @@ -276,13 +437,12 @@ describe('adapterManager tests', () => { it('does not call client adapters for bidders that go to server', () => { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); - AdapterManager.setS2SConfig(TESTING_CONFIG); var adUnits = getTestAdUnits(); adUnits[0].bids[0].finalSource = s2sTesting.SERVER; adUnits[0].bids[1].finalSource = s2sTesting.SERVER; adUnits[1].bids[0].finalSource = s2sTesting.SERVER; adUnits[1].bids[1].finalSource = s2sTesting.SERVER; - AdapterManager.callBids({adUnits}); + callBids(adUnits); // server adapter checkServerCalled(2, 2); @@ -296,13 +456,12 @@ describe('adapterManager tests', () => { it('calls client and server adapters for bidders that go to both', () => { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); - AdapterManager.setS2SConfig(TESTING_CONFIG); var adUnits = getTestAdUnits(); adUnits[0].bids[0].finalSource = s2sTesting.BOTH; adUnits[0].bids[1].finalSource = s2sTesting.BOTH; adUnits[1].bids[0].finalSource = s2sTesting.BOTH; adUnits[1].bids[1].finalSource = s2sTesting.BOTH; - AdapterManager.callBids({adUnits}); + callBids(adUnits); // server adapter checkServerCalled(2, 2); @@ -316,13 +475,12 @@ describe('adapterManager tests', () => { it('makes mixed client/server adapter calls for mixed bidder sources', () => { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); - AdapterManager.setS2SConfig(TESTING_CONFIG); var adUnits = getTestAdUnits(); adUnits[0].bids[0].finalSource = s2sTesting.CLIENT; adUnits[0].bids[1].finalSource = s2sTesting.CLIENT; adUnits[1].bids[0].finalSource = s2sTesting.SERVER; adUnits[1].bids[1].finalSource = s2sTesting.SERVER; - AdapterManager.callBids({adUnits}); + callBids(adUnits); // server adapter checkServerCalled(1, 2); @@ -387,5 +545,119 @@ describe('adapterManager tests', () => { expect(AdapterManager.videoAdapters).to.include(alias); }); }); + + describe('makeBidRequests', () => { + let adUnits; + beforeEach(() => { + adUnits = utils.deepClone(getAdUnits()).map(adUnit => { + adUnit.bids = adUnit.bids.filter(bid => includes(['appnexus', 'rubicon'], bid.bidder)); + return adUnit; + }) + }); + + describe('sizeMapping', () => { + beforeEach(() => { + sinon.stub(window, 'matchMedia', () => ({matches: true})); + }); + + afterEach(() => { + matchMedia.restore(); + setSizeConfig([]); + }); + + it('should not filter bids w/ no labels', () => { + let bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); + + expect(bidRequests.length).to.equal(2); + let rubiconBidRequests = find(bidRequests, bidRequest => bidRequest.bidderCode === 'rubicon'); + expect(rubiconBidRequests.bids.length).to.equal(1); + expect(rubiconBidRequests.bids[0].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === rubiconBidRequests.bids[0].adUnitCode).sizes); + + let appnexusBidRequests = find(bidRequests, bidRequest => bidRequest.bidderCode === 'appnexus'); + expect(appnexusBidRequests.bids.length).to.equal(2); + expect(appnexusBidRequests.bids[0].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === appnexusBidRequests.bids[0].adUnitCode).sizes); + expect(appnexusBidRequests.bids[1].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === appnexusBidRequests.bids[1].adUnitCode).sizes); + }); + + it('should filter sizes using size config', () => { + let validSizes = [ + [728, 90], + [300, 250] + ]; + + let validSizeMap = validSizes.map(size => size.toString()).reduce((map, size) => { + map[size] = true; + return map; + }, {}); + + setSizeConfig([{ + 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', + 'sizesSupported': validSizes, + 'labels': ['tablet', 'phone'] + }]); + + let bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); + + // only valid sizes as specified in size config should show up in bidRequests + bidRequests.forEach(bidRequest => { + bidRequest.bids.forEach(bid => { + bid.sizes.forEach(size => { + expect(validSizeMap[size]).to.equal(true); + }); + }); + }); + + setSizeConfig([{ + 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', + 'sizesSupported': [], + 'labels': ['tablet', 'phone'] + }]); + + bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + [] + ); + + // if no valid sizes, all bidders should be filtered out + expect(bidRequests.length).to.equal(0); + }); + + it('should filter adUnits/bidders based on applied labels', () => { + adUnits[0].labelAll = ['visitor-uk', 'mobile']; + adUnits[1].labelAny = ['visitor-uk', 'desktop']; + adUnits[1].bids[0].labelAny = ['mobile']; + adUnits[1].bids[1].labelAll = ['desktop']; + + let bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + ['visitor-uk', 'desktop'] + ); + + // only one adUnit and one bid from that adUnit should make it through the applied labels above + expect(bidRequests.length).to.equal(1); + expect(bidRequests[0].bidderCode).to.equal('rubicon'); + expect(bidRequests[0].bids.length).to.equal(1); + expect(bidRequests[0].bids[0].adUnitCode).to.equal(adUnits[1].code); + }); + }) + }); }); }); diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index e621f1fb329..7358017474d 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -1,5 +1,4 @@ import { newBidder, registerBidder } from 'src/adapters/bidderFactory'; -import bidmanager from 'src/bidmanager'; import adaptermanager from 'src/adaptermanager'; import * as ajax from 'src/ajax'; import { expect } from 'chai'; @@ -11,15 +10,17 @@ const CODE = 'sampleBidder'; const MOCK_BIDS_REQUEST = { bids: [ { + bidId: 1, requestId: 'first-bid-id', - placementCode: 'mock/placement', + adUnitCode: 'mock/placement', params: { param: 5 } }, { + bidId: 2, requestId: 'second-bid-id', - placementCode: 'mock/placement2', + adUnitCode: 'mock/placement2', params: { badParam: 6 } @@ -29,8 +30,9 @@ const MOCK_BIDS_REQUEST = { describe('bidders created by newBidder', () => { let spec; - let addBidRequestStub; let bidder; + let addBidResponseStub; + let doneStub; beforeEach(() => { spec = { @@ -40,11 +42,9 @@ describe('bidders created by newBidder', () => { interpretResponse: sinon.stub(), getUserSyncs: sinon.stub() }; - addBidRequestStub = sinon.stub(bidmanager, 'addBidResponse'); - }); - afterEach(() => { - addBidRequestStub.restore(); + addBidResponseStub = sinon.stub(); + doneStub = sinon.stub(); }); describe('when the ajax response is irrelevant', () => { @@ -52,6 +52,8 @@ describe('bidders created by newBidder', () => { beforeEach(() => { ajaxStub = sinon.stub(ajax, 'ajax'); + addBidResponseStub.reset(); + doneStub.reset(); }); afterEach(() => { @@ -78,7 +80,7 @@ describe('bidders created by newBidder', () => { spec.isBidRequestValid.returns(true); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.called).to.equal(false); expect(spec.isBidRequestValid.calledTwice).to.equal(true); @@ -92,7 +94,7 @@ describe('bidders created by newBidder', () => { spec.isBidRequestValid.returns(false); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.called).to.equal(false); expect(spec.isBidRequestValid.calledTwice).to.equal(true); @@ -106,7 +108,7 @@ describe('bidders created by newBidder', () => { spec.isBidRequestValid.onSecondCall().returns(false); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.called).to.equal(false); expect(spec.isBidRequestValid.calledTwice).to.equal(true); @@ -120,7 +122,7 @@ describe('bidders created by newBidder', () => { spec.isBidRequestValid.returns(true); spec.buildRequests.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.called).to.equal(false); }); @@ -136,7 +138,7 @@ describe('bidders created by newBidder', () => { data: data }); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(url); @@ -161,7 +163,7 @@ describe('bidders created by newBidder', () => { options: options }); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(url); @@ -184,7 +186,7 @@ describe('bidders created by newBidder', () => { data: data }); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(`${url}?arg=2&`); @@ -208,7 +210,7 @@ describe('bidders created by newBidder', () => { options: opt }); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.calledOnce).to.equal(true); expect(ajaxStub.firstCall.args[0]).to.equal(`${url}?arg=2&`); @@ -237,12 +239,12 @@ describe('bidders created by newBidder', () => { } ]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(ajaxStub.calledTwice).to.equal(true); }); - it('should add bids for each placement code if no requests are given', () => { + it('should not add bids for each placement code if no requests are given', () => { const bidder = newBidder(spec); spec.isBidRequestValid.returns(true); @@ -250,13 +252,9 @@ describe('bidders created by newBidder', () => { spec.interpretResponse.returns([]); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); - expect(bidmanager.addBidResponse.calledTwice).to.equal(true); - const placementsWithBids = - [bidmanager.addBidResponse.firstCall.args[0], bidmanager.addBidResponse.secondCall.args[0]]; - expect(placementsWithBids).to.contain('mock/placement'); - expect(placementsWithBids).to.contain('mock/placement2'); + expect(addBidResponseStub.callCount).to.equal(0); }); }); @@ -271,6 +269,8 @@ describe('bidders created by newBidder', () => { fakeResponse.returns('headerContent'); callbacks.success('response body', { getResponseHeader: fakeResponse }); }); + addBidResponseStub.reset(); + doneStub.reset(); userSyncStub = sinon.stub(userSync, 'registerSync') logErrorSpy = sinon.spy(utils, 'logError'); }); @@ -292,7 +292,7 @@ describe('bidders created by newBidder', () => { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(spec.interpretResponse.calledOnce).to.equal(true); const response = spec.interpretResponse.firstCall.args[0] @@ -303,6 +303,7 @@ describe('bidders created by newBidder', () => { url: 'test.url.com', data: {} }); + expect(doneStub.calledOnce).to.equal(true); }); it('should call spec.interpretResponse() once for each request made', () => { @@ -323,23 +324,23 @@ describe('bidders created by newBidder', () => { ]); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(spec.interpretResponse.calledTwice).to.equal(true); + expect(doneStub.calledOnce).to.equal(true); }); - it('should add bids for each placement code into the bidmanager, even if the bidder doesn\'t bid on all of them', () => { + it('should only add bids for valid adUnit code into the auction, even if the bidder doesn\'t bid on all of them', () => { const bidder = newBidder(spec); const bid = { creativeId: 'creative-id', - bidderCode: 'code', - requestId: 'some-id', + requestId: '1', ad: 'ad-url.com', cpm: 0.5, height: 200, width: 300, - placementCode: 'mock/placement', + adUnitCode: 'mock/placement', currency: 'USD', netRevenue: true, ttl: 300 @@ -354,13 +355,11 @@ describe('bidders created by newBidder', () => { spec.interpretResponse.returns(bid); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); - expect(bidmanager.addBidResponse.calledTwice).to.equal(true); - const placementsWithBids = - [bidmanager.addBidResponse.firstCall.args[0], bidmanager.addBidResponse.secondCall.args[0]]; - expect(placementsWithBids).to.contain('mock/placement'); - expect(placementsWithBids).to.contain('mock/placement2'); + expect(addBidResponseStub.calledOnce).to.equal(true); + expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); + expect(doneStub.calledOnce).to.equal(true); expect(logErrorSpy.callCount).to.equal(0); }); @@ -375,7 +374,7 @@ describe('bidders created by newBidder', () => { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(spec.getUserSyncs.calledOnce).to.equal(true); expect(spec.getUserSyncs.firstCall.args[1].length).to.equal(1); @@ -394,7 +393,7 @@ describe('bidders created by newBidder', () => { url: 'usersync.com' }]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(userSyncStub.called).to.equal(true); expect(userSyncStub.firstCall.args[0]).to.equal('iframe'); @@ -406,7 +405,7 @@ describe('bidders created by newBidder', () => { const bidder = newBidder(spec); const bid = { - requestId: 'some-id', + requestId: '1', ad: 'ad-url.com', cpm: 0.5, height: 200, @@ -423,7 +422,7 @@ describe('bidders created by newBidder', () => { spec.interpretResponse.returns(bid); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(logErrorSpy.calledOnce).to.equal(true); }); @@ -436,6 +435,8 @@ describe('bidders created by newBidder', () => { ajaxStub = sinon.stub(ajax, 'ajax', function(url, callbacks) { callbacks.error('ajax call failed.'); }); + addBidResponseStub.reset(); + doneStub.reset(); }); afterEach(() => { @@ -453,12 +454,13 @@ describe('bidders created by newBidder', () => { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(spec.interpretResponse.called).to.equal(false); + expect(doneStub.calledOnce).to.equal(true); }); - it('should add bids for each placement code into the bidmanager', () => { + it('should not add bids for each adunit code into the auction', () => { const bidder = newBidder(spec); spec.isBidRequestValid.returns(true); @@ -470,13 +472,10 @@ describe('bidders created by newBidder', () => { spec.interpretResponse.returns([]); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); - expect(bidmanager.addBidResponse.calledTwice).to.equal(true); - const placementsWithBids = - [bidmanager.addBidResponse.firstCall.args[0], bidmanager.addBidResponse.secondCall.args[0]]; - expect(placementsWithBids).to.contain('mock/placement'); - expect(placementsWithBids).to.contain('mock/placement2'); + expect(addBidResponseStub.callCount).to.equal(0); + expect(doneStub.calledOnce).to.equal(true); }); it('should call spec.getUserSyncs() with no responses', () => { @@ -490,10 +489,11 @@ describe('bidders created by newBidder', () => { }); spec.getUserSyncs.returns([]); - bidder.callBids(MOCK_BIDS_REQUEST); + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); expect(spec.getUserSyncs.calledOnce).to.equal(true); expect(spec.getUserSyncs.firstCall.args[1]).to.deep.equal([]); + expect(doneStub.calledOnce).to.equal(true); }); }); }); @@ -554,3 +554,193 @@ describe('registerBidder', () => { expect(registerBidAdapterStub.thirdCall.args[1]).to.equal('bar') }); }) + +describe('validate bid response: ', () => { + let spec; + let bidder; + let addBidResponseStub; + let doneStub; + let ajaxStub; + let logErrorSpy; + + let bids = [{ + 'ad': 'creative', + 'cpm': '1.99', + 'width': 300, + 'height': 250, + 'requestId': '1', + 'creativeId': 'some-id', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 360 + }]; + + beforeEach(() => { + spec = { + code: CODE, + isBidRequestValid: sinon.stub(), + buildRequests: sinon.stub(), + interpretResponse: sinon.stub(), + }; + + spec.isBidRequestValid.returns(true); + spec.buildRequests.returns({ + method: 'POST', + url: 'test.url.com', + data: {} + }); + + addBidResponseStub = sinon.stub(); + doneStub = sinon.stub(); + ajaxStub = sinon.stub(ajax, 'ajax', function(url, callbacks) { + const fakeResponse = sinon.stub(); + fakeResponse.returns('headerContent'); + callbacks.success('response body', { getResponseHeader: fakeResponse }); + }); + logErrorSpy = sinon.spy(utils, 'logError'); + }); + + afterEach(() => { + ajaxStub.restore(); + logErrorSpy.restore(); + }); + + it('should add native bids that do have required assets', () => { + let bidRequest = { + bids: [{ + bidId: 1, + requestId: 'first-bid-id', + adUnitCode: 'mock/placement', + params: { + param: 5 + }, + nativeParams: { + title: {'required': true}, + }, + mediaType: 'native', + }] + }; + + let bids1 = Object.assign({}, + bids[0], + { + 'mediaType': 'native', + 'native': { + 'title': 'Native Creative', + 'clickUrl': 'https://www.link.example', + } + } + ); + + const bidder = newBidder(spec); + + spec.interpretResponse.returns(bids1); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub); + + expect(addBidResponseStub.calledOnce).to.equal(true); + expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); + expect(logErrorSpy.callCount).to.equal(0); + }); + + it('should not add native bids that do not have required assets', () => { + let bidRequest = { + bids: [{ + bidId: 1, + requestId: 'first-bid-id', + adUnitCode: 'mock/placement', + params: { + param: 5 + }, + nativeParams: { + title: {'required': true}, + }, + mediaType: 'native', + }] + }; + + let bids1 = Object.assign({}, + bids[0], + { + bidderCode: CODE, + mediaType: 'native', + native: { + title: undefined, + clickUrl: 'https://www.link.example', + } + } + ); + + const bidder = newBidder(spec); + spec.interpretResponse.returns(bids1); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub); + + expect(addBidResponseStub.calledOnce).to.equal(false); + expect(logErrorSpy.callCount).to.equal(1); + }); + + it('should add bid when renderer is present on outstream bids', () => { + let bidRequest = { + bids: [{ + bidId: 1, + requestId: 'first-bid-id', + adUnitCode: 'mock/placement', + params: { + param: 5 + }, + mediaTypes: { + video: {context: 'outstream'} + } + }] + }; + + let bids1 = Object.assign({}, + bids[0], + { + bidderCode: CODE, + mediaType: 'video', + renderer: {render: () => true, url: 'render.js'}, + } + ); + + const bidder = newBidder(spec); + + spec.interpretResponse.returns(bids1); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub); + + expect(addBidResponseStub.calledOnce).to.equal(true); + expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); + expect(logErrorSpy.callCount).to.equal(0); + }); + + it('should add banner bids that have no width or height but single adunit size', () => { + let bidRequest = { + bids: [{ + bidder: CODE, + bidId: 1, + requestId: 'first-bid-id', + adUnitCode: 'mock/placement', + params: { + param: 5 + }, + sizes: [[300, 250]], + }] + }; + + let bids1 = Object.assign({}, + bids[0], + { + width: undefined, + height: undefined + } + ); + + const bidder = newBidder(spec); + + spec.interpretResponse.returns(bids1); + bidder.callBids(bidRequest, addBidResponseStub, doneStub, ajaxStub); + + expect(addBidResponseStub.calledOnce).to.equal(true); + expect(addBidResponseStub.firstCall.args[0]).to.equal('mock/placement'); + expect(logErrorSpy.callCount).to.equal(0); + }); +}); diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index f705a46a7f7..4e95139a875 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -1,8 +1,10 @@ import { expect } from 'chai'; -import Targeting from 'src/targeting'; +import { targeting as targetingInstance } from 'src/targeting'; import { config } from 'src/config'; import { getAdUnits } from 'test/fixtures/fixtures'; import CONSTANTS from 'src/constants.json'; +import { auctionManager } from 'src/auctionManager'; +import * as targetingModule from 'src/targeting'; const bid1 = { 'bidderCode': 'rubicon', @@ -28,7 +30,10 @@ const bid1 = { 'hb_adid': '148018fe5e', 'hb_pb': '0.53', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }; const bid2 = { @@ -55,45 +60,43 @@ const bid2 = { 'hb_adid': '5454545', 'hb_pb': '0.25', 'foobar': '300x250' - } + }, + 'netRevenue': true, + 'currency': 'USD', + 'ttl': 300 }; describe('targeting tests', () => { describe('getAllTargeting', () => { + let amBidsReceivedStub; + let amGetAdUnitsStub; + let bidExpiryStub; + beforeEach(() => { $$PREBID_GLOBAL$$._sendAllBids = false; - $$PREBID_GLOBAL$$._bidsReceived = []; - $$PREBID_GLOBAL$$._adUnitCodes = []; - $$PREBID_GLOBAL$$.adUnits = []; + amBidsReceivedStub = sinon.stub(auctionManager, 'getBidsReceived', function() { + return [bid1, bid2]; + }); + amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnitCodes', function() { + return ['/123456/header-bid-tag-0']; + }); + bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired', () => true); + }); + + afterEach(() => { + auctionManager.getBidsReceived.restore(); + auctionManager.getAdUnitCodes.restore(); + targetingModule.isBidExpired.restore(); }); it('selects the top bid when _sendAllBids true', () => { - $$PREBID_GLOBAL$$.adUnits = [{ - code: '/123456/header-bid-tag-0', - sizes: [300, 250], - bids: [ - { - 'bidder': 'rubicon', - 'params': { - 'accountId': 10617, - 'siteId': 23635, - 'zoneId': 453908 - } - } - ] - }]; config.setConfig({ enableSendAllBids: true }); - $$PREBID_GLOBAL$$._bidsReceived.push(bid1, bid2); - $$PREBID_GLOBAL$$._adUnitCodes = ['/123456/header-bid-tag-0']; - let targeting = Targeting.getAllTargeting(['/123456/header-bid-tag-0']); - let flattened = []; - targeting.filter(obj => obj['/123456/header-bid-tag-0'] !== undefined).forEach(item => flattened = flattened.concat(item['/123456/header-bid-tag-0'])); - let sendAllBidCpm = flattened.filter(obj => obj.hb_pb_rubicon !== undefined); - let winningBidCpm = flattened.filter(obj => obj.hb_pb !== undefined); + let targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + let sendAllBidCpm = Object.keys(targeting['/123456/header-bid-tag-0']).filter(key => key.indexOf('hb_pb_') != -1) // we shouldn't get more than 1 key for hb_pb_${bidder} expect(sendAllBidCpm.length).to.equal(1); // expect the winning CPM to be equal to the sendAllBidCPM - expect(sendAllBidCpm[0]['hb_pb_rubicon']).to.deep.equal(winningBidCpm[0]['hb_pb']); + expect(targeting['/123456/header-bid-tag-0']['hb_pb_rubicon']).to.deep.equal(targeting['/123456/header-bid-tag-0']['hb_pb']); }); }); // end getAllTargeting tests }); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index 1cf366082c0..f0a4f0b8e9a 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -7,7 +7,13 @@ import { getTargetingKeysBidLandscape, getAdUnits } from 'test/fixtures/fixtures'; +import { auctionManager, newAuctionManager } from 'src/auctionManager'; +import { targeting, newTargeting } from 'src/targeting'; import { config as configObj } from 'src/config'; +import * as ajaxLib from 'src/ajax'; +import * as auctionModule from 'src/auction'; +import { newBidder, registerBidder } from 'src/adapters/bidderFactory'; +import * as targetingModule from 'src/targeting'; var assert = require('chai').assert; var expect = require('chai').expect; @@ -16,7 +22,7 @@ var urlParse = require('url-parse'); var prebid = require('src/prebid'); var utils = require('src/utils'); -var bidmanager = require('src/bidmanager'); +// var bidmanager = require('src/bidmanager'); var bidfactory = require('src/bidfactory'); var adloader = require('src/adloader'); var adaptermanager = require('src/adaptermanager'); @@ -25,24 +31,27 @@ var adserver = require('src/adserver'); var CONSTANTS = require('src/constants.json'); // These bid adapters are required to be loaded for the following tests to work -require('modules/appnexusAstBidAdapter'); -require('modules/adequantBidAdapter'); +require('modules/appnexusBidAdapter'); var config = require('test/fixtures/config.json'); $$PREBID_GLOBAL$$ = $$PREBID_GLOBAL$$ || {}; -$$PREBID_GLOBAL$$._bidsRequested = getBidRequests(); -$$PREBID_GLOBAL$$._bidsReceived = getBidResponses(); -$$PREBID_GLOBAL$$.adUnits = getAdUnits(); -$$PREBID_GLOBAL$$._adUnitCodes = $$PREBID_GLOBAL$$.adUnits.map(unit => unit.code); +var adUnits = getAdUnits(); +var adUnitCodes = getAdUnits().map(unit => unit.code); +var bidsBackHandler = function() {}; +const timeout = 2000; +var auction = auctionManager.createAuction({adUnits, adUnitCodes, callback: bidsBackHandler, cbTimeout: timeout}); +auction.getBidRequests = getBidRequests; +auction.getBidsReceived = getBidResponses; +auction.getAdUnits = getAdUnits; +auction.getAuctionStatus = function() { return auctionModule.AUCTION_COMPLETED } function resetAuction() { $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: false }); - $$PREBID_GLOBAL$$.clearAuction(); - $$PREBID_GLOBAL$$._bidsRequested = getBidRequests(); - $$PREBID_GLOBAL$$._bidsReceived = getBidResponses(); - $$PREBID_GLOBAL$$.adUnits = getAdUnits(); - $$PREBID_GLOBAL$$._adUnitCodes = $$PREBID_GLOBAL$$.adUnits.map(unit => unit.code); + auction.getBidRequests = getBidRequests; + auction.getBidsReceived = getBidResponses; + auction.getAdUnits = getAdUnits; + auction.getAuctionStatus = function() { return auctionModule.AUCTION_COMPLETED } } var Slot = function Slot(elementId, pathId) { @@ -138,9 +147,16 @@ window.apntag = { }; describe('Unit: Prebid Module', function () { + let bidExpiryStub; + before(() => { + bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired', () => true); + }); + after(function() { $$PREBID_GLOBAL$$.adUnits = []; + targetingModule.isBidExpired.restore(); }); + describe('getAdserverTargetingForAdUnitCodeStr', function () { beforeEach(() => { resetAuction(); @@ -149,7 +165,7 @@ describe('Unit: Prebid Module', function () { it('should return targeting info as a string', function () { const adUnitCode = config.adUnitCodes[0]; $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: true }); - var expected = 'foobar=300x250&hb_size=300x250&hb_pb=10.00&hb_adid=233bcbee889d46d&hb_bidder=appnexus&hb_size_triplelift=0x0&hb_pb_triplelift=10.00&hb_adid_triplelift=222bb26f9e8bd&hb_bidder_triplelift=triplelift&hb_size_appnexus=300x250&hb_pb_appnexus=10.00&hb_adid_appnexus=233bcbee889d46d&hb_bidder_appnexus=appnexus&hb_size_pagescience=300x250&hb_pb_pagescience=10.00&hb_adid_pagescience=25bedd4813632d7&hb_bidder_pagescienc=pagescience&hb_size_brightcom=300x250&hb_pb_brightcom=10.00&hb_adid_brightcom=26e0795ab963896&hb_bidder_brightcom=brightcom&hb_size_brealtime=300x250&hb_pb_brealtime=10.00&hb_adid_brealtime=275bd666f5a5a5d&hb_bidder_brealtime=brealtime&hb_size_pubmatic=300x250&hb_pb_pubmatic=10.00&hb_adid_pubmatic=28f4039c636b6a7&hb_bidder_pubmatic=pubmatic&hb_size_rubicon=300x600&hb_pb_rubicon=10.00&hb_adid_rubicon=29019e2ab586a5a&hb_bidder_rubicon=rubicon'; + var expected = 'foobar=0x0%2C300x250%2C300x600&hb_size=300x250&hb_pb=10.00&hb_adid=233bcbee889d46d&hb_bidder=appnexus&hb_size_triplelift=0x0&hb_pb_triplelift=10.00&hb_adid_triplelift=222bb26f9e8bd&hb_bidder_triplelift=triplelift&hb_size_appnexus=300x250&hb_pb_appnexus=10.00&hb_adid_appnexus=233bcbee889d46d&hb_bidder_appnexus=appnexus&hb_size_pagescience=300x250&hb_pb_pagescience=10.00&hb_adid_pagescience=25bedd4813632d7&hb_bidder_pagescienc=pagescience&hb_size_brightcom=300x250&hb_pb_brightcom=10.00&hb_adid_brightcom=26e0795ab963896&hb_bidder_brightcom=brightcom&hb_size_brealtime=300x250&hb_pb_brealtime=10.00&hb_adid_brealtime=275bd666f5a5a5d&hb_bidder_brealtime=brealtime&hb_size_pubmatic=300x250&hb_pb_pubmatic=10.00&hb_adid_pubmatic=28f4039c636b6a7&hb_bidder_pubmatic=pubmatic&hb_size_rubicon=300x600&hb_pb_rubicon=10.00&hb_adid_rubicon=29019e2ab586a5a&hb_bidder_rubicon=rubicon'; var result = $$PREBID_GLOBAL$$.getAdserverTargetingForAdUnitCodeStr(adUnitCode); assert.equal(expected, result, 'returns expected string of ad targeting info'); }); @@ -194,7 +210,7 @@ describe('Unit: Prebid Module', function () { var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); var expected = { '/19968336/header-bid-tag-0': { - foobar: '300x250', + foobar: '0x0,300x250,300x600', hb_size: '300x250', hb_pb: '10.00', hb_adid: '233bcbee889d46d', @@ -218,17 +234,19 @@ describe('Unit: Prebid Module', function () { assert.deepEqual(targeting, expected); }); - it("should include a losing bid's custom ad targeting key when the bid has `alwaysUseBid` set to `true`", () => { + it("should include a losing bid's custom ad targeting key", () => { // Let's make sure we're getting the expected losing bid. - assert.equal($$PREBID_GLOBAL$$._bidsReceived[0]['bidderCode'], 'triplelift'); - assert.equal($$PREBID_GLOBAL$$._bidsReceived[0]['cpm'], 0.112256); + assert.equal(auction.getBidsReceived()[0]['bidderCode'], 'triplelift'); + assert.equal(auction.getBidsReceived()[0]['cpm'], 0.112256); // Modify the losing bid to have `alwaysUseBid=true` and a custom `adserverTargeting` key. - $$PREBID_GLOBAL$$._bidsReceived[0]['alwaysUseBid'] = true; - $$PREBID_GLOBAL$$._bidsReceived[0]['adserverTargeting'] = { + let _bidsReceived = getBidResponses(); + _bidsReceived[0]['adserverTargeting'] = { always_use_me: 'abc', }; + auction.getBidsReceived = function() { return _bidsReceived }; + var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); // Ensure targeting for both ad placements includes the custom key. @@ -239,7 +257,7 @@ describe('Unit: Prebid Module', function () { var expected = { '/19968336/header-bid-tag-0': { - foobar: '300x250', + foobar: '300x250,300x600', hb_size: '300x250', hb_pb: '10.00', hb_adid: '233bcbee889d46d', @@ -254,16 +272,19 @@ describe('Unit: Prebid Module', function () { hb_bidder: 'appnexus' } }; - assert.deepEqual(targeting, expected); }); - it('should not overwrite winning bids custom keys targeting key when the bid has `alwaysUseBid` set to `true`', () => { + it('should not overwrite winning bids custom keys targeting key', () => { + resetAuction(); // mimic a bidderSetting.standard key here for each bid and alwaysUseBid true for every bid - $$PREBID_GLOBAL$$._bidsReceived.forEach(bid => { + let _bidsReceived = getBidResponses(); + _bidsReceived.forEach(bid => { bid.adserverTargeting.custom_ad_id = bid.adId; - bid.alwaysUseBid = true; }); + + auction.getBidsReceived = function() { return _bidsReceived }; + $$PREBID_GLOBAL$$.bidderSettings = { 'standard': { adserverTargeting: [{ @@ -316,26 +337,27 @@ describe('Unit: Prebid Module', function () { }); it('should not send standard targeting keys when the bid has `sendStandardTargeting` set to `false`', () => { - $$PREBID_GLOBAL$$._bidsReceived.forEach(bid => { + let _bidsReceived = getBidResponses(); + _bidsReceived.forEach(bid => { bid.adserverTargeting.custom_ad_id = bid.adId; bid.sendStandardTargeting = false; }); + auction.getBidsReceived = function() { return _bidsReceived }; + var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); var expected = { '/19968336/header-bid-tag-0': { - foobar: '300x250', - custom_ad_id: '233bcbee889d46d' + foobar: '0x0,300x250,300x600', + custom_ad_id: '222bb26f9e8bd,233bcbee889d46d,25bedd4813632d7,26e0795ab963896,275bd666f5a5a5d,28f4039c636b6a7,29019e2ab586a5a' }, '/19968336/header-bid-tag1': { foobar: '728x90', custom_ad_id: '24bd938435ec3fc' } }; - assert.deepEqual(targeting, expected); - $$PREBID_GLOBAL$$.bidderSettings = {}; }); }); @@ -350,48 +372,138 @@ describe('Unit: Prebid Module', function () { }; let currentPriceBucket; let bid; + let auction; + let ajaxStub; + let cbTimeout = 3000; + let auctionManagerInstance = newAuctionManager(); + let targeting = newTargeting(auctionManagerInstance); + + let RESPONSE = { + 'version': '0.0.1', + 'tags': [{ + 'uuid': '4d0a6829338a07', + 'tag_id': 4799418, + 'auction_id': '2256922143947979797', + 'no_ad_url': 'http://lax1-ib.adnxs.com/no-ad', + 'timeout_ms': 2500, + 'ads': [{ + 'content_source': 'rtb', + 'ad_type': 'banner', + 'buyer_member_id': 958, + 'creative_id': 33989846, + 'media_type_id': 1, + 'media_subtype_id': 1, + 'cpm': 1.99, + 'cpm_publisher_currency': 0.500000, + 'publisher_currency_code': '$', + 'client_initiated_ad_counting': true, + 'rtb': { + 'banner': { + 'width': 728, + 'height': 90, + 'content': '' + }, + 'trackers': [{ + 'impression_urls': ['http://lax1-ib.adnxs.com/impression'] + }] + } + }] + }] + }; before(() => { - resetAuction(); + $$PREBID_GLOBAL$$.bidderSettings = {}; currentPriceBucket = configObj.getConfig('priceGranularity'); configObj.setConfig({ priceGranularity: customConfigObject }); - bid = Object.assign({}, - bidfactory.createBid(2), - getBidResponses()[5] - ); + sinon.stub(adaptermanager, 'makeBidRequests', () => ([{ + 'bidderCode': 'appnexus', + 'auctionId': '20882439e3238c', + 'bidderRequestId': '331f3cf3f1d9c8', + 'bids': [ + { + 'bidder': 'appnexus', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'sizes': [ + [ + 300, + 250 + ], + [ + 300, + 600 + ] + ], + 'bidId': '4d0a6829338a07', + 'bidderRequestId': '331f3cf3f1d9c8', + 'auctionId': '20882439e3238c' + } + ], + 'auctionStart': 1505250713622, + 'timeout': 3000 + }] + )); }); after(() => { configObj.setConfig({ priceGranularity: currentPriceBucket }); - resetAuction(); + adaptermanager.makeBidRequests.restore(); }) beforeEach(() => { - $$PREBID_GLOBAL$$._bidsReceived = []; - }) + let adUnits = [{ + code: 'div-gpt-ad-1460505748561-0', + sizes: [[300, 250], [300, 600]], + bids: [{ + bidder: 'appnexus', + params: { + placementId: '10433394' + } + }] + }]; + let adUnitCodes = ['div-gpt-ad-1460505748561-0']; + auction = auctionManagerInstance.createAuction({adUnits, adUnitCodes}); + ajaxStub = sinon.stub(ajaxLib, 'ajaxBuilder', function() { + return function(url, callback) { + const fakeResponse = sinon.stub(); + fakeResponse.returns('headerContent'); + callback.success(JSON.stringify(RESPONSE), { getResponseHeader: fakeResponse }); + } + }); + }); + + afterEach(() => { + ajaxStub.restore(); + }); it('should get correct hb_pb when using bid.cpm is between 0 to 5', () => { - bid.cpm = 2.1234; - bidmanager.addBidResponse(bid.adUnitCode, bid); - expect($$PREBID_GLOBAL$$.getAdserverTargeting()['/19968336/header-bid-tag-0'].hb_pb).to.equal('2.12'); + RESPONSE.tags[0].ads[0].cpm = 2.1234; + auction.callBids(cbTimeout); + let bidTargeting = targeting.getAllTargeting(); + expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('2.12'); }); it('should get correct hb_pb when using bid.cpm is between 5 to 8', () => { - bid.cpm = 6.78; - bidmanager.addBidResponse(bid.adUnitCode, bid); - expect($$PREBID_GLOBAL$$.getAdserverTargeting()['/19968336/header-bid-tag-0'].hb_pb).to.equal('6.75'); + RESPONSE.tags[0].ads[0].cpm = 6.78; + auction.callBids(cbTimeout); + let bidTargeting = targeting.getAllTargeting(); + expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('6.75'); }); it('should get correct hb_pb when using bid.cpm is between 8 to 20', () => { - bid.cpm = 19.5234; - bidmanager.addBidResponse(bid.adUnitCode, bid); - expect($$PREBID_GLOBAL$$.getAdserverTargeting()['/19968336/header-bid-tag-0'].hb_pb).to.equal('19.50'); + RESPONSE.tags[0].ads[0].cpm = 19.5234; + auction.callBids(cbTimeout); + let bidTargeting = targeting.getAllTargeting(); + expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('19.50'); }); it('should get correct hb_pb when using bid.cpm is between 20 to 25', () => { - bid.cpm = 21.5234; - bidmanager.addBidResponse(bid.adUnitCode, bid); - expect($$PREBID_GLOBAL$$.getAdserverTargeting()['/19968336/header-bid-tag-0'].hb_pb).to.equal('21.00'); + RESPONSE.tags[0].ads[0].cpm = 21.5234; + auction.callBids(cbTimeout); + let bidTargeting = targeting.getAllTargeting(); + expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('21.00'); }); }); @@ -467,6 +579,7 @@ describe('Unit: Prebid Module', function () { it('should set targeting from googletag data', function () { var slots = createSlotArray(); + slots[0].spySetTargeting.reset(); window.googletag.pubads().setSlots(slots); $$PREBID_GLOBAL$$.setTargetingForGPTAsync(); @@ -487,17 +600,20 @@ describe('Unit: Prebid Module', function () { expect(slots[0].spySetTargeting.args).to.deep.contain.members(expected); }); - it('should set targeting for bids with `alwaysUseBid=true`', function () { + it('should set targeting for bids', function () { // Make sure we're getting the expected losing bid. - assert.equal($$PREBID_GLOBAL$$._bidsReceived[0]['bidderCode'], 'triplelift'); - assert.equal($$PREBID_GLOBAL$$._bidsReceived[0]['cpm'], 0.112256); + assert.equal(auctionManager.getBidsReceived()[0]['bidderCode'], 'triplelift'); + assert.equal(auctionManager.getBidsReceived()[0]['cpm'], 0.112256); + resetAuction(); // Modify the losing bid to have `alwaysUseBid=true` and a custom `adserverTargeting` key. - $$PREBID_GLOBAL$$._bidsReceived[0]['alwaysUseBid'] = true; - $$PREBID_GLOBAL$$._bidsReceived[0]['adserverTargeting'] = { + let _bidsReceived = getBidResponses(); + _bidsReceived[0]['adserverTargeting'] = { always_use_me: 'abc', }; + auction.getBidsReceived = function() { return _bidsReceived }; + var slots = createSlotArray(); window.googletag.pubads().setSlots(slots); @@ -522,15 +638,11 @@ describe('Unit: Prebid Module', function () { ], [ 'foobar', - '300x250' + ['300x250', '300x600'] ], [ 'always_use_me', 'abc' - ], - [ - 'foobar', - '300x250' ] ]; @@ -560,16 +672,6 @@ describe('Unit: Prebid Module', function () { }); }); - describe('allBidsAvailable', function () { - it('should call bidmanager.allBidsBack', function () { - var spyAllBidsBack = sinon.spy(bidmanager, 'bidsBackAll'); - - $$PREBID_GLOBAL$$.allBidsAvailable(); - assert.ok(spyAllBidsBack.called, 'called bidmanager.allBidsBack'); - bidmanager.bidsBackAll.restore(); - }); - }); - describe('renderAd', function () { var bidId = 1; var doc = {}; @@ -579,6 +681,21 @@ describe('Unit: Prebid Module', function () { var spyLogMessage = null; var inIframe = true; + function pushBidResponseToAuction(obj) { + adResponse = Object.assign({ + auctionId: 1, + adId: bidId, + width: 300, + height: 250, + }, obj); + auction.getBidsReceived = function() { + let bidsReceived = getBidResponses(); + bidsReceived.push(adResponse); + return bidsReceived; + } + auction.getAuctionId = () => 1; + } + beforeEach(function () { doc = { write: sinon.spy(), @@ -597,13 +714,6 @@ describe('Unit: Prebid Module', function () { }; doc.getElementsByTagName.returns([elStub]); - adResponse = { - adId: bidId, - width: 300, - height: 250, - }; - $$PREBID_GLOBAL$$._bidsReceived.push(adResponse); - spyLogError = sinon.spy(utils, 'logError'); spyLogMessage = sinon.spy(utils, 'logMessage'); @@ -612,8 +722,7 @@ describe('Unit: Prebid Module', function () { }); afterEach(function () { - $$PREBID_GLOBAL$$._bidsReceived.splice($$PREBID_GLOBAL$$._bidsReceived.indexOf(adResponse), 1); - $$PREBID_GLOBAL$$._winningBids = []; + auction.getBidsReceived = getBidResponses; utils.logError.restore(); utils.logMessage.restore(); utils.inIframe.restore(); @@ -632,6 +741,9 @@ describe('Unit: Prebid Module', function () { }); it('should write the ad to the doc', function () { + pushBidResponseToAuction({ + ad: "" + }); adResponse.ad = ""; $$PREBID_GLOBAL$$.renderAd(doc, bidId); assert.ok(doc.write.calledWith(adResponse.ad), 'ad was written to doc'); @@ -639,18 +751,24 @@ describe('Unit: Prebid Module', function () { }); it('should place the url inside an iframe on the doc', function () { - adResponse.adUrl = 'http://server.example.com/ad/ad.js'; + pushBidResponseToAuction({ + adUrl: 'http://server.example.com/ad/ad.js' + }); $$PREBID_GLOBAL$$.renderAd(doc, bidId); assert.ok(elStub.insertBefore.called, 'url was written to iframe in doc'); }); it('should log an error when no ad or url', function () { + pushBidResponseToAuction({}); $$PREBID_GLOBAL$$.renderAd(doc, bidId); var error = 'Error trying to write ad. No ad for bid response id: ' + bidId; assert.ok(spyLogError.calledWith(error), 'expected error was logged'); }); it('should log an error when not in an iFrame', () => { + pushBidResponseToAuction({ + ad: "" + }); inIframe = false; $$PREBID_GLOBAL$$.renderAd(document, bidId); const error = 'Error trying to write ad. Ad render call ad id ' + bidId + ' was prevented from writing to the main document.'; @@ -658,14 +776,17 @@ describe('Unit: Prebid Module', function () { }); it('should not render videos', () => { - adResponse.mediatype = 'video'; + pushBidResponseToAuction({ + mediatype: 'video' + }); $$PREBID_GLOBAL$$.renderAd(doc, bidId); sinon.assert.notCalled(doc.write); - delete adResponse.mediatype; }); it('should catch errors thrown when trying to write ads to the page', function () { - adResponse.ad = ""; + pushBidResponseToAuction({ + ad: "" + }); var error = { message: 'doc write error' }; doc.write = sinon.stub().throws(error); @@ -683,413 +804,396 @@ describe('Unit: Prebid Module', function () { }); it('should save bid displayed to winning bid', function () { + pushBidResponseToAuction({ + ad: "" + }); $$PREBID_GLOBAL$$.renderAd(doc, bidId); - assert.equal($$PREBID_GLOBAL$$._winningBids[0], adResponse); + assert.deepEqual($$PREBID_GLOBAL$$.getAllWinningBids()[0], adResponse); }); }); describe('requestBids', () => { var adUnitsBackup; + var auctionManagerStub; + let logMessageSpy + + let spec = { + code: 'sampleBidder', + isBidRequestValid: () => {}, + buildRequests: () => {}, + interpretResponse: () => {}, + getUserSyncs: () => {} + }; + registerBidder(spec); + + describe('part 1', () => { + beforeEach(() => { + adUnitsBackup = auction.getAdUnits + auctionManagerStub = sinon.stub(auctionManager, 'createAuction', function() { + return auction; + }); + logMessageSpy = sinon.spy(utils, 'logMessage'); + }); - beforeEach(() => { - adUnitsBackup = $$PREBID_GLOBAL$$.adUnits; - }); - - afterEach(() => { - $$PREBID_GLOBAL$$.adUnits = adUnitsBackup; - resetAuction(); - }); - - it('should add bidsBackHandler callback to bidmanager', () => { - var spyAddOneTimeCallBack = sinon.spy(bidmanager, 'addOneTimeCallback'); - var requestObj = { - bidsBackHandler: function bidsBackHandlerCallback() { - } - }; - $$PREBID_GLOBAL$$.requestBids(requestObj); - assert.ok(spyAddOneTimeCallBack.calledWith(requestObj.bidsBackHandler), - 'called bidmanager.addOneTimeCallback'); - bidmanager.addOneTimeCallback.restore(); - }); - - it('should log message when adUnits not configured', () => { - const logMessageSpy = sinon.spy(utils, 'logMessage'); + afterEach(() => { + auction.getAdUnits = adUnitsBackup; + auctionManager.createAuction.restore(); + utils.logMessage.restore(); + resetAuction(); + }); - $$PREBID_GLOBAL$$.adUnits = []; - $$PREBID_GLOBAL$$.requestBids({}); + it('should log message when adUnits not configured', () => { + $$PREBID_GLOBAL$$.adUnits = []; + $$PREBID_GLOBAL$$.requestBids({}); - assert.ok(logMessageSpy.calledWith('No adUnits configured. No bids requested.'), 'expected message was logged'); - utils.logMessage.restore(); - }); + assert.ok(logMessageSpy.calledWith('No adUnits configured. No bids requested.'), 'expected message was logged'); + }); - it('should execute callback after timeout', () => { - var spyExecuteCallback = sinon.spy(bidmanager, 'executeCallback'); - var clock = sinon.useFakeTimers(); - var requestObj = { - bidsBackHandler: function bidsBackHandlerCallback() { - }, + it('should execute callback after timeout', () => { + let clock = sinon.useFakeTimers(); + let requestObj = { + bidsBackHandler: function bidsBackHandlerCallback() {}, + timeout: timeout, + adUnits: auction.getAdUnits() + }; - timeout: 2000 - }; + $$PREBID_GLOBAL$$.requestBids(requestObj); + let re = new RegExp('^Auction [a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12} timedOut$'); + clock.tick(requestObj.timeout - 1); + assert.ok(logMessageSpy.neverCalledWith(sinon.match(re)), 'executeCallback not called'); - $$PREBID_GLOBAL$$.requestBids(requestObj); + clock.tick(1); + assert.ok(logMessageSpy.calledWith(sinon.match(re)), 'executeCallback called'); - clock.tick(requestObj.timeout - 1); - assert.ok(spyExecuteCallback.notCalled, 'bidmanager.executeCallback not called'); + clock.restore(); + }); - clock.tick(1); - assert.ok(spyExecuteCallback.called, 'called bidmanager.executeCallback'); + it('should execute callback immediately if adUnits is empty', () => { + var bidsBackHandler = function bidsBackHandlerCallback() {}; + var spyExecuteCallback = sinon.spy(bidsBackHandler); - bidmanager.executeCallback.restore(); - clock.restore(); - }); + $$PREBID_GLOBAL$$.adUnits = []; + $$PREBID_GLOBAL$$.requestBids({ + bidsBackHandler: spyExecuteCallback + }); - it('should execute callback immediately if adUnits is empty', () => { - var spyExecuteCallback = sinon.spy(bidmanager, 'executeCallback'); + assert.ok(spyExecuteCallback.calledOnce, 'callback executed immediately when adUnits is' + + ' empty'); + }); - $$PREBID_GLOBAL$$.adUnits = []; - $$PREBID_GLOBAL$$.requestBids({}); + it('should not propagate exceptions from bidsBackHandler', () => { + $$PREBID_GLOBAL$$.adUnits = []; - assert.ok(spyExecuteCallback.calledOnce, 'callback executed immediately when adUnits is' + - ' empty'); + var requestObj = { + bidsBackHandler: function bidsBackHandlerCallback() { + var test; + return test.test; + } + }; - bidmanager.executeCallback.restore(); + expect(() => { + $$PREBID_GLOBAL$$.requestBids(requestObj); + }).not.to.throw(); + }); }); - it('should not propagate exceptions from bidsBackHandler', () => { - $$PREBID_GLOBAL$$.adUnits = []; + describe.skip('#video', () => { + let spyCallBids; + let createAuctionStub; + let adUnits; - var requestObj = { - bidsBackHandler: function bidsBackHandlerCallback() { - var test; - return test.test; - } - }; - - expect(() => { - $$PREBID_GLOBAL$$.requestBids(requestObj); - }).not.to.throw(); - }); + before(() => { + adUnits = [{ + code: 'adUnit-code', + mediaType: 'video', + sizes: [[300, 250], [300, 600]], + bids: [ + {bidder: 'appnexus', params: {placementId: 'id'}}, + {bidder: 'sampleBidder', params: {placementId: 'id'}} + ] + }]; + adUnitCodes = ['adUnit-code']; + let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout}); + spyCallBids = sinon.spy(adaptermanager, 'callBids'); + createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + }); - it('should call callBids function on adaptermanager', () => { - var spyCallBids = sinon.spy(adaptermanager, 'callBids'); + after(() => { + auctionModule.newAuction.restore(); + adaptermanager.callBids.restore(); + }); - $$PREBID_GLOBAL$$.requestBids({}); - assert.ok(spyCallBids.called, 'called adaptermanager.callBids'); - adaptermanager.callBids.restore(); + it('should not callBids if a video adUnit has non-video bidders', () => { + const videoAdaptersBackup = adaptermanager.videoAdapters; + adaptermanager.videoAdapters = ['appnexus']; + $$PREBID_GLOBAL$$.requestBids({adUnits}); + sinon.assert.notCalled(adaptermanager.callBids); + adaptermanager.videoAdapters = videoAdaptersBackup; + }); }); - it('should only request video bidders on video adunits', () => { - sinon.spy(adaptermanager, 'callBids'); - const videoAdaptersBackup = adaptermanager.videoAdapters; - adaptermanager.videoAdapters = ['appnexusAst']; - const adUnits = [{ - code: 'adUnit-code', - mediaType: 'video', - bids: [ - {bidder: 'appnexus', params: {placementId: 'id'}}, - {bidder: 'appnexusAst', params: {placementId: 'id'}} - ] - }]; - - $$PREBID_GLOBAL$$.requestBids({adUnits}); - sinon.assert.calledOnce(adaptermanager.callBids); + describe('#video', () => { + let spyCallBids; + let createAuctionStub; + let adUnits; - const spyArgs = adaptermanager.callBids.getCall(0); - const biddersCalled = spyArgs.args[0].adUnits[0].bids; - expect(biddersCalled.length).to.equal(1); + before(() => { + adUnits = [{ + code: 'adUnit-code', + mediaType: 'video', + sizes: [[300, 250], [300, 600]], + bids: [ + {bidder: 'appnexus', params: {placementId: 'id'}} + ] + }]; + adUnitCodes = ['adUnit-code']; + let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout}); + spyCallBids = sinon.spy(adaptermanager, 'callBids'); + createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + }) + + after(() => { + auctionModule.newAuction.restore(); + adaptermanager.callBids.restore(); + }); - adaptermanager.callBids.restore(); - adaptermanager.videoAdapters = videoAdaptersBackup; + it('should callBids if a video adUnit has all video bidders', () => { + const videoAdaptersBackup = adaptermanager.videoAdapters; + adaptermanager.videoAdapters = ['appnexus']; + $$PREBID_GLOBAL$$.requestBids({adUnits}); + sinon.assert.calledOnce(adaptermanager.callBids); + 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'}} - ] - }]; + describe('#native', () => { + let spyCallBids; + let createAuctionStub; + let adUnits; - $$PREBID_GLOBAL$$.requestBids({adUnits}); - sinon.assert.calledOnce(adaptermanager.callBids); + before(() => { + adUnits = [{ + code: 'adUnit-code', + mediaType: 'native', + sizes: [[300, 250], [300, 600]], + bids: [ + {bidder: 'appnexus', params: {placementId: 'id'}}, + {bidder: 'sampleBidder', params: {placementId: 'id'}} + ] + }]; + adUnitCodes = ['adUnit-code']; + let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout}); + spyCallBids = sinon.spy(adaptermanager, 'callBids'); + createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.returns(auction); + }); - const spyArgs = adaptermanager.callBids.getCall(0); - const biddersCalled = spyArgs.args[0].adUnits[0].bids; - expect(biddersCalled.length).to.equal(1); + after(() => { + auctionModule.newAuction.restore(); + adaptermanager.callBids.restore(); + }); - adaptermanager.callBids.restore(); - adaptermanager.videoAdapters = videoAdaptersBackup; + it('should only request native bidders on native adunits', () => { + // appnexus is a native bidder, appnexus is not + $$PREBID_GLOBAL$$.requestBids({adUnits}); + sinon.assert.calledOnce(adaptermanager.callBids); + const spyArgs = adaptermanager.callBids.getCall(0); + const biddersCalled = spyArgs.args[0][0].bids; + expect(biddersCalled.length).to.equal(1); + }); }); - it('should callBids if a video adUnit has all video bidders', () => { - sinon.spy(adaptermanager, 'callBids'); - const videoAdaptersBackup = adaptermanager.videoAdapters; - adaptermanager.videoAdapters = ['appnexusAst']; - const adUnits = [{ - code: 'adUnit-code', - mediaType: 'video', - bids: [ - {bidder: 'appnexusAst', params: {placementId: 'id'}} - ] - }]; - - $$PREBID_GLOBAL$$.requestBids({adUnits}); - sinon.assert.calledOnce(adaptermanager.callBids); + describe('part 2', () => { + let spyCallBids; + let createAuctionStub; + let adUnits; - adaptermanager.callBids.restore(); - adaptermanager.videoAdapters = videoAdaptersBackup; - }); + before(() => { + adUnits = [{ + code: 'adUnit-code', + sizes: [[300, 250], [300, 600]], + bids: [ + {bidder: 'appnexus', params: {placementId: '10433394'}} + ] + }]; + let adUnitCodes = ['adUnit-code']; + let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout}); + + adUnits[0]['mediaType'] = 'native'; + adUnitCodes = ['adUnit-code']; + let auction1 = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout}); + + adUnits = [{ + code: 'adUnit-code', + nativeParams: {type: 'image'}, + sizes: [[300, 250], [300, 600]], + bids: [ + {bidder: 'appnexus', params: {placementId: 'id'}} + ] + }]; + let auction3 = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout}); - it('should only request native bidders on native adunits', () => { - sinon.spy(adaptermanager, 'callBids'); - // appnexusAst is a native bidder, appnexus is not - const adUnits = [{ - code: 'adUnit-code', - mediaType: 'native', - bids: [ - {bidder: 'appnexus', params: {placementId: 'id'}}, - {bidder: 'appnexusAst', params: {placementId: 'id'}} - ] - }]; + let createAuctionStub = sinon.stub(auctionModule, 'newAuction'); + createAuctionStub.onCall(0).returns(auction1); + createAuctionStub.onCall(2).returns(auction3); + createAuctionStub.returns(auction); + }); - $$PREBID_GLOBAL$$.requestBids({adUnits}); - sinon.assert.calledOnce(adaptermanager.callBids); + after(() => { + auctionModule.newAuction.restore(); + }); - const spyArgs = adaptermanager.callBids.getCall(0); - const biddersCalled = spyArgs.args[0].adUnits[0].bids; - expect(biddersCalled.length).to.equal(1); + beforeEach(() => { + spyCallBids = sinon.spy(adaptermanager, 'callBids'); + }) - adaptermanager.callBids.restore(); - }); + afterEach(() => { + adaptermanager.callBids.restore(); + }) - it('should callBids if a native adUnit has all native bidders', () => { - sinon.spy(adaptermanager, 'callBids'); - // TODO: appnexusAst is currently hardcoded in native.js, update this text when fixed - const adUnits = [{ - code: 'adUnit-code', - mediaType: 'native', - bids: [ - {bidder: 'appnexusAst', params: {placementId: 'id'}} - ] - }]; + it('should callBids if a native adUnit has all native bidders', () => { + $$PREBID_GLOBAL$$.requestBids({adUnits}); + sinon.assert.calledOnce(adaptermanager.callBids); + }); - $$PREBID_GLOBAL$$.requestBids({adUnits}); - sinon.assert.calledOnce(adaptermanager.callBids); + it('should call callBids function on adaptermanager', () => { + let adUnits = [{ + code: 'adUnit-code', + sizes: [[300, 250], [300, 600]], + bids: [ + {bidder: 'appnexus', params: {placementId: '10433394'}} + ] + }]; + $$PREBID_GLOBAL$$.requestBids({adUnits}); + assert.ok(spyCallBids.called, 'called adaptermanager.callBids'); + }); - adaptermanager.callBids.restore(); + it('splits native type to individual native assets', () => { + let adUnits = [{ + code: 'adUnit-code', + nativeParams: {type: 'image'}, + sizes: [[300, 250], [300, 600]], + bids: [ + {bidder: 'appnexus', params: {placementId: 'id'}} + ] + }]; + $$PREBID_GLOBAL$$.requestBids({adUnits}); + const spyArgs = adaptermanager.callBids.getCall(0); + const nativeRequest = spyArgs.args[1][0].bids[0].nativeParams; + expect(nativeRequest).to.deep.equal({ + image: {required: true}, + title: {required: true}, + sponsoredBy: {required: true}, + clickUrl: {required: true}, + body: {required: false}, + icon: {required: false}, + }); + resetAuction(); + }); }); - it('splits native type to individual native assets', () => { - $$PREBID_GLOBAL$$._bidsRequested = []; + describe('part-3', () => { + let auctionManagerInstance = newAuctionManager(); + let auctionManagerStub; + let adUnits1 = getAdUnits().filter((adUnit) => { + return adUnit.code === '/19968336/header-bid-tag1'; + }); + let adUnitCodes1 = getAdUnits().map(unit => unit.code); + let auction1 = auctionManagerInstance.createAuction({adUnits: adUnits1, adUnitCodes: adUnitCodes1}); - const adUnits = [{ - code: 'adUnit-code', - nativeParams: {type: 'image'}, - bids: [ - {bidder: 'appnexusAst', params: {placementId: 'id'}} - ] - }]; + let adUnits2 = getAdUnits().filter((adUnit) => { + return adUnit.code === '/19968336/header-bid-tag-0'; + }); + let adUnitCodes2 = getAdUnits().map(unit => unit.code); + let auction2 = auctionManagerInstance.createAuction({adUnits: adUnits2, adUnitCodes: adUnitCodes2}); + let spyCallBids; + + auction1.getBidRequests = function() { + return getBidRequests().map((req) => { + req.bids = req.bids.filter((bid) => { + return bid.adUnitCode === '/19968336/header-bid-tag1'; + }); + return (req.bids.length > 0) ? req : undefined; + }).filter((item) => { + return item != undefined; + }); + }; + auction1.getBidsReceived = function() { + return getBidResponses().filter((bid) => { + return bid.adUnitCode === '/19968336/header-bid-tag1'; + }); + }; - $$PREBID_GLOBAL$$.requestBids({adUnits}); + auction2.getBidRequests = function() { + return getBidRequests().map((req) => { + req.bids = req.bids.filter((bid) => { + return bid.adUnitCode === '/19968336/header-bid-tag-0'; + }); + return (req.bids.length > 0) ? req : undefined; + }).filter((item) => { + return item != undefined; + }); + }; + auction2.getBidsReceived = function() { + return getBidResponses().filter((bid) => { + return bid.adUnitCode === '/19968336/header-bid-tag-0'; + }); + }; - const nativeRequest = $$PREBID_GLOBAL$$._bidsRequested[0].bids[0].nativeParams; - expect(nativeRequest).to.deep.equal({ - image: {required: true}, - title: {required: true}, - sponsoredBy: {required: true}, - clickUrl: {required: true}, - body: {required: false}, - icon: {required: false}, + beforeEach(function() { + spyCallBids = sinon.spy(adaptermanager, 'callBids'); + auctionManagerStub = sinon.stub(auctionManager, 'createAuction'); + auctionManagerStub.onCall(0).returns(auction1); + auctionManagerStub.onCall(1).returns(auction2); }); - resetAuction(); - }); + afterEach(function() { + auctionManager.createAuction.restore(); + adaptermanager.callBids.restore(); + }); - it('should queue bid requests when a previous bid request is in process', () => { - var spyCallBids = sinon.spy(adaptermanager, 'callBids'); - var clock = sinon.useFakeTimers(); - var requestObj1 = { - adUnitCodes: ['/19968336/header-bid-tag1'], - bidsBackHandler: function bidsBackHandlerCallback() { - }, + it('should not queue bid requests when a previous bid request is in process', () => { + var requestObj1 = { + bidsBackHandler: function bidsBackHandlerCallback() {}, + timeout: 2000, + adUnits: auction1.getAdUnits() + }; - timeout: 2000 - }; + var requestObj2 = { + bidsBackHandler: function bidsBackHandlerCallback() {}, + timeout: 2000, + adUnits: auction2.getAdUnits() + }; - var requestObj2 = { - adUnitCodes: ['/19968336/header-bid-tag-0'], - bidsBackHandler: function bidsBackHandlerCallback() { - }, + assert.equal(auctionManager.getBidsReceived().length, 8, '_bidsReceived contains 8 bids'); - timeout: 2000 - }; + $$PREBID_GLOBAL$$.requestBids(requestObj1); + $$PREBID_GLOBAL$$.requestBids(requestObj2); - assert.equal($$PREBID_GLOBAL$$._bidsReceived.length, 8, '_bidsReceived contains 8 bids'); - - $$PREBID_GLOBAL$$.requestBids(requestObj1); - $$PREBID_GLOBAL$$.requestBids(requestObj2); - - clock.tick(requestObj1.timeout - 1); - assert.ok(spyCallBids.calledOnce, 'When two requests for bids are made only one should' + - ' callBids immediately'); - assert.equal($$PREBID_GLOBAL$$._bidsReceived.length, 7, '_bidsReceived now contains 7 bids'); - assert.deepEqual($$PREBID_GLOBAL$$._bidsReceived - .find(bid => requestObj1.adUnitCodes.includes(bid.adUnitCode)), undefined, 'Placements' + - ' for' + - ' current request have been cleared of bids'); - assert.deepEqual($$PREBID_GLOBAL$$._bidsReceived - .filter(bid => requestObj2.adUnitCodes.includes(bid.adUnitCode)).length, 7, 'Placements' + - ' for previous request have not been cleared of bids'); - assert.deepEqual($$PREBID_GLOBAL$$._adUnitCodes, ['/19968336/header-bid-tag1'], '_adUnitCodes is' + - ' for first request'); - assert.ok($$PREBID_GLOBAL$$._bidsReceived.length > 0, '_bidsReceived contains bids'); - assert.deepEqual($$PREBID_GLOBAL$$.getBidResponses(), {}, 'yet getBidResponses returns' + - ' empty object for first request (no matching bids for current placement'); - assert.deepEqual($$PREBID_GLOBAL$$.getAdserverTargeting(), {}, 'getAdserverTargeting' + - ' returns empty object for first request'); - clock.tick(1); - - // restore _bidsReceived to simulate more bids returned - $$PREBID_GLOBAL$$._bidsReceived = getBidResponses(); - assert.ok(spyCallBids.calledTwice, 'The second queued request should callBids when the' + - ' first request has completed'); - assert.deepEqual($$PREBID_GLOBAL$$._adUnitCodes, ['/19968336/header-bid-tag-0'], '_adUnitCodes is' + - 'now for second request'); - assert.deepEqual($$PREBID_GLOBAL$$.getBidResponses(), { - '/19968336/header-bid-tag-0': { - 'bids': [ - { - 'bidderCode': 'brightcom', - 'width': 300, - 'height': 250, - 'statusMessage': 'Bid available', - 'adId': '26e0795ab963896', - 'cpm': 0.17, - 'ad': "", - 'responseTimestamp': 1462919239420, - 'requestTimestamp': 1462919238937, - 'bidder': 'brightcom', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'timeToRespond': 483, - 'pbLg': '0.00', - 'pbMg': '0.10', - 'pbHg': '0.17', - 'pbAg': '0.15', - 'size': '300x250', - 'requestId': 654321, - 'adserverTargeting': { - 'hb_bidder': 'brightcom', - 'hb_adid': '26e0795ab963896', - 'hb_pb': '10.00', - 'hb_size': '300x250', - 'foobar': '300x250' - } - }, - { - 'bidderCode': 'brealtime', - 'width': 300, - 'height': 250, - 'statusMessage': 'Bid available', - 'adId': '275bd666f5a5a5d', - 'creative_id': 29681110, - 'cpm': 0.5, - 'adUrl': 'http://lax1-ib.adnxs.com/ab?e=wqT_3QLzBKhzAgAAAwDWAAUBCMjAybkFEIPr4YfMvKLoQBjL84KE1tzG-kkgASotCQAAAQII4D8RAQcQAADgPxkJCQjwPyEJCQjgPykRCaAwuvekAji-B0C-B0gCUNbLkw5YweAnYABokUB4mo8EgAEBigEDVVNEkgUG8FKYAawCoAH6AagBAbABALgBAcABA8gBANABANgBAOABAPABAIoCOnVmKCdhJywgNDk0NDcyLCAxNDYyOTE5MjQwKTt1ZigncicsIDI5NjgxMTEwLDIeAPBvkgLNASFsU2NQWlFpNjBJY0VFTmJMa3c0WUFDREI0Q2N3QURnQVFBUkl2Z2RRdXZla0FsZ0FZSk1IYUFCdzNBMTRDb0FCcGh5SUFRcVFBUUdZQVFHZ0FRR29BUU93QVFDNUFRQUFBQUFBQU9BX3dRRQkMSEFEZ1A4a0JHZmNvazFBejFUX1oVKCRQQV80QUVBOVFFBSw8bUFLS2dOU0NEYUFDQUxVQwUVBEwwCQh0T0FDQU9nQ0FQZ0NBSUFEQVEuLpoCJSFDUWxfYXdpMtAA8KZ3ZUFuSUFRb2lvRFVnZzAu2ALoB-ACx9MB6gIfaHR0cDovL3ByZWJpZC5vcmc6OTk5OS9ncHQuaHRtbIADAIgDAZADAJgDBaADAaoDALADALgDAMADrALIAwDYAwDgAwDoAwD4AwOABACSBAQvanB0mAQAogQKMTAuMS4xMy4zN6gEi-wJsgQICAAQABgAIAC4BADABADIBADSBAsxMC4wLjg1LjIwOA..&s=975cfe6518f064683541240f0d780d93a5f973da&referrer=http%3A%2F%2Fprebid.org%3A9999%2Fgpt.html', - 'responseTimestamp': 1462919239486, - 'requestTimestamp': 1462919238941, - 'bidder': 'brealtime', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'timeToRespond': 545, - 'pbLg': '0.50', - 'pbMg': '0.50', - 'pbHg': '0.50', - 'pbAg': '0.50', - 'size': '300x250', - 'requestId': 654321, - 'adserverTargeting': { - 'hb_bidder': 'brealtime', - 'hb_adid': '275bd666f5a5a5d', - 'hb_pb': '10.00', - 'hb_size': '300x250', - 'foobar': '300x250' - } - }, - { - 'bidderCode': 'pubmatic', - 'width': '300', - 'height': '250', - 'statusMessage': 'Bid available', - 'adId': '28f4039c636b6a7', - 'adSlot': '39620189@300x250', - 'cpm': 5.9396, - 'ad': "\r
", - 'dealId': '', - 'responseTimestamp': 1462919239544, - 'requestTimestamp': 1462919238922, - 'bidder': 'pubmatic', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'timeToRespond': 622, - 'pbLg': '5.00', - 'pbMg': '5.90', - 'pbHg': '5.93', - 'pbAg': '5.90', - 'size': '300x250', - 'requestId': 654321, - 'adserverTargeting': { - 'hb_bidder': 'pubmatic', - 'hb_adid': '28f4039c636b6a7', - 'hb_pb': '10.00', - 'hb_size': '300x250', - 'foobar': '300x250' - } - }, - { - 'bidderCode': 'rubicon', - 'width': 300, - 'height': 600, - 'statusMessage': 'Bid available', - 'adId': '29019e2ab586a5a', - 'cpm': 2.74, - 'ad': '', - 'responseTimestamp': 1462919239860, - 'requestTimestamp': 1462919238934, - 'bidder': 'rubicon', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'timeToRespond': 926, - 'pbLg': '2.50', - 'pbMg': '2.70', - 'pbHg': '2.74', - 'pbAg': '2.70', - 'size': '300x600', - 'requestId': 654321, - 'adserverTargeting': { - 'hb_bidder': 'rubicon', - 'hb_adid': '29019e2ab586a5a', - 'hb_pb': '10.00', - 'hb_size': '300x600', - 'foobar': '300x600' - } - } - ] - } - }, 'getBidResponses returns info for current bid request'); + assert.ok(spyCallBids.calledTwice, 'When two requests for bids are made both should be' + + ' callBids immediately'); - assert.deepEqual($$PREBID_GLOBAL$$.getAdserverTargeting(), { - '/19968336/header-bid-tag-0': { - 'foobar': '300x250', - 'hb_size': '300x250', - 'hb_pb': '10.00', - 'hb_adid': '233bcbee889d46d', - 'hb_bidder': 'appnexus' + let result = targeting.getAllTargeting(); // $$PREBID_GLOBAL$$.getAdserverTargeting(); + let expected = { + '/19968336/header-bid-tag-0': { + 'foobar': '0x0,300x250,300x600', + 'hb_size': '300x250', + 'hb_pb': '10.00', + 'hb_adid': '233bcbee889d46d', + 'hb_bidder': 'appnexus' + }, + '/19968336/header-bid-tag1': { + 'hb_bidder': 'appnexus', + 'hb_adid': '24bd938435ec3fc', + 'hb_pb': '10.00', + 'hb_size': '728x90', + 'foobar': '728x90' + } } - }, 'targeting info returned for current placements'); - resetAuction(); - adaptermanager.callBids.restore(); + assert.deepEqual(result, expected, 'targeting info returned for current placements'); + }); }); }); @@ -1145,31 +1249,6 @@ describe('Unit: Prebid Module', function () { }); }); - describe('addCallback', () => { - it('should log error and return null id when error registering callback', () => { - var spyLogError = sinon.spy(utils, 'logError'); - var id = $$PREBID_GLOBAL$$.addCallback('event', 'fakeFunction'); - assert.equal(id, null, 'id returned was null'); - assert.ok(spyLogError.calledWith('error registering callback. Check method signature'), - 'expected error was logged'); - utils.logError.restore(); - }); - - it('should add callback to bidmanager', () => { - var spyAddCallback = sinon.spy(bidmanager, 'addCallback'); - var id = $$PREBID_GLOBAL$$.addCallback('event', Function); - assert.ok(spyAddCallback.calledWith(id, Function, 'event'), 'called bidmanager.addCallback'); - bidmanager.addCallback.restore(); - }); - }); - - describe('removeCallback', () => { - it('should return null', () => { - const id = $$PREBID_GLOBAL$$.removeCallback(); - assert.equal(id, null); - }); - }); - describe('registerBidAdapter', () => { it('should register bidAdaptor with adaptermanager', () => { var registerBidAdapterSpy = sinon.spy(adaptermanager, 'registerBidAdapter'); @@ -1191,19 +1270,6 @@ describe('Unit: Prebid Module', function () { }); }); - describe('bidsAvailableForAdapter', () => { - it('should update requested bid with status set to available', () => { - const bidderCode = 'appnexus'; - $$PREBID_GLOBAL$$.bidsAvailableForAdapter(bidderCode); - - const requestedBids = $$PREBID_GLOBAL$$._bidsRequested.find(bid => bid.bidderCode === bidderCode); - requestedBids.bids.forEach(bid => { - assert.equal(bid.bidderCode, bidderCode, 'bidderCode was set'); - assert.equal(bid.statusMessage, 'Bid available', 'bid set as available'); - }); - }); - }); - describe('createBid', () => { it('should return a bid object', () => { const statusCode = 1; @@ -1217,18 +1283,6 @@ describe('Unit: Prebid Module', function () { }); }); - describe('addBidResponse', () => { - it('should call bidmanager.addBidResponse', () => { - const addBidResponseStub = sinon.stub(bidmanager, 'addBidResponse'); - const adUnitCode = 'testcode'; - const bid = $$PREBID_GLOBAL$$.createBid(0); - - $$PREBID_GLOBAL$$.addBidResponse(adUnitCode, bid); - assert.ok(addBidResponseStub.calledWith(adUnitCode, bid), 'called bidmanager.addBidResponse'); - bidmanager.addBidResponse.restore(); - }); - }); - describe('loadScript', () => { it('should call adloader.loadScript', () => { const loadScriptSpy = sinon.spy(adloader, 'loadScript'); @@ -1242,79 +1296,6 @@ describe('Unit: Prebid Module', function () { }); }); - // describe('enableAnalytics', () => { - // let logErrorSpy; - // - // beforeEach(() => { - // logErrorSpy = sinon.spy(utils, 'logError'); - // }); - // - // afterEach(() => { - // utils.logError.restore(); - // }); - // - // it('should log error when not passed options', () => { - // const error = '$$PREBID_GLOBAL$$.enableAnalytics should be called with option {}'; - // $$PREBID_GLOBAL$$.enableAnalytics(); - // assert.ok(logErrorSpy.calledWith(error), 'expected error was logged'); - // }); - // - // it('should call ga.enableAnalytics with options', () => { - // const enableAnalyticsSpy = sinon.spy(ga, 'enableAnalytics'); - // - // let options = {'provider': 'ga'}; - // $$PREBID_GLOBAL$$.enableAnalytics(options); - // assert.ok(enableAnalyticsSpy.calledWith({}), 'ga.enableAnalytics called with empty options object'); - // - // options['options'] = 'testoptions'; - // $$PREBID_GLOBAL$$.enableAnalytics(options); - // assert.ok(enableAnalyticsSpy.calledWith(options.options), 'ga.enableAnalytics called with provided options'); - // - // ga.enableAnalytics.restore(); - // }); - // - // it('should catch errors thrown from ga.enableAnalytics', () => { - // const error = {message: 'Error calling GA: '}; - // const enableAnalyticsStub = sinon.stub(ga, 'enableAnalytics').throws(error); - // const options = {'provider': 'ga'}; - // - // $$PREBID_GLOBAL$$.enableAnalytics(options); - // assert.ok(logErrorSpy.calledWith(error.message), 'expected error was caught'); - // ga.enableAnalytics.restore(); - // }); - // - // it('should return null for other providers', () => { - // const options = {'provider': 'other_provider'}; - // const returnValue = $$PREBID_GLOBAL$$.enableAnalytics(options); - // assert.equal(returnValue, null, 'expected return value'); - // }); - // }); - - describe('sendTimeoutEvent', () => { - it('should emit BID_TIMEOUT for timed out bids', () => { - const eventsEmitSpy = sinon.spy(events, 'emit'); - - var requestObj = { - bidsBackHandler: function bidsBackHandlerCallback() {}, - timeout: 20 - }; - var adUnits = [{ - code: 'code', - bids: [{ - bidder: 'appnexus', - params: { placementId: '123' } - }] - }]; - $$PREBID_GLOBAL$$.adUnits = adUnits; - $$PREBID_GLOBAL$$.requestBids(requestObj); - - setTimeout(function () { - assert.ok(eventsEmitSpy.calledWith(CONSTANTS.EVENTS.BID_TIMEOUT), 'emitted events BID_TIMEOUT'); - events.emit.restore(); - }, 100); - }); - }); - describe('aliasBidder', () => { it('should call adaptermanager.aliasBidder', () => { const aliasBidAdapterSpy = sinon.spy(adaptermanager, 'aliasBidAdapter'); @@ -1388,101 +1369,16 @@ describe('Unit: Prebid Module', function () { }); }); - describe('getAllWinningBids', () => { - it('should return all winning bids', () => { - const bids = {name: 'a winning bid'}; - $$PREBID_GLOBAL$$._winningBids = bids; - - assert.deepEqual($$PREBID_GLOBAL$$.getAllWinningBids(), bids); - - $$PREBID_GLOBAL$$._winningBids = []; - }); - }); - describe('emit event', () => { - it('should call AUCTION_END only once', () => { - resetAuction(); - var spyClearAuction = sinon.spy($$PREBID_GLOBAL$$, 'clearAuction'); - var clock1 = sinon.useFakeTimers(); - - var requestObj = { - bidsBackHandler: function bidsBackHandlerCallback() {}, - timeout: 2000, - }; - - $$PREBID_GLOBAL$$.requestBids(requestObj); - clock1.tick(2001); - assert.ok(spyClearAuction.calledOnce, true); - - $$PREBID_GLOBAL$$._bidsRequested = [{ - 'bidderCode': 'appnexus', - 'requestId': '1863e370099523', - 'bidderRequestId': '2946b569352ef2', - 'bids': [ - { - 'bidder': 'appnexus', - 'params': { - 'placementId': '4799418', - 'test': 'me' - }, - 'placementCode': '/19968336/header-bid-tag1', - 'sizes': [[728, 90], [970, 90]], - 'bidId': '392b5a6b05d648', - 'bidderRequestId': '2946b569352ef2', - 'requestId': '1863e370099523', - 'startTime': 1462918897462, - 'status': 1 - } - ], - 'start': 1462918897460 - }]; - - $$PREBID_GLOBAL$$._bidsReceived = []; - - var bid = Object.assign({ - 'bidderCode': 'appnexus', - 'width': 728, - 'height': 90, - 'statusMessage': 'Bid available', - 'adId': '24bd938435ec3fc', - 'creative_id': 33989846, - 'cpm': 0, - 'adUrl': 'http://lax1-ib.adnxs.com/ab?e=wqT_3QLyBKhyAgAAAwDWAAUBCMjAybkFEOOryfjI7rGNWhjL84KE1tzG-kkgASotCQAAAQII4D8RAQcQAADgPxkJCQjwPyEJCQjgPykRCaAwuvekAji-B0C-B0gCUNbJmhBYweAnYABokUB4mt0CgAEBigEDVVNEkgUG8ECYAdgFoAFaqAEBsAEAuAEBwAEDyAEA0AEA2AEA4AEA8AEAigI6dWYoJ2EnLCA0OTQ0NzIsIDE0NjI5MTkyNDApOwEcLHInLCAzMzk4OTg0NjYeAPBvkgLNASFwU2Y1YUFpNjBJY0VFTmJKbWhBWUFDREI0Q2N3QURnQVFBUkl2Z2RRdXZla0FsZ0FZSk1IYUFCd3lnNTRDb0FCcGh5SUFRcVFBUUdZQVFHZ0FRR29BUU93QVFDNUFRQUFBQUFBQU9BX3dRRQkMSEFEZ1A4a0JJNTJDbGs5VjB6X1oVKCRQQV80QUVBOVFFBSw8bUFLS2dNQ0NENkFDQUxVQwUVBEwwCQh0T0FDQU9nQ0FQZ0NBSUFEQVEuLpoCJSFfZ2lqYXdpMtAA8KZ3ZUFuSUFRb2lvREFnZzgu2ALoB-ACx9MB6gIfaHR0cDovL3ByZWJpZC5vcmc6OTk5OS9ncHQuaHRtbIADAIgDAZADAJgDBaADAaoDALADALgDAMADrALIAwDYAwDgAwDoAwD4AwOABACSBAQvanB0mAQAogQKMTAuMS4xMy4zN6gEi-wJsgQICAAQABgAIAC4BADABADIBADSBAsxMC4wLjgwLjI0MA..&s=1f584d32c2d7ae3ce3662cfac7ca24e710bc7fd0&referrer=http%3A%2F%2Fprebid.org%3A9999%2Fgpt.html', - 'responseTimestamp': 1462919239342, - 'requestTimestamp': 1462919238919, - 'bidder': 'appnexus', - 'adUnitCode': '/19968336/header-bid-tag1', - 'timeToRespond': 423, - 'pbLg': '5.00', - 'pbMg': '10.00', - 'pbHg': '10.00', - 'pbAg': '10.00', - 'size': '728x90', - 'alwaysUseBid': true, - 'adserverTargeting': { - 'hb_bidder': 'appnexus', - 'hb_adid': '24bd938435ec3fc', - 'hb_pb': '10.00', - 'hb_size': '728x90', - 'foobar': '728x90' - } - }, bidfactory.createBid(2)); - - var adUnits = [{ - code: '/19968336/header-bid-tag1', - bids: [{ - bidder: 'appnexus', - params: { placementId: '123' } - }] - }]; - $$PREBID_GLOBAL$$.adUnits = adUnits; - - const adUnitCode = '/19968336/header-bid-tag1'; - $$PREBID_GLOBAL$$.addBidResponse(adUnitCode, bid); - assert.equal(spyClearAuction.callCount, 1, 'AUCTION_END event emitted more than once'); + let auctionManagerStub; + beforeEach(() => { + auctionManagerStub = sinon.stub(auctionManager, 'createAuction', function() { + return auction; + }); + }); - clock1.restore(); - resetAuction(); + afterEach(() => { + auctionManager.createAuction.restore(); }); }); @@ -1566,126 +1462,18 @@ describe('Unit: Prebid Module', function () { }); }); - describe('video adserverTag', () => { - var adserverTag = 'https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/19968336/header-bid-tag-0&impl=s&gdfp_req=1&env=vp&output=xml_vast2&unviewed_position_start=1&url=www.test.com'; - - var options = { - 'adserver': 'dfp', - 'code': '/19968336/header-bid-tag-0' - }; - + describe('setBidderSequence', () => { + let auctionManagerStub; beforeEach(() => { - resetAuction(); - $$PREBID_GLOBAL$$._bidsReceived = [ - { - 'bidderCode': 'appnexusAstDummyName', - 'width': 0, - 'height': 0, - 'statusMessage': 'Bid returned empty or error response', - 'adId': '233bcbee889d46d', - 'requestId': 123456, - 'responseTimestamp': 1462919238959, - 'requestTimestamp': 1462919238910, - 'cpm': 0, - 'bidder': 'appnexus', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'timeToRespond': 49, - 'pbLg': '0.00', - 'pbMg': '0.00', - 'pbHg': '0.00', - 'pbAg': '0.00', - 'pbDg': '0.00', - 'pbCg': '', - 'adserverTargeting': {} - }, - { - 'bidderCode': 'appnexusAst', - 'dealId': '1234', - 'width': 300, - 'height': 250, - 'statusMessage': 'Bid available', - 'adId': '233bcbee889d46d', - 'creative_id': 29681110, - 'cpm': 10, - 'vastUrl': 'http://www.simplevideoad.com/', - 'responseTimestamp': 1462919239340, - 'requestTimestamp': 1462919238919, - 'bidder': 'appnexus', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'timeToRespond': 421, - 'pbLg': '5.00', - 'pbMg': '10.00', - 'pbHg': '10.00', - 'pbAg': '10.00', - 'size': '300x250', - 'alwaysUseBid': true, - 'requestId': 123456, - 'adserverTargeting': { - 'hb_bidder': 'appnexus', - 'hb_adid': '233bcbee889d46d', - 'hb_pb': '10.00', - 'hb_size': '300x250', - 'foobar': '300x250', - 'hb_deal_appnexusAst': '1234' - } - } - ]; - }); - - afterEach(() => { - resetAuction(); - }); - - it('should log error when adserver is not dfp', () => { - var logErrorSpy = sinon.spy(utils, 'logError'); - var options = { - 'adserver': 'anyother', - 'code': '/19968336/header-bid-tag-0' - }; - var masterTagUrl = $$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag(adserverTag, options); - assert.ok(logErrorSpy.calledOnce, true); - utils.logError.restore(); - }); - - it('should return original adservertag if bids empty', () => { - $$PREBID_GLOBAL$$._bidsReceived = []; - var masterTagUrl = $$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag(adserverTag, options); - expect(masterTagUrl).to.equal(adserverTag); - }); - - it('should return original adservertag if there are no bids for the given placement code', () => { - // urls.js:parse returns port 443 for IE11, blank for other browsers - const ie11port = !!window.MSInputMethodContext && !!document.documentMode ? ':443' : ''; - const adserverTag = `https://pubads.g.doubleclick.net${ie11port}/gampad/ads?sz=640x480&iu=/19968336/header-bid-tag-0&impl=s&gdfp_req=1&env=vp&output=xml_vast2&unviewed_position_start=1&url=www.test.com`; - - const masterTagUrl = $$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag(adserverTag, { - 'adserver': 'dfp', - 'code': 'one-without-bids' + auctionManagerStub = sinon.stub(auctionManager, 'createAuction', function() { + return auction; }); - - expect(masterTagUrl).to.equal(adserverTag); }); - it('should log error when google\'s parameters are missing in adserverTag', () => { - var logErrorSpy = sinon.spy(utils, 'logError'); - var adserverTag = 'https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/19968336/header-bid-tag-0&impl=s&gdfp_req=1&env=vp&output=xml_vast2&unviewed_position_start=1&url=www.test.com'; - var masterTagUrl = $$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag(adserverTag, options); - assert.ok(logErrorSpy.calledOnce, true); - utils.logError.restore(); - }); - - it('should append parameters to the adserverTag', () => { - var masterTagUrl = $$PREBID_GLOBAL$$.buildMasterVideoTagFromAdserverTag(adserverTag, options); - var masterTagUrlParsed = urlParse(masterTagUrl, true); - var masterTagQuery = masterTagUrlParsed.query; - var expectedTargetingQuery = 'hb_bidder=appnexus&hb_adid=233bcbee889d46d&hb_pb=10.00&hb_size=300x250&foobar=300x250&hb_deal_appnexusAst=1234'; - - expect(masterTagQuery).to.have.property('cust_params').and.to.equal(expectedTargetingQuery); - expect(masterTagQuery).to.have.property('description_url').and.to.equal('http://www.simplevideoad.com/'); + afterEach(() => { + auctionManager.createAuction.restore(); }); - }); - describe('bidderSequence', () => { it('setting to `random` uses shuffled order of adUnits', () => { sinon.spy(utils, 'shuffle'); const requestObj = { @@ -1706,14 +1494,14 @@ describe('Unit: Prebid Module', function () { it('returns an array of winning bid objects for each adUnit', () => { const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids(); expect(highestCpmBids.length).to.equal(2); - expect(highestCpmBids[0]).to.deep.equal($$PREBID_GLOBAL$$._bidsReceived[1]); - expect(highestCpmBids[1]).to.deep.equal($$PREBID_GLOBAL$$._bidsReceived[2]); + expect(highestCpmBids[0]).to.deep.equal(auctionManager.getBidsReceived()[1]); + expect(highestCpmBids[1]).to.deep.equal(auctionManager.getBidsReceived()[2]); }); it('returns an array containing the highest bid object for the given adUnitCode', () => { const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/19968336/header-bid-tag-0'); expect(highestCpmBids.length).to.equal(1); - expect(highestCpmBids[0]).to.deep.equal($$PREBID_GLOBAL$$._bidsReceived[1]); + expect(highestCpmBids[0]).to.deep.equal(auctionManager.getBidsReceived()[1]); }); it('returns an empty array when the given adUnit is not found', () => { @@ -1722,8 +1510,10 @@ describe('Unit: Prebid Module', function () { }); it('returns an empty array when the given adUnit has no bids', () => { - $$PREBID_GLOBAL$$._bidsReceived = [$$PREBID_GLOBAL$$._bidsReceived[0]]; - $$PREBID_GLOBAL$$._bidsReceived[0].cpm = 0; + let _bidsReceived = getBidResponses()[0]; + _bidsReceived.cpm = 0; + auction.getBidsReceived = function() { return _bidsReceived }; + const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/19968336/header-bid-tag-0'); expect(highestCpmBids.length).to.equal(0); resetAuction(); @@ -1731,18 +1521,30 @@ describe('Unit: Prebid Module', function () { }); describe('setTargetingForAst', () => { + let targeting; + let auctionManagerInstance; + beforeEach(() => { resetAuction(); + auctionManagerInstance = newAuctionManager(); + sinon.stub(auctionManagerInstance, 'getBidsReceived', function() { + return [getBidResponses()[1]]; + }); + sinon.stub(auctionManagerInstance, 'getAdUnitCodes', function() { + return ['/19968336/header-bid-tag-0']; + }); + targeting = newTargeting(auctionManagerInstance); }); afterEach(() => { + auctionManagerInstance.getBidsReceived.restore(); + auctionManagerInstance.getAdUnitCodes.restore(); resetAuction(); }); it('should set targeting for appnexus apntag object', () => { + const bids = auctionManagerInstance.getBidsReceived(); const adUnitCode = '/19968336/header-bid-tag-0'; - const bidder = 'appnexus'; - const bids = $$PREBID_GLOBAL$$._bidsReceived.filter(bid => (bid.adUnitCode === adUnitCode && bid.bidderCode === bidder)); var expectedAdserverTargeting = bids[0].adserverTargeting; var newAdserverTargeting = {}; @@ -1751,14 +1553,14 @@ describe('Unit: Prebid Module', function () { newAdserverTargeting[nkey] = expectedAdserverTargeting[key]; } - $$PREBID_GLOBAL$$.setTargetingForAst(); + targeting.setTargetingForAst(); expect(newAdserverTargeting).to.deep.equal(window.apntag.tags[adUnitCode].keywords); }); it('should not find hb_adid key in lowercase for all bidders', () => { const adUnitCode = '/19968336/header-bid-tag-0'; $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: true }); - $$PREBID_GLOBAL$$.setTargetingForAst(); + targeting.setTargetingForAst(); const keywords = Object.keys(window.apntag.tags[adUnitCode].keywords).filter(keyword => (keyword.substring(0, 'hb_adid'.length) === 'hb_adid')); expect(keywords.length).to.equal(0); }); @@ -1797,42 +1599,4 @@ describe('Unit: Prebid Module', function () { assert.equal($$PREBID_GLOBAL$$.que.push, $$PREBID_GLOBAL$$.cmd.push); }); }); - - describe('setS2SConfig', () => { - let logErrorSpy; - - beforeEach(() => { - logErrorSpy = sinon.spy(utils, 'logError'); - }); - - afterEach(() => { - utils.logError.restore(); - }); - - it('should log error when accountId is missing', () => { - const options = { - enabled: true, - bidders: ['appnexus'], - timeout: 1000, - adapter: 'prebidServer', - endpoint: 'https://prebid.adnxs.com/pbs/v1/auction' - }; - - $$PREBID_GLOBAL$$.setConfig({ s2sConfig: {options} }); - assert.ok(logErrorSpy.calledOnce, true); - }); - - it('should log error when bidders is missing', () => { - const options = { - accountId: '1', - enabled: true, - timeout: 1000, - adapter: 's2s', - endpoint: 'https://prebid.adnxs.com/pbs/v1/auction' - }; - - $$PREBID_GLOBAL$$.setConfig({ s2sConfig: {options} }); - assert.ok(logErrorSpy.calledOnce, true); - }); - }); }); diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index c2f664e19f0..9f7c57ccb81 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -100,7 +100,7 @@ describe('Utils', function () { var obj = getAdServerTargeting(); var output = utils.transformAdServerTargetingObj(obj[Object.keys(obj)[0]]); - var expected = 'foobar=300x250&hb_size=300x250&hb_pb=10.00&hb_adid=233bcbee889d46d&hb_bidder=appnexus&hb_size_triplelift=0x0&hb_pb_triplelift=10.00&hb_adid_triplelift=222bb26f9e8bd&hb_bidder_triplelift=triplelift&hb_size_appnexus=300x250&hb_pb_appnexus=10.00&hb_adid_appnexus=233bcbee889d46d&hb_bidder_appnexus=appnexus&hb_size_pagescience=300x250&hb_pb_pagescience=10.00&hb_adid_pagescience=25bedd4813632d7&hb_bidder_pagescienc=pagescience&hb_size_brightcom=300x250&hb_pb_brightcom=10.00&hb_adid_brightcom=26e0795ab963896&hb_bidder_brightcom=brightcom&hb_size_brealtime=300x250&hb_pb_brealtime=10.00&hb_adid_brealtime=275bd666f5a5a5d&hb_bidder_brealtime=brealtime&hb_size_pubmatic=300x250&hb_pb_pubmatic=10.00&hb_adid_pubmatic=28f4039c636b6a7&hb_bidder_pubmatic=pubmatic&hb_size_rubicon=300x600&hb_pb_rubicon=10.00&hb_adid_rubicon=29019e2ab586a5a&hb_bidder_rubicon=rubicon'; + var expected = 'foobar=0x0%2C300x250%2C300x600&hb_size=300x250&hb_pb=10.00&hb_adid=233bcbee889d46d&hb_bidder=appnexus&hb_size_triplelift=0x0&hb_pb_triplelift=10.00&hb_adid_triplelift=222bb26f9e8bd&hb_bidder_triplelift=triplelift&hb_size_appnexus=300x250&hb_pb_appnexus=10.00&hb_adid_appnexus=233bcbee889d46d&hb_bidder_appnexus=appnexus&hb_size_pagescience=300x250&hb_pb_pagescience=10.00&hb_adid_pagescience=25bedd4813632d7&hb_bidder_pagescienc=pagescience&hb_size_brightcom=300x250&hb_pb_brightcom=10.00&hb_adid_brightcom=26e0795ab963896&hb_bidder_brightcom=brightcom&hb_size_brealtime=300x250&hb_pb_brealtime=10.00&hb_adid_brealtime=275bd666f5a5a5d&hb_bidder_brealtime=brealtime&hb_size_pubmatic=300x250&hb_pb_pubmatic=10.00&hb_adid_pubmatic=28f4039c636b6a7&hb_bidder_pubmatic=pubmatic&hb_size_rubicon=300x600&hb_pb_rubicon=10.00&hb_adid_rubicon=29019e2ab586a5a&hb_bidder_rubicon=rubicon'; assert.equal(output, expected); }); diff --git a/test/spec/videoCache_spec.js b/test/spec/videoCache_spec.js index e9af314218e..ab52b3be145 100644 --- a/test/spec/videoCache_spec.js +++ b/test/spec/videoCache_spec.js @@ -1,6 +1,7 @@ import 'mocha'; import chai from 'chai'; import { getCacheUrl, store } from 'src/videoCache'; +import { config } from 'src/config'; const should = chai.should(); @@ -48,9 +49,17 @@ describe('The video cache', () => { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = (request) => requests.push(request); + config.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }) }); - afterEach(() => xhr.restore()); + afterEach(() => { + xhr.restore(); + config.resetConfig(); + }); it('should execute the callback with a successful result when store() is called', () => { const uuid = 'c488b101-af3e-4a99-b538-00423e5a3371'; @@ -128,6 +137,18 @@ describe('The video cache', () => { }); describe('The getCache function', () => { + beforeEach(() => { + config.setConfig({ + cache: { + url: 'https://prebid.adnxs.com/pbc/v1/cache' + } + }) + }); + + afterEach(() => { + config.resetConfig(); + }); + it('should return the expected URL', () => { const uuid = 'c488b101-af3e-4a99-b538-00423e5a3371'; const url = getCacheUrl(uuid); diff --git a/test/spec/video_spec.js b/test/spec/video_spec.js index 512b56c334f..5ad9b662e7f 100644 --- a/test/spec/video_spec.js +++ b/test/spec/video_spec.js @@ -1,82 +1,89 @@ import { isValidVideoBid } from 'src/video'; -import { newConfig } from 'src/config'; -import * as utils from 'src/utils'; describe('video.js', () => { - afterEach(() => { - utils.getBidRequest.restore(); - }); - it('validates valid instream bids', () => { - sinon.stub(utils, 'getBidRequest', () => ({ - bidder: 'appnexusAst', - mediaTypes: { - video: { context: 'instream' }, - }, - })); - - const valid = isValidVideoBid({ + const bid = { + adId: '123abc', vastUrl: 'http://www.example.com/vastUrl' - }); - + }; + const bidRequests = [{ + bids: [{ + bidId: '123abc', + bidder: 'appnexus', + mediaTypes: { + video: { context: 'instream' } + } + }] + }]; + const valid = isValidVideoBid(bid, bidRequests); expect(valid).to.be(true); }); it('catches invalid instream bids', () => { - sinon.stub(utils, 'getBidRequest', () => ({ - bidder: 'appnexusAst', - mediaTypes: { - video: { context: 'instream' }, - }, - })); - - const valid = isValidVideoBid({}); - + const bid = { + adId: '123abc' + }; + const bidRequests = [{ + bids: [{ + bidId: '123abc', + bidder: 'appnexus', + mediaTypes: { + video: { context: 'instream' } + } + }] + }]; + const valid = isValidVideoBid(bid, bidRequests); expect(valid).to.be(false); }); it('catches invalid bids when prebid-cache is disabled', () => { - sinon.stub(utils, 'getBidRequest', () => ({ - bidder: 'vastOnlyVideoBidder', - mediaTypes: { video: {} }, - })); + const bidRequests = [{ + bids: [{ + bidder: 'vastOnlyVideoBidder', + mediaTypes: { video: {} }, + }] + }]; - const config = newConfig(); - config.setConfig({ usePrebidCache: false }); - - const valid = isValidVideoBid({ vastXml: 'vast' }); + const valid = isValidVideoBid({ vastXml: 'vast' }, bidRequests); expect(valid).to.be(false); }); it('validates valid outstream bids', () => { - sinon.stub(utils, 'getBidRequest', () => ({ - bidder: 'appnexusAst', - mediaTypes: { - video: { context: 'outstream' }, - }, - })); - - const valid = isValidVideoBid({ + const bid = { + adId: '123abc', renderer: { url: 'render.url', render: () => true, } - }); - + }; + const bidRequests = [{ + bids: [{ + bidId: '123abc', + bidder: 'appnexus', + mediaTypes: { + video: { context: 'outstream' } + } + }] + }]; + const valid = isValidVideoBid(bid, bidRequests); expect(valid).to.be(true); }); it('catches invalid outstream bids', () => { - sinon.stub(utils, 'getBidRequest', () => ({ - bidder: 'appnexusAst', - mediaTypes: { - video: { context: 'outstream' }, - }, - })); - - const valid = isValidVideoBid({}); - + const bid = { + adId: '123abc' + }; + const bidRequests = [{ + bids: [{ + bidId: '123abc', + bidder: 'appnexus', + mediaTypes: { + video: { context: 'outstream' } + } + }] + }]; + const valid = isValidVideoBid(bid, bidRequests); expect(valid).to.be(false); }); });