diff --git a/src/adapters/aardvark.js b/src/adapters/aardvark.js index 69c8e61417c..b89a8266ddd 100644 --- a/src/adapters/aardvark.js +++ b/src/adapters/aardvark.js @@ -1,104 +1,144 @@ -var utils = require('../utils.js'); -var bidfactory = require('../bidfactory.js'); -var bidmanager = require('../bidmanager.js'); -var adloader = require('../adloader'); - - -/** +/* * 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 AardvarkAdapter = function AardvarkAdapter() { - - function _callBids(params) { - var rtkBids = params.bids || []; - - _requestBids(rtkBids); - } - - function _requestBids(bidReqs) { - let ref; - try { - ref = window.top.location.host; - } - catch (err) { - ref = "thor.rtk.io"; - - } - var ai = ""; - var shortcodes = []; - - //build bid URL for RTK - utils._each(bidReqs, function (bid) { - ai = utils.getBidIdParameter('ai', bid.params); - var sc = utils.getBidIdParameter('sc', bid.params); - shortcodes.push(sc); - }); - - var scURL = ""; - - if (shortcodes.length > 1) { - scURL = shortcodes.join("_"); - } else { - scURL = shortcodes[0]; - } - - var scriptUrl = '//thor.rtk.io/' + ai + "/" + scURL + "/aardvark/?jsonp=window.$$PREBID_GLOBAL$$.aardvarkResponse&rtkreferer=" + ref; - adloader.loadScript(scriptUrl); - } - - //expose the callback to the global object: - window.$$PREBID_GLOBAL$$.aardvarkResponse = function (rtkResponseObj) { - - //Get all initial Aardvark Bid Objects - var bidsObj = $$PREBID_GLOBAL$$._bidsRequested.filter(function (bidder) { - return bidder.bidderCode === 'aardvark'; - })[0]; - - var returnedBidIDs = {}; - - if (rtkResponseObj.length > 0) { - rtkResponseObj.forEach(function (bid) { - - if (!bid.error) { - var currentBid = bidsObj.bids.filter(function (r) { - return r.params.sc === bid.id; - })[0]; - if (currentBid) { - var bidResponse = bidfactory.createBid(1, currentBid); - bidResponse.bidderCode = "aardvark"; - bidResponse.cpm = bid.cpm; - bidResponse.ad = bid.adm; - bidResponse.ad += utils.createTrackPixelHtml(decodeURIComponent(bid.nurl)); - bidResponse.width = currentBid.sizes[0][0]; - bidResponse.height = currentBid.sizes[0][1]; - returnedBidIDs[bid.id] = currentBid.placementCode; - bidmanager.addBidResponse(currentBid.placementCode, bidResponse); +var utils = require('../utils.js'); +var bidfactory = require('../bidfactory.js'); +var bidmanager = require('../bidmanager.js'); +var adloader = require('../adloader.js'); +var adapter = require('./adapter.js'); +var constants = require('../constants.json'); + +var AARDVARK_CALLBACK_NAME = 'aardvarkResponse', + AARDVARK_REQUESTS_MAP = 'aardvarkRequests', + AARDVARK_BIDDER_CODE = 'aardvark', + DEFAULT_REFERRER = 'thor.rtk.io', + DEFAULT_ENDPOINT = 'thor.rtk.io', + + endpoint = DEFAULT_ENDPOINT, + + requestBids = function(bidderCode, callbackName, bidReqs) { + var ref = utils.getTopWindowLocation(), + ai = '', + scs = [], + 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('')); + }, + + + + registerBidResponse = function(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; + }, + + + + registerAardvarkCallback = function(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); + } } + }; + }, + + + + AardvarkAdapter = function() { + var baseAdapter = adapter.createNew(AARDVARK_BIDDER_CODE); + + $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP] = $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP] || {}; + + baseAdapter.callBids = function (params) { + var bidderCode = baseAdapter.getBidderCode(), + callbackName = AARDVARK_CALLBACK_NAME; - } + if (bidderCode !== AARDVARK_BIDDER_CODE) + callbackName = [AARDVARK_CALLBACK_NAME, bidderCode].join('_'); - }); + $$PREBID_GLOBAL$$[AARDVARK_REQUESTS_MAP][bidderCode] = {}; - } + registerAardvarkCallback(bidderCode, callbackName); - //All bids are back - lets add a bid response for anything that did not receive a bid. - let difference = bidsObj.bids.filter(x => Object.keys(returnedBidIDs).indexOf(x.params.sc) === -1); + return requestBids(bidderCode, callbackName, params.bids || []); + }; - difference.forEach(function (bidRequest) { - var bidResponse = bidfactory.createBid(2, bidRequest); - bidResponse.bidderCode = "aardvark"; - bidmanager.addBidResponse(bidRequest.placementCode, bidResponse); - }); + return { + callBids: baseAdapter.callBids, + setBidderCode: baseAdapter.setBidderCode, + createNew: exports.createNew + }; + }; - }; // aardvarkResponse - return { - callBids: _callBids - }; +exports.createNew = function() { + return new AardvarkAdapter(); }; -module.exports = AardvarkAdapter; +module.exports = AardvarkAdapter; \ No newline at end of file diff --git a/test/spec/adapters/aardvark_spec.js b/test/spec/adapters/aardvark_spec.js index 8ef7051fc14..4d94d5c7cc3 100644 --- a/test/spec/adapters/aardvark_spec.js +++ b/test/spec/adapters/aardvark_spec.js @@ -1,124 +1,171 @@ -import {expect} from 'chai'; -import Adapter from '../../../src/adapters/aardvark'; -import bidManager from '../../../src/bidmanager'; -import adLoader from '../../../src/adloader'; +describe('aardvark adapter tests', function () { + const expect = require('chai').expect; + const adapter = require('src/adapters/aardvark'); + const bidmanager = require('src/bidmanager'); + const adloader = require('src/adloader'); + const constants = require('src/constants.json'); -describe('aardvark adapter', () => { - - let bidsRequestedOriginal; - let adapter; - let sandbox; + var aardvark, + sandbox, + bidsRequestedOriginal; const bidderRequest = { - bidderCode: 'aardvark', - bids: [ - { - bidId: 'bidId1', - bidder: 'aardvark', - placementCode: 'foo', - sizes: [[728, 90]], - params: { - ai: 'XBC1', - sc: 'AAAA' - } - }, - { - bidId: 'bidId2', - bidder: 'aardvark', - placementCode: 'bar', - sizes: [[300, 600]], - params: { - ai: 'XBC1', - sc: 'BBBB' - } - } - ] - }; + 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' + } + } + ] + }, + - beforeEach(() => { - bidsRequestedOriginal = pbjs._bidsRequested; - pbjs._bidsRequested = []; - adapter = new Adapter(); + // 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(); - pbjs._bidsRequested = bidsRequestedOriginal; + $$PREBID_GLOBAL$$._bidsRequested = bidsRequestedOriginal; }); - describe('callBids', () => { + describe('callBids', () => { beforeEach(() => { - sandbox.stub(adLoader, 'loadScript'); - adapter.callBids(bidderRequest); + sandbox.stub(adloader, 'loadScript'); + aardvark.callBids(bidderRequest); }); - it('should load script', () => { - sinon.assert.calledOnce(adLoader.loadScript); - - let expected = '//thor.rtk.io/XBC1/AAAA_BBBB/aardvark/?jsonp=window.pbjs.aardvarkResponse&rtkreferer=localhost:9876'; - expect(adLoader.loadScript.firstCall.args[0]).to.eql(expected); + 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', () => { + describe('aardvarkResponse', () => { it('should exist and be a function', () => { - expect(pbjs.aardvarkResponse).to.exist.and.to.be.a('function'); + expect($$PREBID_GLOBAL$$.aardvarkResponse).to.exist.and.to.be.a('function'); }); }); - describe('add bids to the manager', () => { + + describe('add empty bids if no bid returned', () => { let firstBid; let secondBid; beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - - pbjs._bidsRequested.push(bidderRequest); - - // respond - let bidderReponse = [ - { - "adm": "", - "cpm": 0.39440, - "ex": "", - "height": "90", - "id": "AAAA", - "nurl": "", - "width": "728" - }, - { - "adm": "", - "cpm": 0.03485, - "ex": "", - "height": "600", - "id": "BBBB", - "nurl": "", - "width": "300" - } - ]; - pbjs.aardvarkResponse(bidderReponse); - - firstBid = bidManager.addBidResponse.firstCall.args[1]; - secondBid = bidManager.addBidResponse.secondCall.args[1]; + 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); + 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 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', () => { @@ -126,14 +173,12 @@ describe('aardvark adapter', () => { 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 pass the correct placement code as first param', () => { + let firstPlacementCode = bidmanager.addBidResponse.firstCall.args[0]; + let secondPlacementCode = bidmanager.addBidResponse.secondCall.args[0]; - 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); + expect(firstPlacementCode).to.eql('foo'); + expect(secondPlacementCode).to.eql('bar'); }); it('should add the bidder code to the bid object', () => { @@ -141,44 +186,34 @@ describe('aardvark adapter', () => { 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); - }); }); - describe('add empty bids if no bid returned', () => { + describe('add bids to the manager', () => { let firstBid; let secondBid; beforeEach(() => { - sandbox.stub(bidManager, 'addBidResponse'); - - pbjs._bidsRequested.push(bidderRequest); + sandbox.stub(bidmanager, 'addBidResponse'); - // respond - let bidderReponse = []; - pbjs.aardvarkResponse(bidderReponse); + $$PREBID_GLOBAL$$._bidsRequested.push(bidderRequest); + aardvark.callBids(bidderRequest); - firstBid = bidManager.addBidResponse.firstCall.args[1]; - secondBid = bidManager.addBidResponse.secondCall.args[1]; + $$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); + sinon.assert.calledTwice(bidmanager.addBidResponse); }); - 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 include bid request bidId as the adId', () => { @@ -186,12 +221,14 @@ describe('aardvark adapter', () => { 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]; + it('should have a good statusCode', () => { + expect(firstBid.getStatusCode()).to.eql(constants.STATUS.GOOD); + expect(secondBid.getStatusCode()).to.eql(constants.STATUS.GOOD); + }); - expect(firstPlacementCode).to.eql('foo'); - expect(secondPlacementCode).to.eql('bar'); + 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', () => { @@ -199,5 +236,21 @@ describe('aardvark adapter', () => { 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); + }); }); + + + + }); +