From 3da639ca943addc09431632d796de2ba2a17119e Mon Sep 17 00:00:00 2001 From: Daniel Lawrence Date: Tue, 13 Jun 2017 11:14:05 -0700 Subject: [PATCH 1/6] implemented AerServ adapter --- src/adapters/aerserv.js | 99 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/adapters/aerserv.js diff --git a/src/adapters/aerserv.js b/src/adapters/aerserv.js new file mode 100644 index 00000000000..75b4137ca0b --- /dev/null +++ b/src/adapters/aerserv.js @@ -0,0 +1,99 @@ +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'; + +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 BIDDER_CODE = 'aerserv'; + const REQUIRED_PARAMS = ['plc']; + const VIDEO_TARGETING = []; + + function _isResponseValid(bidRequest, response) { + return ((bidRequest.mediaType === 'video' && response.vastUrl) || (bidRequest.mediaType !== 'video' && response.adm)) && + response.cpm && response.cpm > 0; + } + + function _addBidResponse(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.descriptionUrl = response.vastUrl; + } else { + bid.ad = response.adm; + } + bidmanager.addBidResponse(bidRequest.placementCode, bid); + } else { + bidmanager.addBidResponse(bidRequest.placementCode, bidfactory.createBid(STATUS.NO_BID, bidRequest)); + } + } + + function _buildQueryParameters(bidRequest, requestParams) { + Object.keys(bidRequest.params).forEach(param => requestParams[param] = bidRequest.params[param]); + + if (bidRequest.params.video) { + Object.keys(bidRequest.params.video) + .filter(param => VIDEO_TARGETING.includes(param)) + .forEach(param => requestParams[param] = bidRequest.params.video[param]); + } + + return utils.parseQueryStringParameters(requestParams); + } + + function _callBids(params) { + let currentUrl = (window.parent !== window) ? document.referrer : window.location.href; + currentUrl = currentUrl && encodeURIComponent(currentUrl); + + let bids = params.bids || []; + bids.forEach(bidRequest => { + if (utils.hasValidBidRequest(bidRequest.params, REQUIRED_PARAMS, BIDDER_CODE)) { + let env = ENVIRONMENTS[bidRequest.params['env']] || ENVIRONMENTS['prod']; + let requestPath = bidRequest.mediaType === 'video' ? VIDEO_PATH : BANNER_PATH; + let requestParams = {url: currentUrl}; + let parameterStr = _buildQueryParameters(bidRequest, requestParams); + + let url = `//${env}${requestPath}${parameterStr}`; + utils.logMessage('sending request to: ' + url); + ajax(url, 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; + } + + _addBidResponse(bidRequest, response); + }, null, {withCredentials: true}); + } else { + bidmanager.addBidResponse(bidRequest.placementCode, bidfactory.createBid(STATUS.NO_BID, bidRequest)); + } + }); + } + + return { + callBids: _callBids + }; +}; + +module.exports = AerServAdapter; From bf629882b7238c0d8298d1177977614c9f71a2b9 Mon Sep 17 00:00:00 2001 From: Daniel Lawrence Date: Wed, 14 Jun 2017 09:54:14 -0700 Subject: [PATCH 2/6] added unit tests, slight refactor/formatting of adapter code, added to adapters json --- adapters.json | 6 + src/adapters/aerserv.js | 57 ++++----- test/spec/adapters/aerserv_spec.js | 197 +++++++++++++++++++++++++++++ 3 files changed, 230 insertions(+), 30 deletions(-) create mode 100644 test/spec/adapters/aerserv_spec.js diff --git a/adapters.json b/adapters.json index 48ca7cefc35..32c4f10da2a 100644 --- a/adapters.json +++ b/adapters.json @@ -69,6 +69,7 @@ "trion", "prebidServer", "adsupply", + "aerserv", { "appnexus": { "alias": "brealtime" @@ -154,5 +155,10 @@ "conversant": { "supportedMediaTypes": ["video"] } + }, + { + "aerserv": { + "supportedMediaTypes": ["video"] + } } ] diff --git a/src/adapters/aerserv.js b/src/adapters/aerserv.js index 75b4137ca0b..39cefeb2801 100644 --- a/src/adapters/aerserv.js +++ b/src/adapters/aerserv.js @@ -16,14 +16,13 @@ const AerServAdapter = function AerServAdapter() { const VIDEO_PATH = '/as/json/pbjsvast/v1?'; const BIDDER_CODE = 'aerserv'; const REQUIRED_PARAMS = ['plc']; - const VIDEO_TARGETING = []; function _isResponseValid(bidRequest, response) { return ((bidRequest.mediaType === 'video' && response.vastUrl) || (bidRequest.mediaType !== 'video' && response.adm)) && response.cpm && response.cpm > 0; } - function _addBidResponse(bidRequest, response) { + function _createBid(bidRequest, response) { if (_isResponseValid(bidRequest, response)) { let bid = bidfactory.createBid(1, bidRequest); bid.bidderCode = BIDDER_CODE; @@ -45,46 +44,44 @@ const AerServAdapter = function AerServAdapter() { function _buildQueryParameters(bidRequest, requestParams) { Object.keys(bidRequest.params).forEach(param => requestParams[param] = bidRequest.params[param]); - if (bidRequest.params.video) { - Object.keys(bidRequest.params.video) - .filter(param => VIDEO_TARGETING.includes(param)) - .forEach(param => requestParams[param] = bidRequest.params.video[param]); - } - return utils.parseQueryStringParameters(requestParams); } - function _callBids(params) { + 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 = params.bids || []; + let bids = bidRequests.bids || []; bids.forEach(bidRequest => { if (utils.hasValidBidRequest(bidRequest.params, REQUIRED_PARAMS, BIDDER_CODE)) { let env = ENVIRONMENTS[bidRequest.params['env']] || ENVIRONMENTS['prod']; let requestPath = bidRequest.mediaType === 'video' ? VIDEO_PATH : BANNER_PATH; - let requestParams = {url: currentUrl}; - let parameterStr = _buildQueryParameters(bidRequest, requestParams); + let pageParameters = {url: currentUrl}; + let parameterStr = _buildQueryParameters(bidRequest, pageParameters); let url = `//${env}${requestPath}${parameterStr}`; utils.logMessage('sending request to: ' + url); - ajax(url, 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; - } - - _addBidResponse(bidRequest, response); - }, null, {withCredentials: true}); + ajax(url, _handleResponse(bidRequest), null, {withCredentials: true}); } else { bidmanager.addBidResponse(bidRequest.placementCode, bidfactory.createBid(STATUS.NO_BID, bidRequest)); } @@ -93,7 +90,7 @@ const AerServAdapter = function AerServAdapter() { return { callBids: _callBids - }; + } }; module.exports = AerServAdapter; diff --git a/test/spec/adapters/aerserv_spec.js b/test/spec/adapters/aerserv_spec.js new file mode 100644 index 00000000000..c75e2be6f19 --- /dev/null +++ b/test/spec/adapters/aerserv_spec.js @@ -0,0 +1,197 @@ +import {expect} from 'chai'; +import AerServAdapter from 'src/adapters/aerserv'; +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('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); + }); + }); +}); From 36411f3fc8ad09ba16d2c3d24eb04d72b77a1fde Mon Sep 17 00:00:00 2001 From: Daniel Lawrence Date: Tue, 13 Jun 2017 11:14:05 -0700 Subject: [PATCH 3/6] implemented AerServ adapter --- src/adapters/aerserv.js | 99 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/adapters/aerserv.js diff --git a/src/adapters/aerserv.js b/src/adapters/aerserv.js new file mode 100644 index 00000000000..75b4137ca0b --- /dev/null +++ b/src/adapters/aerserv.js @@ -0,0 +1,99 @@ +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'; + +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 BIDDER_CODE = 'aerserv'; + const REQUIRED_PARAMS = ['plc']; + const VIDEO_TARGETING = []; + + function _isResponseValid(bidRequest, response) { + return ((bidRequest.mediaType === 'video' && response.vastUrl) || (bidRequest.mediaType !== 'video' && response.adm)) && + response.cpm && response.cpm > 0; + } + + function _addBidResponse(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.descriptionUrl = response.vastUrl; + } else { + bid.ad = response.adm; + } + bidmanager.addBidResponse(bidRequest.placementCode, bid); + } else { + bidmanager.addBidResponse(bidRequest.placementCode, bidfactory.createBid(STATUS.NO_BID, bidRequest)); + } + } + + function _buildQueryParameters(bidRequest, requestParams) { + Object.keys(bidRequest.params).forEach(param => requestParams[param] = bidRequest.params[param]); + + if (bidRequest.params.video) { + Object.keys(bidRequest.params.video) + .filter(param => VIDEO_TARGETING.includes(param)) + .forEach(param => requestParams[param] = bidRequest.params.video[param]); + } + + return utils.parseQueryStringParameters(requestParams); + } + + function _callBids(params) { + let currentUrl = (window.parent !== window) ? document.referrer : window.location.href; + currentUrl = currentUrl && encodeURIComponent(currentUrl); + + let bids = params.bids || []; + bids.forEach(bidRequest => { + if (utils.hasValidBidRequest(bidRequest.params, REQUIRED_PARAMS, BIDDER_CODE)) { + let env = ENVIRONMENTS[bidRequest.params['env']] || ENVIRONMENTS['prod']; + let requestPath = bidRequest.mediaType === 'video' ? VIDEO_PATH : BANNER_PATH; + let requestParams = {url: currentUrl}; + let parameterStr = _buildQueryParameters(bidRequest, requestParams); + + let url = `//${env}${requestPath}${parameterStr}`; + utils.logMessage('sending request to: ' + url); + ajax(url, 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; + } + + _addBidResponse(bidRequest, response); + }, null, {withCredentials: true}); + } else { + bidmanager.addBidResponse(bidRequest.placementCode, bidfactory.createBid(STATUS.NO_BID, bidRequest)); + } + }); + } + + return { + callBids: _callBids + }; +}; + +module.exports = AerServAdapter; From 45c257c46ee6c248cc12d574cfbc3d92e8c82463 Mon Sep 17 00:00:00 2001 From: Daniel Lawrence Date: Wed, 14 Jun 2017 09:54:14 -0700 Subject: [PATCH 4/6] added unit tests, slight refactor/formatting of adapter code, added to adapters json --- adapters.json | 6 + src/adapters/aerserv.js | 57 ++++----- test/spec/adapters/aerserv_spec.js | 197 +++++++++++++++++++++++++++++ 3 files changed, 230 insertions(+), 30 deletions(-) create mode 100644 test/spec/adapters/aerserv_spec.js diff --git a/adapters.json b/adapters.json index 704bb0bd388..6f0ef0f7e51 100644 --- a/adapters.json +++ b/adapters.json @@ -71,6 +71,7 @@ "prebidServer", "adsupply", "cox", + "aerserv", { "appnexus": { "alias": "brealtime" @@ -156,5 +157,10 @@ "conversant": { "supportedMediaTypes": ["video"] } + }, + { + "aerserv": { + "supportedMediaTypes": ["video"] + } } ] diff --git a/src/adapters/aerserv.js b/src/adapters/aerserv.js index 75b4137ca0b..39cefeb2801 100644 --- a/src/adapters/aerserv.js +++ b/src/adapters/aerserv.js @@ -16,14 +16,13 @@ const AerServAdapter = function AerServAdapter() { const VIDEO_PATH = '/as/json/pbjsvast/v1?'; const BIDDER_CODE = 'aerserv'; const REQUIRED_PARAMS = ['plc']; - const VIDEO_TARGETING = []; function _isResponseValid(bidRequest, response) { return ((bidRequest.mediaType === 'video' && response.vastUrl) || (bidRequest.mediaType !== 'video' && response.adm)) && response.cpm && response.cpm > 0; } - function _addBidResponse(bidRequest, response) { + function _createBid(bidRequest, response) { if (_isResponseValid(bidRequest, response)) { let bid = bidfactory.createBid(1, bidRequest); bid.bidderCode = BIDDER_CODE; @@ -45,46 +44,44 @@ const AerServAdapter = function AerServAdapter() { function _buildQueryParameters(bidRequest, requestParams) { Object.keys(bidRequest.params).forEach(param => requestParams[param] = bidRequest.params[param]); - if (bidRequest.params.video) { - Object.keys(bidRequest.params.video) - .filter(param => VIDEO_TARGETING.includes(param)) - .forEach(param => requestParams[param] = bidRequest.params.video[param]); - } - return utils.parseQueryStringParameters(requestParams); } - function _callBids(params) { + 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 = params.bids || []; + let bids = bidRequests.bids || []; bids.forEach(bidRequest => { if (utils.hasValidBidRequest(bidRequest.params, REQUIRED_PARAMS, BIDDER_CODE)) { let env = ENVIRONMENTS[bidRequest.params['env']] || ENVIRONMENTS['prod']; let requestPath = bidRequest.mediaType === 'video' ? VIDEO_PATH : BANNER_PATH; - let requestParams = {url: currentUrl}; - let parameterStr = _buildQueryParameters(bidRequest, requestParams); + let pageParameters = {url: currentUrl}; + let parameterStr = _buildQueryParameters(bidRequest, pageParameters); let url = `//${env}${requestPath}${parameterStr}`; utils.logMessage('sending request to: ' + url); - ajax(url, 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; - } - - _addBidResponse(bidRequest, response); - }, null, {withCredentials: true}); + ajax(url, _handleResponse(bidRequest), null, {withCredentials: true}); } else { bidmanager.addBidResponse(bidRequest.placementCode, bidfactory.createBid(STATUS.NO_BID, bidRequest)); } @@ -93,7 +90,7 @@ const AerServAdapter = function AerServAdapter() { return { callBids: _callBids - }; + } }; module.exports = AerServAdapter; diff --git a/test/spec/adapters/aerserv_spec.js b/test/spec/adapters/aerserv_spec.js new file mode 100644 index 00000000000..c75e2be6f19 --- /dev/null +++ b/test/spec/adapters/aerserv_spec.js @@ -0,0 +1,197 @@ +import {expect} from 'chai'; +import AerServAdapter from 'src/adapters/aerserv'; +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('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); + }); + }); +}); From c1381dbd2c70c528f94889d0b59007934875dbce Mon Sep 17 00:00:00 2001 From: Daniel Lawrence Date: Wed, 23 Aug 2017 14:08:01 -0700 Subject: [PATCH 5/6] feature necromancy! post-merge fixes to account for new structure --- ...ervBidAadapter.js => aerservBidAdapter.js} | 9 +- src/adapters/aerserv.js | 96 --------- test/spec/adapters/aerserv_spec.js | 197 ------------------ test/spec/modules/aerservBidAdapter_spec.js | 2 +- 4 files changed, 8 insertions(+), 296 deletions(-) rename modules/{aerservBidAadapter.js => aerservBidAdapter.js} (92%) delete mode 100644 src/adapters/aerserv.js delete mode 100644 test/spec/adapters/aerserv_spec.js diff --git a/modules/aerservBidAadapter.js b/modules/aerservBidAdapter.js similarity index 92% rename from modules/aerservBidAadapter.js rename to modules/aerservBidAdapter.js index 39cefeb2801..4e65a1ac8f1 100644 --- a/modules/aerservBidAadapter.js +++ b/modules/aerservBidAdapter.js @@ -3,6 +3,9 @@ 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 = { @@ -14,12 +17,11 @@ const AerServAdapter = function AerServAdapter() { const BANNER_PATH = '/as/json/pbjs/v1?'; const VIDEO_PATH = '/as/json/pbjsvast/v1?'; - const BIDDER_CODE = 'aerserv'; const REQUIRED_PARAMS = ['plc']; function _isResponseValid(bidRequest, response) { return ((bidRequest.mediaType === 'video' && response.vastUrl) || (bidRequest.mediaType !== 'video' && response.adm)) && - response.cpm && response.cpm > 0; + response.cpm && response.cpm > 0; } function _createBid(bidRequest, response) { @@ -32,6 +34,7 @@ const AerServAdapter = function AerServAdapter() { if (bidRequest.mediaType === 'video') { bid.vastUrl = response.vastUrl; bid.descriptionUrl = response.vastUrl; + bid.mediaType = 'video'; } else { bid.ad = response.adm; } @@ -93,4 +96,6 @@ const AerServAdapter = function AerServAdapter() { } }; +adaptermanager.registerBidAdapter(new AerServAdapter(), BIDDER_CODE, {supportedMediaTypes: ['video']}); + module.exports = AerServAdapter; diff --git a/src/adapters/aerserv.js b/src/adapters/aerserv.js deleted file mode 100644 index 39cefeb2801..00000000000 --- a/src/adapters/aerserv.js +++ /dev/null @@ -1,96 +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'; - -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 BIDDER_CODE = 'aerserv'; - 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.descriptionUrl = response.vastUrl; - } else { - bid.ad = response.adm; - } - bidmanager.addBidResponse(bidRequest.placementCode, bid); - } else { - bidmanager.addBidResponse(bidRequest.placementCode, bidfactory.createBid(STATUS.NO_BID, bidRequest)); - } - } - - function _buildQueryParameters(bidRequest, requestParams) { - Object.keys(bidRequest.params).forEach(param => requestParams[param] = bidRequest.params[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(bidRequest => { - if (utils.hasValidBidRequest(bidRequest.params, REQUIRED_PARAMS, BIDDER_CODE)) { - let env = ENVIRONMENTS[bidRequest.params['env']] || ENVIRONMENTS['prod']; - let requestPath = bidRequest.mediaType === 'video' ? VIDEO_PATH : BANNER_PATH; - let pageParameters = {url: currentUrl}; - let parameterStr = _buildQueryParameters(bidRequest, pageParameters); - - let url = `//${env}${requestPath}${parameterStr}`; - utils.logMessage('sending request to: ' + url); - ajax(url, _handleResponse(bidRequest), null, {withCredentials: true}); - } else { - bidmanager.addBidResponse(bidRequest.placementCode, bidfactory.createBid(STATUS.NO_BID, bidRequest)); - } - }); - } - - return { - callBids: _callBids - } -}; - -module.exports = AerServAdapter; diff --git a/test/spec/adapters/aerserv_spec.js b/test/spec/adapters/aerserv_spec.js deleted file mode 100644 index c75e2be6f19..00000000000 --- a/test/spec/adapters/aerserv_spec.js +++ /dev/null @@ -1,197 +0,0 @@ -import {expect} from 'chai'; -import AerServAdapter from 'src/adapters/aerserv'; -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('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/aerservBidAdapter_spec.js b/test/spec/modules/aerservBidAdapter_spec.js index 171a797072c..1a8553c45fe 100644 --- a/test/spec/modules/aerservBidAdapter_spec.js +++ b/test/spec/modules/aerservBidAdapter_spec.js @@ -1,5 +1,5 @@ import {expect} from 'chai'; -import AerServAdapter from 'modules/aerservBidAadapter'; +import AerServAdapter from 'modules/aerservBidAdapter'; import bidmanager from 'src/bidmanager'; const BASE_REQUEST = JSON.stringify({ From 5a8b9d4d2f2d163efce28a183c89e096db4f9238 Mon Sep 17 00:00:00 2001 From: Daniel Lawrence Date: Thu, 24 Aug 2017 16:35:55 -0700 Subject: [PATCH 6/6] last minute addition of some video parameter logic + some name refactoring --- modules/aerservBidAdapter.js | 34 +++++++++++++++------ test/spec/modules/aerservBidAdapter_spec.js | 16 ++++++++++ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/modules/aerservBidAdapter.js b/modules/aerservBidAdapter.js index 4e65a1ac8f1..64a02e77325 100644 --- a/modules/aerservBidAdapter.js +++ b/modules/aerservBidAdapter.js @@ -44,8 +44,24 @@ const AerServAdapter = function AerServAdapter() { } } - function _buildQueryParameters(bidRequest, requestParams) { - Object.keys(bidRequest.params).forEach(param => requestParams[param] = bidRequest.params[param]); + 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); } @@ -75,18 +91,18 @@ const AerServAdapter = function AerServAdapter() { currentUrl = currentUrl && encodeURIComponent(currentUrl); let bids = bidRequests.bids || []; - bids.forEach(bidRequest => { - if (utils.hasValidBidRequest(bidRequest.params, REQUIRED_PARAMS, BIDDER_CODE)) { - let env = ENVIRONMENTS[bidRequest.params['env']] || ENVIRONMENTS['prod']; - let requestPath = bidRequest.mediaType === 'video' ? VIDEO_PATH : BANNER_PATH; + 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(bidRequest, pageParameters); + let parameterStr = _buildQueryParameters(bid, pageParameters); let url = `//${env}${requestPath}${parameterStr}`; utils.logMessage('sending request to: ' + url); - ajax(url, _handleResponse(bidRequest), null, {withCredentials: true}); + ajax(url, _handleResponse(bid), null, {withCredentials: true}); } else { - bidmanager.addBidResponse(bidRequest.placementCode, bidfactory.createBid(STATUS.NO_BID, bidRequest)); + bidmanager.addBidResponse(bid.placementCode, bidfactory.createBid(STATUS.NO_BID, bid)); } }); } diff --git a/test/spec/modules/aerservBidAdapter_spec.js b/test/spec/modules/aerservBidAdapter_spec.js index 1a8553c45fe..be0f6393063 100644 --- a/test/spec/modules/aerservBidAdapter_spec.js +++ b/test/spec/modules/aerservBidAdapter_spec.js @@ -80,6 +80,22 @@ describe('AerServ Adapter', () => { 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');