diff --git a/src/adapters/aol.js b/src/adapters/aol.js
index 199cebee712..f02e58366a8 100644
--- a/src/adapters/aol.js
+++ b/src/adapters/aol.js
@@ -1,183 +1,140 @@
-var utils = require('../utils.js');
-var bidfactory = require('../bidfactory.js');
-var bidmanager = require('../bidmanager.js');
-var adloader = require('../adloader');
-
-var AolAdapter = function AolAdapter() {
-
- // constants
- var ADTECH_URI = 'https://secure-ads.pictela.net/rm/marketplace/pubtaglib/0_4_0/pubtaglib_0_4_0.js';
- var ADTECH_BIDDER_NAME = 'aol';
- var ADTECH_PUBAPI_CONFIG = {
- pixelsDivId: 'pixelsDiv',
- defaultKey: 'aolBid',
- roundingConfig: [
- {
- from: 0,
- to: 999,
- roundFunction: 'tenCentsRound'
- }, {
- from: 1000,
- to: -1,
- roundValue: 1000
- }
- ],
- pubApiOK: _addBid,
- pubApiER: _addErrorBid
+const utils = require('../utils.js');
+const ajax = require('../ajax.js').ajax;
+const bidfactory = require('../bidfactory.js');
+const bidmanager = require('../bidmanager.js');
+
+const AolAdapter = function AolAdapter() {
+
+ const pubapiTemplate = template`${'protocol'}://${'host'}/pubapi/3.0/${'network'}/${'placement'}/${'pageid'}/${'sizeid'}/ADTECH;v=2;cmd=bid;cors=yes;alias=${'alias'}${'bidfloor'};misc=${'misc'}`;
+ const BIDDER_CODE = 'aol';
+ const SERVER_MAP = {
+ us: 'adserver-us.adtech.advertising.com',
+ eu: 'adserver-eu.adtech.advertising.com',
+ as: 'adserver-as.adtech.advertising.com'
};
- var bids;
- var bidsMap = {};
- var d = window.document;
- var h = d.getElementsByTagName('HEAD')[0];
- var dummyUnitIdCount = 0;
-
- /**
- * @private create a div that we'll use as the
- * location for the AOL unit; AOL will document.write
- * if the div is not present in the document.
- * @param {String} id to identify the div
- * @return {String} the id used with the div
- */
- function _dummyUnit(id) {
- var div = d.createElement('DIV');
-
- if (!id || !id.length) {
- id = 'ad-placeholder-' + (++dummyUnitIdCount);
- }
-
- div.id = id + '-head-unit';
- h.appendChild(div);
- return div.id;
+ function template(strings, ...keys) {
+ return function(...values) {
+ let dict = values[values.length - 1] || {};
+ let result = [strings[0]];
+ keys.forEach(function(key, i) {
+ let value = Number.isInteger(key) ? values[key] : dict[key];
+ result.push(value, strings[i + 1]);
+ });
+ return result.join('');
+ };
}
- /**
- * @private Add a succesful bid response for aol
- * @param {ADTECHResponse} response the response for the bid
- * @param {ADTECHContext} context the context passed from aol
- */
- function _addBid(response, context) {
- var bid = bidsMap[context.alias];
- var cpm;
-
- if (!bid) {
- utils.logError('mismatched bid: ' + context.placement, ADTECH_BIDDER_NAME, context);
- return;
- }
+ function _buildPubapiUrl(bid) {
+ const params = bid.params;
+ const serverParam = params.server;
+ let regionParam = params.region || 'us';
+ let server;
- cpm = response.getCPM();
- if (cpm === null || isNaN(cpm)) {
- return _addErrorBid(response, context);
+ if (!SERVER_MAP.hasOwnProperty(regionParam)) {
+ console.warn(`Unknown region '${regionParam}' for AOL bidder.`);
+ regionParam = 'us'; // Default region.
}
- // clean up--we no longer need to store the bid
- delete bidsMap[context.alias];
-
- var bidResponse = bidfactory.createBid(1);
- var ad = response.getCreative();
- if (typeof response.getPixels() !== 'undefined') {
- ad += response.getPixels();
+ if (serverParam) {
+ server = serverParam;
+ } else {
+ server = SERVER_MAP[regionParam];
}
- bidResponse.bidderCode = ADTECH_BIDDER_NAME;
- bidResponse.ad = ad;
- bidResponse.cpm = cpm;
- bidResponse.width = response.getAdWidth();
- bidResponse.height = response.getAdHeight();
- bidResponse.creativeId = response.getCreativeId();
- // add it to the bid manager
+ // Set region param, used by AOL analytics.
+ params.region = regionParam;
+
+ return pubapiTemplate({
+ protocol: (document.location.protocol === 'https:') ? 'https' : 'http',
+ host: server,
+ network: params.network,
+ placement: parseInt(params.placement),
+ pageid: params.pageId || 0,
+ sizeid: params.sizeId || 0,
+ alias: params.alias || utils.getUniqueIdentifierStr(),
+ bidfloor: (typeof params.bidFloor !== 'undefined') ?
+ `;bidfloor=${params.bidFloor.toString()}` : '',
+ misc: new Date().getTime() // cache busting
+ });
+ }
+
+ function _addErrorBidResponse(bid, response = {}) {
+ const bidResponse = bidfactory.createBid(2, bid);
+ bidResponse.bidderCode = BIDDER_CODE;
+ bidResponse.reason = response.nbr;
+ bidResponse.raw = response;
bidmanager.addBidResponse(bid.placementCode, bidResponse);
}
- /**
- * @private Add an error bid response for aol
- * @param {ADTECHResponse} response the response for the bid
- * @param {ADTECHContext} context the context passed from aol
- */
- function _addErrorBid(response, context) {
- var bid = bidsMap[context.alias];
+ function _addBidResponse(bid, response) {
+ let bidData;
- if (!bid) {
- utils.logError('mismatched bid: ' + context.placement, ADTECH_BIDDER_NAME, context);
+ try {
+ bidData = response.seatbid[0].bid[0];
+ } catch (e) {
+ _addErrorBidResponse(bid, response);
return;
}
- // clean up--we no longer need to store the bid
- delete bidsMap[context.alias];
+ let cpm;
- var bidResponse = bidfactory.createBid(2);
- bidResponse.bidderCode = ADTECH_BIDDER_NAME;
- bidResponse.reason = response.getNbr();
- bidResponse.raw = response.getResponse();
- bidmanager.addBidResponse(bid.placementCode, bidResponse);
- }
+ if (bidData.ext && bidData.ext.encp) {
+ cpm = bidData.ext.encp;
+ } else {
+ cpm = bidData.price;
- /**
- * @private map a prebid bidrequest to an ADTECH/aol bid request
- * @param {Bid} bid the bid request
- * @return {Object} the bid request, formatted for the ADTECH/DAC api
- */
- function _mapUnit(bid) {
- var alias = bid.params.alias || utils.getUniqueIdentifierStr();
-
- // save the bid
- bidsMap[alias] = bid;
-
- return {
- adContainerId: _dummyUnit(bid.params.adContainerId),
- server: bid.params.server, // By default, DAC.js will use the US region endpoint (adserver.adtechus.com)
- sizeid: bid.params.sizeId || 0,
- pageid: bid.params.pageId,
- secure: document.location.protocol === 'https:',
- serviceType: 'pubapi',
- performScreenDetection: false,
- alias: alias,
- network: bid.params.network,
- placement: parseInt(bid.params.placement),
- gpt: {
- adUnitPath: bid.params.adUnitPath || bid.placementCode,
- size: bid.params.size || (bid.sizes || [])[0]
- },
- params: {
- cors: 'yes',
- cmd: 'bid',
- bidfloor: (typeof bid.params.bidFloor !== "undefined") ? bid.params.bidFloor.toString() : ''
- },
- pubApiConfig: ADTECH_PUBAPI_CONFIG,
- placementCode: bid.placementCode
- };
- }
+ if (cpm === null || isNaN(cpm)) {
+ utils.logError('Invalid price in bid response', BIDDER_CODE, bid);
+ _addErrorBidResponse(bid, response);
+ return;
+ }
+ }
- /**
- * @private once ADTECH is loaded, request bids by
- * calling ADTECH.loadAd
- */
- function _reqBids() {
- if (!window.ADTECH) {
- utils.logError('window.ADTECH is not present!', ADTECH_BIDDER_NAME);
- return;
+ let ad = bidData.adm;
+ if (bidData.ext && bidData.ext.pixels) {
+ ad += bidData.ext.pixels;
}
- // get the bids
- utils._each(bids, function (bid) {
- var bidreq = _mapUnit(bid);
- window.ADTECH.loadAd(bidreq);
- });
+ const bidResponse = bidfactory.createBid(1, bid);
+ bidResponse.bidderCode = BIDDER_CODE;
+ bidResponse.ad = ad;
+ bidResponse.cpm = cpm;
+ bidResponse.width = bidData.w;
+ bidResponse.height = bidData.h;
+ bidResponse.creativeId = bidData.crid;
+ bidResponse.pubapiId = response.id;
+ bidResponse.currencyCode = response.cur;
+ if (bidData.dealid) {
+ bidResponse.dealId = bidData.dealid;
+ }
+
+ bidmanager.addBidResponse(bid.placementCode, bidResponse);
}
- /**
- * @public call the bids
- * this requests the specified bids
- * from aol marketplace
- * @param {Object} params
- * @param {Array} params.bids the bids to be requested
- */
function _callBids(params) {
- window.bidRequestConfig = window.bidRequestConfig || {};
- window.dacBidRequestConfigs = window.dacBidRequestConfigs || {};
- bids = params.bids;
- if (!bids || !bids.length) return;
- adloader.loadScript(ADTECH_URI, _reqBids, true);
+ utils._each(params.bids, bid => {
+ const pubapiUrl = _buildPubapiUrl(bid);
+
+ ajax(pubapiUrl, response => {
+ if (!response && response.length <= 0) {
+ utils.logError('Empty bid response', BIDDER_CODE, bid);
+ _addErrorBidResponse(bid, response);
+ return;
+ }
+
+ try {
+ response = JSON.parse(response);
+ } catch (e) {
+ utils.logError('Invalid JSON in bid response', BIDDER_CODE, bid);
+ _addErrorBidResponse(bid, response);
+ return;
+ }
+
+ _addBidResponse(bid, response);
+
+ }, null, { withCredentials: true });
+ });
}
return {
diff --git a/src/polyfill.js b/src/polyfill.js
index ab21fb66683..467a09f7cba 100644
--- a/src/polyfill.js
+++ b/src/polyfill.js
@@ -56,3 +56,10 @@ if (!Array.prototype.includes) {
}
});
}
+
+// 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/test/spec/adapters/aol_spec.js b/test/spec/adapters/aol_spec.js
new file mode 100644
index 00000000000..8eb09af4496
--- /dev/null
+++ b/test/spec/adapters/aol_spec.js
@@ -0,0 +1,434 @@
+import {expect} from 'chai';
+import _ from 'lodash';
+import AolAdapter from 'src/adapters/aol';
+import bidmanager from 'src/bidmanager';
+
+const DEFAULT_BIDDER_REQUEST = {
+ bidderCode: 'aol',
+ requestId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6',
+ bidderRequestId: '7101db09af0db2',
+ start: new Date().getTime(),
+ bids: [{
+ bidder: 'aol',
+ bidId: '84ab500420319d',
+ bidderRequestId: '7101db09af0db2',
+ requestId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6',
+ placementCode: 'foo',
+ params: {
+ placement: 1234567,
+ network: '9599.1'
+ }
+ }]
+};
+const DEFAULT_PUBAPI_RESPONSE = {
+ "id": "245730051428950632",
+ "cur": "USD",
+ "seatbid": [{
+ "bid": [{
+ "id": 1,
+ "impid": "245730051428950632",
+ "price": 0.09,
+ "adm": "",
+ "crid": "0",
+ "h": 90,
+ "w": 728,
+ "ext": {"sizeid": 225}
+ }]
+ }]
+};
+
+describe('AolAdapter', () => {
+
+ let adapter;
+
+ beforeEach(() => adapter = new AolAdapter());
+
+ function createBidderRequest({bids, params} = {}) {
+ var bidderRequest = _.cloneDeep(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');
+ });
+
+ describe('bid request', () => {
+ let xhr;
+ let requests;
+
+ beforeEach(() => {
+ xhr = sinon.useFakeXMLHttpRequest();
+ requests = [];
+ xhr.onCreate = request => requests.push(request);
+ });
+
+ afterEach(() => xhr.restore());
+
+ it('requires parameters to be made', () => {
+ adapter.callBids({});
+ expect(requests).to.be.empty;
+ });
+
+ it('should hit the default pubapi endpoint', () => {
+ adapter.callBids(DEFAULT_BIDDER_REQUEST);
+ expect(requests[0].url).to.contain('adserver-us.adtech.advertising.com/pubapi/3.0/');
+ });
+
+ it('should hit endpoint based on the region config option', () => {
+ adapter.callBids(createBidderRequest({
+ params: {
+ placement: 1234567,
+ network: '9599.1',
+ region: 'eu'
+ }
+ }));
+ expect(requests[0].url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/');
+ });
+
+ it('should hit the default endpoint in case of unknown region config option', () => {
+ adapter.callBids(createBidderRequest({
+ params: {
+ placement: 1234567,
+ network: '9599.1',
+ region: 'an'
+ }
+ }));
+ expect(requests[0].url).to.contain('adserver-us.adtech.advertising.com/pubapi/3.0/');
+ });
+
+ it('should hit endpoint based on the server config option', () => {
+ adapter.callBids(createBidderRequest({
+ params: {
+ placement: 1234567,
+ network: '9599.1',
+ server: 'adserver-eu.adtech.advertising.com'
+ }
+ }));
+ expect(requests[0].url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/');
+ });
+
+ it('should be the pubapi bid request', () => {
+ adapter.callBids(DEFAULT_BIDDER_REQUEST);
+ expect(requests[0].url).to.contain('cmd=bid;');
+ });
+
+ it('should be the version 2 of pubapi', () => {
+ adapter.callBids(DEFAULT_BIDDER_REQUEST);
+ expect(requests[0].url).to.contain('v=2;');
+ });
+
+ it('should contain cache busting', () => {
+ adapter.callBids(DEFAULT_BIDDER_REQUEST);
+ expect(requests[0].url).to.match(/misc=\d+/);
+ });
+
+ it('should contain required params - placement & network', () => {
+ adapter.callBids(createBidderRequest({
+ params: {
+ placement: 1234567,
+ network: '9599.1'
+ }
+ }));
+ expect(requests[0].url).to.contain('/pubapi/3.0/9599.1/1234567/');
+ });
+
+ it('should contain pageId and sizeId of 0 if params are missing', () => {
+ adapter.callBids(createBidderRequest({
+ params: {
+ placement: 1234567,
+ network: '9599.1'
+ }
+ }));
+ expect(requests[0].url).to.contain('/pubapi/3.0/9599.1/1234567/0/0/ADTECH;');
+ });
+
+ it('should contain pageId optional param', () => {
+ adapter.callBids(createBidderRequest({
+ params: {
+ placement: 1234567,
+ network: '9599.1',
+ pageId: 12345
+ }
+ }));
+ expect(requests[0].url).to.contain('/pubapi/3.0/9599.1/1234567/12345/');
+ });
+
+ it('should contain sizeId optional param', () => {
+ adapter.callBids(createBidderRequest({
+ params: {
+ placement: 1234567,
+ network: '9599.1',
+ sizeId: 12345
+ }
+ }));
+ expect(requests[0].url).to.contain('/12345/ADTECH;');
+ });
+
+ it('should contain generated alias if alias param is missing', () => {
+ adapter.callBids(createBidderRequest({
+ params: {
+ placement: 1234567,
+ network: '9599.1'
+ }
+ }));
+ expect(requests[0].url).to.match(/alias=\w+?;/);
+ });
+
+ it('should contain alias optional param', () => {
+ adapter.callBids(createBidderRequest({
+ params: {
+ placement: 1234567,
+ network: '9599.1',
+ alias: 'desktop_articlepage_something_box_300_250'
+ }
+ }));
+ expect(requests[0].url).to.contain('alias=desktop_articlepage_something_box_300_250');
+ });
+
+ it('should not contain bidfloor if bidFloor param is missing', () => {
+ adapter.callBids(createBidderRequest({
+ params: {
+ placement: 1234567,
+ network: '9599.1'
+ }
+ }));
+ expect(requests[0].url).not.to.contain('bidfloor=');
+ });
+
+ it('should contain bidFloor optional param', () => {
+ adapter.callBids(createBidderRequest({
+ params: {
+ placement: 1234567,
+ network: '9599.1',
+ bidFloor: 0.80
+ }
+ }));
+ expect(requests[0].url).to.contain('bidfloor=0.8');
+ });
+
+ });
+
+ describe('bid response', () => {
+
+ let server;
+
+ beforeEach(() => {
+ server = sinon.fakeServer.create();
+ sinon.stub(bidmanager, 'addBidResponse');
+ });
+
+ afterEach(() => {
+ server.restore();
+ bidmanager.addBidResponse.restore();
+ });
+
+ it('should be added to bidmanager if returned from pubapi', () => {
+ server.respondWith(JSON.stringify(DEFAULT_PUBAPI_RESPONSE));
+ adapter.callBids(DEFAULT_BIDDER_REQUEST);
+ server.respond();
+ expect(bidmanager.addBidResponse.calledOnce).to.be.true;
+ });
+
+ it('should be added to bidmanager with correct bidderCode', () => {
+ server.respondWith(JSON.stringify(DEFAULT_PUBAPI_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', 'aol');
+ });
+
+ it('should have adId matching the bidId from related bid request', () => {
+ server.respondWith(JSON.stringify(DEFAULT_PUBAPI_RESPONSE));
+ adapter.callBids(DEFAULT_BIDDER_REQUEST);
+ server.respond();
+ expect(bidmanager.addBidResponse.calledOnce).to.be.true;
+ expect(bidmanager.addBidResponse.firstCall.args[1])
+ .to.have.property('adId', DEFAULT_BIDDER_REQUEST.bids[0].bidId);
+ });
+
+ it('should be added to bidmanager as invalid in case of empty response', () => {
+ server.respondWith('');
+ adapter.callBids(DEFAULT_BIDDER_REQUEST);
+ server.respond();
+ expect(bidmanager.addBidResponse.calledOnce).to.be.true;
+ expect(bidmanager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(2);
+ });
+
+ it('should be added to bidmanager as invalid in case of invalid JSON response', () => {
+ server.respondWith('{foo:{bar:{baz:');
+ adapter.callBids(DEFAULT_BIDDER_REQUEST);
+ server.respond();
+ expect(bidmanager.addBidResponse.calledOnce).to.be.true;
+ expect(bidmanager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(2);
+ });
+
+ it('should be added to bidmanager as invalid in case of no bid data', () => {
+ server.respondWith(JSON.stringify({
+ "id": "245730051428950632",
+ "cur": "USD",
+ "seatbid": []
+ }));
+ adapter.callBids(DEFAULT_BIDDER_REQUEST);
+ server.respond();
+ expect(bidmanager.addBidResponse.calledOnce).to.be.true;
+ expect(bidmanager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(2);
+ });
+
+ it('should have adId matching the bidId from bid request in case of no bid data', () => {
+ server.respondWith(JSON.stringify({
+ "id": "245730051428950632",
+ "cur": "USD",
+ "seatbid": []
+ }));
+ adapter.callBids(DEFAULT_BIDDER_REQUEST);
+ server.respond();
+ expect(bidmanager.addBidResponse.calledOnce).to.be.true;
+ expect(bidmanager.addBidResponse.firstCall.args[1])
+ .to.have.property('adId', DEFAULT_BIDDER_REQUEST.bids[0].bidId);
+ });
+
+ it('should be added to bidmanager as invalid in case of empty price', () => {
+ server.respondWith(JSON.stringify({
+ "id": "245730051428950632",
+ "cur": "USD",
+ "seatbid": [{
+ "bid": [{
+ "id": 1,
+ "impid": "245730051428950632",
+ "adm": "",
+ "crid": "0",
+ "h": 90,
+ "w": 728,
+ "ext": {"sizeid": 225}
+ }]
+ }]
+ }));
+ adapter.callBids(DEFAULT_BIDDER_REQUEST);
+ server.respond();
+ expect(bidmanager.addBidResponse.calledOnce).to.be.true;
+ expect(bidmanager.addBidResponse.firstCall.args[1].getStatusCode()).to.equal(2);
+ });
+
+ it('should be added to bidmanager with attributes from pubapi response', () => {
+ server.respondWith(JSON.stringify({
+ "id": "245730051428950632",
+ "cur": "USD",
+ "seatbid": [{
+ "bid": [{
+ "id": 1,
+ "impid": "245730051428950632",
+ "price": 0.09,
+ "adm": "",
+ "crid": "12345",
+ "h": 90,
+ "w": 728,
+ "ext": {"sizeid": 225}
+ }]
+ }]
+ }));
+ adapter.callBids(DEFAULT_BIDDER_REQUEST);
+ server.respond();
+ expect(bidmanager.addBidResponse.calledOnce).to.be.true;
+ var bidResponse = bidmanager.addBidResponse.firstCall.args[1];
+ expect(bidResponse.ad).to.equal("");
+ expect(bidResponse.cpm).to.equal(0.09);
+ expect(bidResponse.width).to.equal(728);
+ expect(bidResponse.height).to.equal(90);
+ expect(bidResponse.creativeId).to.equal('12345');
+ expect(bidResponse.pubapiId).to.equal('245730051428950632');
+ });
+
+ it('should be added to bidmanager including pixels from pubapi response', () => {
+ server.respondWith(JSON.stringify({
+ "id": "245730051428950632",
+ "cur": "USD",
+ "seatbid": [{
+ "bid": [{
+ "id": 1,
+ "impid": "245730051428950632",
+ "price": 0.09,
+ "adm": "",
+ "crid": "12345",
+ "h": 90,
+ "w": 728,
+ "ext": {
+ "sizeid": 225,
+ "pixels": ""
+ }
+ }]
+ }]
+ }));
+ adapter.callBids(DEFAULT_BIDDER_REQUEST);
+ server.respond();
+ expect(bidmanager.addBidResponse.calledOnce).to.be.true;
+ var bidResponse = bidmanager.addBidResponse.firstCall.args[1];
+ expect(bidResponse.ad).to.equal(
+ "" +
+ ""
+ );
+ });
+
+ it('should be added to bidmanager including dealid from pubapi response', () => {
+ server.respondWith(JSON.stringify({
+ "id": "245730051428950632",
+ "cur": "USD",
+ "seatbid": [{
+ "bid": [{
+ "id": 1,
+ "impid": "245730051428950632",
+ "dealid": "12345",
+ "price": 0.09,
+ "adm": "",
+ "crid": "12345",
+ "h": 90,
+ "w": 728,
+ "ext": {
+ "sizeid": 225
+ }
+ }]
+ }]
+ }));
+ adapter.callBids(DEFAULT_BIDDER_REQUEST);
+ server.respond();
+ expect(bidmanager.addBidResponse.calledOnce).to.be.true;
+ var bidResponse = bidmanager.addBidResponse.firstCall.args[1];
+ expect(bidResponse.dealId).to.equal('12345');
+ });
+
+ it('should be added to bidmanager including encrypted price from pubapi response', () => {
+ server.respondWith(JSON.stringify({
+ "id": "245730051428950632",
+ "cur": "USD",
+ "seatbid": [{
+ "bid": [{
+ "id": 1,
+ "impid": "245730051428950632",
+ "dealid": "12345",
+ "price": 0.09,
+ "adm": "",
+ "crid": "12345",
+ "h": 90,
+ "w": 728,
+ "ext": {
+ "sizeid": 225,
+ "encp": "a9334987"
+ }
+ }]
+ }]
+ }));
+ adapter.callBids(DEFAULT_BIDDER_REQUEST);
+ server.respond();
+ expect(bidmanager.addBidResponse.calledOnce).to.be.true;
+ var bidResponse = bidmanager.addBidResponse.firstCall.args[1];
+ expect(bidResponse.cpm).to.equal('a9334987');
+ });
+ });
+ });
+});