diff --git a/modules/eskimiBidAdapter.js b/modules/eskimiBidAdapter.js
index 4a00b97614b2..88d8f95b8596 100644
--- a/modules/eskimiBidAdapter.js
+++ b/modules/eskimiBidAdapter.js
@@ -1,7 +1,7 @@
-import {registerBidder} from '../src/adapters/bidderFactory.js';
-import {BANNER} from '../src/mediaTypes.js';
+import { ortbConverter } from '../libraries/ortbConverter/converter.js';
+import { registerBidder } from '../src/adapters/bidderFactory.js';
+import { BANNER, VIDEO } from '../src/mediaTypes.js';
import * as utils from '../src/utils.js';
-import {ortbConverter} from '../libraries/ortbConverter/converter.js'
const BIDDER_CODE = 'eskimi';
// const ENDPOINT = 'https://hb.eskimi.com/bids'
@@ -12,43 +12,35 @@ const DEFAULT_CURRENCY = 'USD';
const DEFAULT_NET_REVENUE = true;
const GVLID = 814;
+const VIDEO_ORTB_PARAMS = [
+ 'mimes',
+ 'minduration',
+ 'maxduration',
+ 'placement',
+ 'protocols',
+ 'startdelay',
+ 'skip',
+ 'skipafter',
+ 'minbitrate',
+ 'maxbitrate',
+ 'delivery',
+ 'playbackmethod',
+ 'api',
+ 'linearity',
+ 'battr'
+];
+
+const BANNER_ORTB_PARAMS = [
+ 'battr'
+]
+
export const spec = {
code: BIDDER_CODE,
gvlid: GVLID,
- supportedMediaTypes: [BANNER],
-
- isBidRequestValid: function (bid) {
- return !!bid.params.placementId;
- },
-
- buildRequests(bidRequests, bidderRequest) {
- const data = converter.toORTB({bidRequests, bidderRequest})
-
- let bid = bidRequests.find((b) => b.params.placementId)
- if (!data.site) data.site = {}
- data.site.ext = {placementId: bid.params.placementId}
-
- if (bidderRequest.gdprConsent) {
- if (!data.user) data.user = {};
- if (!data.user.ext) data.user.ext = {};
- if (!data.regs) data.regs = {};
- if (!data.regs.ext) data.regs.ext = {};
- data.user.ext.consent = bidderRequest.gdprConsent.consentString;
- data.regs.ext.gdpr = bidderRequest.gdprConsent.gdprApplies ? 1 : 0;
- }
-
- return [{
- method: 'POST',
- url: ENDPOINT,
- data,
- options: {contentType: 'application/json;charset=UTF-8', withCredentials: false}
- }]
- },
-
- interpretResponse(response, request) {
- return converter.fromORTB({response: response.body, request: request.data}).bids;
- },
-
+ supportedMediaTypes: [BANNER, VIDEO],
+ isBidRequestValid,
+ buildRequests,
+ interpretResponse,
/**
* Register bidder specific code, which will execute if a bid from this bidder won the auction
* @param {Bid} bid The bid that won the auction
@@ -60,13 +52,151 @@ export const spec = {
}
}
-const converter = ortbConverter({
+registerBidder(spec);
+
+const CONVERTER = ortbConverter({
context: {
netRevenue: DEFAULT_NET_REVENUE,
ttl: DEFAULT_BID_TTL,
- currency: DEFAULT_CURRENCY,
- mediaType: BANNER // TODO: support more types, we should set mtype on the winning bid
+ currency: DEFAULT_CURRENCY
+ },
+ imp(buildImp, bidRequest, context) {
+ let imp = buildImp(bidRequest, context);
+ imp.secure = Number(window.location.protocol === 'https:');
+ if (!imp.bidfloor && bidRequest.params.bidFloor) {
+ imp.bidfloor = bidRequest.params.bidFloor;
+ imp.bidfloorcur = utils.getBidIdParameter('bidFloorCur', bidRequest.params).toUpperCase() || 'USD'
+ }
+
+ if (bidRequest.mediaTypes[VIDEO]) {
+ imp = buildVideoImp(bidRequest, imp);
+ } else if (bidRequest.mediaTypes[BANNER]) {
+ imp = buildBannerImp(bidRequest, imp);
+ }
+
+ return imp;
}
});
-registerBidder(spec);
+function isBidRequestValid(bidRequest) {
+ return (isPlacementIdValid(bidRequest) && (isValidBannerRequest(bidRequest) || isValidVideoRequest(bidRequest)));
+}
+
+function isPlacementIdValid(bidRequest) {
+ return utils.isNumber(bidRequest.params.placementId);
+}
+
+function isValidBannerRequest(bidRequest) {
+ const bannerSizes = utils.deepAccess(bidRequest, `mediaTypes.${BANNER}.sizes`);
+ return utils.isArray(bannerSizes) && bannerSizes.length > 0 && bannerSizes.every(size => utils.isNumber(size[0]) && utils.isNumber(size[1]));
+}
+
+function isValidVideoRequest(bidRequest) {
+ const videoSizes = utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}.playerSize`);
+
+ return utils.isArray(videoSizes) && videoSizes.length > 0 && videoSizes.every(size => utils.isNumber(size[0]) && utils.isNumber(size[1]));
+}
+
+function buildRequests(validBids, bidderRequest) {
+ let videoBids = validBids.filter(bid => isVideoBid(bid));
+ let bannerBids = validBids.filter(bid => isBannerBid(bid));
+ let requests = [];
+
+ bannerBids.forEach(bid => {
+ requests.push(createRequest([bid], bidderRequest, BANNER));
+ });
+
+ videoBids.forEach(bid => {
+ requests.push(createRequest([bid], bidderRequest, VIDEO));
+ });
+
+ return requests;
+}
+
+function interpretResponse(response, request) {
+ return CONVERTER.fromORTB({ request: request.data, response: response.body }).bids;
+}
+
+function buildVideoImp(bidRequest, imp) {
+ const videoAdUnitParams = utils.deepAccess(bidRequest, `mediaTypes.${VIDEO}`, {});
+ const videoBidderParams = utils.deepAccess(bidRequest, `params.${VIDEO}`, {});
+
+ const videoParams = { ...videoAdUnitParams, ...videoBidderParams };
+
+ const videoSizes = (videoAdUnitParams && videoAdUnitParams.playerSize) || [];
+
+ if (videoSizes && videoSizes.length > 0) {
+ utils.deepSetValue(imp, 'video.w', videoSizes[0][0]);
+ utils.deepSetValue(imp, 'video.h', videoSizes[0][1]);
+ }
+
+ VIDEO_ORTB_PARAMS.forEach((param) => {
+ if (videoParams.hasOwnProperty(param)) {
+ utils.deepSetValue(imp, `video.${param}`, videoParams[param]);
+ }
+ });
+
+ if (imp.video && videoParams?.context === 'outstream') {
+ imp.video.placement = imp.video.placement || 4;
+ }
+
+ return { ...imp };
+}
+
+function buildBannerImp(bidRequest, imp) {
+ const bannerAdUnitParams = utils.deepAccess(bidRequest, `mediaTypes.${BANNER}`, {});
+ const bannerBidderParams = utils.deepAccess(bidRequest, `params.${BANNER}`, {});
+
+ const bannerParams = { ...bannerAdUnitParams, ...bannerBidderParams };
+
+ let sizes = bidRequest.mediaTypes.banner.sizes;
+
+ if (sizes) {
+ utils.deepSetValue(imp, 'banner.w', sizes[0][0]);
+ utils.deepSetValue(imp, 'banner.h', sizes[0][1]);
+ }
+
+ BANNER_ORTB_PARAMS.forEach((param) => {
+ if (bannerParams.hasOwnProperty(param)) {
+ utils.deepSetValue(imp, `banner.${param}`, bannerParams[param]);
+ }
+ });
+
+ return { ...imp };
+}
+
+function createRequest(bidRequests, bidderRequest, mediaType) {
+ const data = CONVERTER.toORTB({ bidRequests, bidderRequest, context: { mediaType } })
+
+ const bid = bidRequests.find((b) => b.params.placementId)
+ if (!data.site) data.site = {}
+ data.site.ext = { placementId: bid.params.placementId }
+
+ if (bidderRequest.gdprConsent) {
+ if (!data.user) data.user = {};
+ if (!data.user.ext) data.user.ext = {};
+ if (!data.regs) data.regs = {};
+ if (!data.regs.ext) data.regs.ext = {};
+ data.user.ext.consent = bidderRequest.gdprConsent.consentString;
+ data.regs.ext.gdpr = bidderRequest.gdprConsent.gdprApplies ? 1 : 0;
+ }
+
+ if (bid.params.bcat) data.bcat = bid.params.bcat;
+ if (bid.params.badv) data.badv = bid.params.badv;
+ if (bid.params.bapp) data.bapp = bid.params.bapp;
+
+ return {
+ method: 'POST',
+ url: ENDPOINT,
+ data: data,
+ options: { contentType: 'application/json;charset=UTF-8', withCredentials: false }
+ }
+}
+
+function isVideoBid(bid) {
+ return utils.deepAccess(bid, 'mediaTypes.video');
+}
+
+function isBannerBid(bid) {
+ return utils.deepAccess(bid, 'mediaTypes.banner') || !isVideoBid(bid);
+}
diff --git a/modules/eskimiBidAdapter.md b/modules/eskimiBidAdapter.md
index 83ae87fd01b6..b3494a217eb7 100644
--- a/modules/eskimiBidAdapter.md
+++ b/modules/eskimiBidAdapter.md
@@ -6,29 +6,48 @@ Maintainer: tech@eskimi.com
# Description
-An adapter to get a bid from Eskimi DSP.
+Module that connects to Eskimi demand sources to fetch bids using OpenRTB standard.
+Banner and video formats are supported.
# Test Parameters
```javascript
var adUnits = [{
- code: 'div-gpt-ad-1460505748561-0',
- mediaTypes: {
- banner: {
- sizes: [[300, 250], [300, 600]]
- }
- },
-
- bids: [{
- bidder: 'eskimi',
- params: {
- placementId: 612
- }
- }]
-
- }];
+ code: '/19968336/prebid_banner_example_1',
+ mediaTypes: {
+ banner: {
+ sizes: [[ 300, 250 ]],
+ ... // battr
+ }
+ },
+ bids: [{
+ bidder: 'eskimi',
+ params: {
+ placementId: 612,
+ ... // bcat, badv, bapp
+ }
+ }]
+ }, {
+ code: '/19968336/prebid_video_example_1',
+ mediaTypes: {
+ video: {
+ context: 'outstream',
+ mimes: ['video/mp4'],
+ api: [1, 2, 4, 6],
+ ... // Aditional ORTB video params (including battr)
+ }
+ },
+ bids: [{
+ bidder: 'eskimi',
+ params: {
+ placementId: 612,
+ ... // bcat, badv, bapp
+ }
+ }]
+ }];
```
Where:
* placementId - Placement ID of the ad unit (required)
+* bcat, badv, bapp, battr - ORTB blocking parameters as specified by OpenRTB 2.5
diff --git a/test/spec/modules/eskimiBidAdapter_spec.js b/test/spec/modules/eskimiBidAdapter_spec.js
index 4622b374de57..d01240c86abd 100644
--- a/test/spec/modules/eskimiBidAdapter_spec.js
+++ b/test/spec/modules/eskimiBidAdapter_spec.js
@@ -1,155 +1,307 @@
-import {expect} from 'chai';
-import {spec} from 'modules/eskimiBidAdapter.js';
-
-const REQUEST = {
- 'bidderCode': 'eskimi',
- 'auctionId': 'auctionId-56a2-4f71-9098-720a68f2f708',
- 'bidderRequestId': 'requestId',
- 'bidRequest': [{
- 'bidder': 'eskimi',
- 'params': {
- 'placementId': 1003000,
- 'accId': 123
+import { expect } from 'chai';
+import { spec } from 'modules/eskimiBidAdapter.js';
+import * as utils from 'src/utils';
+
+const BANNER_BID = {
+ bidder: 'eskimi',
+ params: {
+ placementId: 1003000
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [
+ [300, 250]
+ ],
},
- 'sizes': [
- [300, 250]
- ],
- 'bidId': 'bidId1',
- 'adUnitCode': 'adUnitCode1',
- 'bidderRequestId': 'bidderRequestId',
- 'auctionId': 'auctionId-56a2-4f71-9098-720a68f2f708'
},
- {
- 'bidder': 'eskimi',
- 'params': {
- 'placementId': 1003001,
- 'accId': 123
+ adUnitCode: 'adUnitCode1',
+ bidId: 'bidId',
+ bidderRequestId: 'bidderRequestId',
+ auctionId: 'auctionId-56a2-4f71-9098-720a68f2f708',
+};
+
+const VIDEO_BID = {
+ bidder: 'eskimi',
+ params: {
+ placementId: 1003000
+ },
+ mediaTypes: {
+ video: {
+ context: 'outstream',
+ api: [1, 2, 4, 6],
+ mimes: ['video/mp4'],
+ playbackmethod: [2, 4, 6],
+ playerSize: [[1024, 768]],
+ protocols: [3, 4, 7, 8, 10],
+ placement: 1,
+ minduration: 0,
+ maxduration: 60,
+ startdelay: 0
},
- 'sizes': [
- [300, 250]
- ],
- 'bidId': 'bidId2',
- 'adUnitCode': 'adUnitCode2',
- 'bidderRequestId': 'bidderRequestId',
- 'auctionId': 'auctionId-56a2-4f71-9098-720a68f2f708'
- }],
- 'start': 1487883186070,
- 'auctionStart': 1487883186069,
- 'timeout': 3000
+ },
+ adUnitCode: 'adUnitCode1',
+ bidId: 'bidId',
+ bidderRequestId: 'bidderRequestId',
+ auctionId: 'auctionId-56a2-4f71-9098-720a68f2f708',
};
-const RESPONSE = {
- 'headers': null,
- 'body': {
- 'id': 'requestId',
- 'seatbid': [
- {
- 'bid': [
- {
- 'id': 'bidId1',
- 'impid': 'bidId1',
- 'price': 0.18,
- 'adm': '',
- 'adid': '144762342',
- 'adomain': [
- 'https://dummydomain.com'
- ],
- 'iurl': 'iurl',
- 'cid': '109',
- 'crid': 'creativeId',
- 'cat': [],
- 'w': 300,
- 'h': 250,
- 'ext': {
- 'prebid': {
- 'type': 'banner'
- },
- 'bidder': {
- 'eskimi': {
- 'brand_id': 334553,
- 'auction_id': 514667951122925701,
- 'bidder_id': 2,
- 'bid_ad_type': 0
- }
- }
- }
- }
- ],
- 'seat': 'seat'
- }
- ]
+const BIDDER_REQUEST = {
+ auctionId: 'auctionId-56a2-4f71-9098-720a68f2f708',
+ bidderRequestId: 'bidderRequestId',
+ timeout: 3000,
+ refererInfo: {
+ page: 'https://hello-world-page.com/',
+ domain: 'hello-world-page.com',
+ ref: 'http://example-domain.com/foo',
}
};
+const BANNER_BID_RESPONSE = {
+ 'id': 'bidderRequestId',
+ 'bidId': 'bidid',
+ 'seatbid': [
+ {
+ 'bid': [
+ {
+ 'id': 'id',
+ 'impid': 'bidId',
+ 'price': 0.18,
+ 'adm': '',
+ 'adid': '144762342',
+ 'burl': 'http://0.0.0.0:8181/burl',
+ 'adomain': [
+ 'https://dummydomain.com'
+ ],
+ 'cid': 'cid',
+ 'crid': 'crid',
+ 'iurl': 'iurl',
+ 'cat': [],
+ 'w': 300,
+ 'h': 250
+ }
+ ]
+ }
+ ],
+ 'cur': 'USD'
+};
+
+const VIDEO_BID_RESPONSE = {
+ 'id': 'bidderRequestId',
+ 'bidid': 'bidid',
+ 'seatbid': [
+ {
+ 'bid': [
+ {
+ 'id': 'id',
+ 'impid': 'bidId',
+ 'price': 1.09,
+ 'adid': '144762342',
+ 'burl': 'http://0.0.0.0:8181/burl',
+ 'adm': '',
+ 'adomain': [
+ 'https://dummydomain.com'
+ ],
+ 'cid': 'cid',
+ 'crid': 'crid',
+ 'iurl': 'iurl',
+ 'cat': [],
+ 'h': 768,
+ 'w': 1024
+ }
+ ]
+ }
+ ],
+ 'cur': 'USD'
+};
+
describe('Eskimi bid adapter', function () {
- describe('isBidRequestValid', function () {
+ describe('isBidRequestValid()', function () {
it('should accept request if placementId is passed', function () {
let bid = {
bidder: 'eskimi',
params: {
placementId: 123
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [[300, 250]]
+ }
}
};
expect(spec.isBidRequestValid(bid)).to.equal(true);
});
- it('reject requests without params', function () {
+
+ it('should reject requests without params', function () {
let bid = {
bidder: 'eskimi',
params: {}
};
expect(spec.isBidRequestValid(bid)).to.equal(false);
});
- });
- describe('buildRequests', function () {
- it('creates request data', function () {
- let request = spec.buildRequests(REQUEST.bidRequest, REQUEST)[0];
- expect(request).to.exist.and.to.be.a('object');
- const payload = request.data;
- expect(payload.imp[0]).to.have.property('id', REQUEST.bidRequest[0].bidId);
- expect(payload.imp[1]).to.have.property('id', REQUEST.bidRequest[1].bidId);
+ it('should return true when required params found', () => {
+ expect(spec.isBidRequestValid(BANNER_BID)).to.equal(true);
+ expect(spec.isBidRequestValid(VIDEO_BID)).to.equal(true);
});
+ });
- it('has gdpr data if applicable', function () {
- const req = Object.assign({}, REQUEST, {
+ describe('buildRequests()', function () {
+ it('should have gdpr data if applicable', function () {
+ const bid = utils.deepClone(BANNER_BID);
+
+ const req = Object.assign({}, BIDDER_REQUEST, {
gdprConsent: {
consentString: 'consentString',
gdprApplies: true,
}
});
- let request = spec.buildRequests(REQUEST.bidRequest, req)[0];
+ let request = spec.buildRequests([bid], req)[0];
const payload = request.data;
expect(payload.user.ext).to.have.property('consent', req.gdprConsent.consentString);
expect(payload.regs.ext).to.have.property('gdpr', 1);
});
- });
- describe('interpretResponse', function () {
- it('has bids', function () {
- let request = spec.buildRequests(REQUEST.bidRequest, REQUEST)[0];
- let bids = spec.interpretResponse(RESPONSE, request);
- expect(bids).to.be.an('array').that.is.not.empty;
- validateBidOnIndex(0);
-
- function validateBidOnIndex(index) {
- expect(bids[index]).to.have.property('currency', 'USD');
- expect(bids[index]).to.have.property('requestId', RESPONSE.body.seatbid[0].bid[index].id);
- expect(bids[index]).to.have.property('cpm', RESPONSE.body.seatbid[0].bid[index].price);
- expect(bids[index]).to.have.property('width', RESPONSE.body.seatbid[0].bid[index].w);
- expect(bids[index]).to.have.property('height', RESPONSE.body.seatbid[0].bid[index].h);
- expect(bids[index]).to.have.property('ad', RESPONSE.body.seatbid[0].bid[index].adm);
- expect(bids[index]).to.have.property('creativeId', RESPONSE.body.seatbid[0].bid[index].crid);
- expect(bids[index]).to.have.property('ttl', 30);
- expect(bids[index]).to.have.property('netRevenue', true);
- }
+ it('should properly forward ORTB blocking params', function () {
+ let bid = utils.deepClone(BANNER_BID);
+ bid = utils.mergeDeep(bid, {
+ params: { bcat: ['IAB1-1'], badv: ['example.com'], bapp: ['com.example'] },
+ mediaTypes: { banner: { battr: [1] } }
+ });
+
+ let [request] = spec.buildRequests([bid], BIDDER_REQUEST);
+
+ expect(request).to.exist.and.to.be.an('object');
+ const payload = request.data;
+ expect(payload).to.have.deep.property('bcat', ['IAB1-1']);
+ expect(payload).to.have.deep.property('badv', ['example.com']);
+ expect(payload).to.have.deep.property('bapp', ['com.example']);
+ expect(payload.imp[0].banner).to.have.deep.property('battr', [1]);
+ });
+
+ context('when mediaType is banner', function () {
+ it('should build correct request for banner bid with both w, h', () => {
+ const bid = utils.deepClone(BANNER_BID);
+
+ const [request] = spec.buildRequests([bid], BIDDER_REQUEST);
+ const requestData = request.data;
+
+ expect(requestData.imp[0].banner.w).to.equal(300);
+ expect(requestData.imp[0].banner.h).to.equal(250);
+ });
+
+ it('should create request data', function () {
+ const bid = utils.deepClone(BANNER_BID);
+
+ let [request] = spec.buildRequests([bid], BIDDER_REQUEST);
+ expect(request).to.exist.and.to.be.a('object');
+ const payload = request.data;
+ expect(payload.imp[0]).to.have.property('id', bid.bidId);
+ });
});
- it('handles empty response', function () {
- let request = spec.buildRequests(REQUEST.bidRequest, REQUEST)[0];
- const EMPTY_RESP = Object.assign({}, RESPONSE, {'body': {}});
- const bids = spec.interpretResponse(EMPTY_RESP, request);
- expect(bids).to.be.empty;
+ context('when mediaType is video', function () {
+ it('should return false when there is no video in mediaTypes', () => {
+ const bid = utils.deepClone(VIDEO_BID);
+ delete bid.mediaTypes.video;
+
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+
+ it('should reutrn false if player size is not set', () => {
+ const bid = utils.deepClone(VIDEO_BID);
+ delete bid.mediaTypes.video.playerSize;
+
+ expect(spec.isBidRequestValid(bid)).to.equal(false);
+ });
+
+ it('should use bidder video params if they are set', () => {
+ const videoBidWithParams = utils.deepClone(VIDEO_BID);
+ const bidderVideoParams = {
+ api: [1, 2],
+ mimes: ['video/mp4', 'video/x-flv'],
+ playbackmethod: [3, 4],
+ protocols: [5, 6],
+ placement: 1,
+ minduration: 0,
+ maxduration: 60,
+ w: 1024,
+ h: 768,
+ startdelay: 0
+ };
+
+ videoBidWithParams.params.video = bidderVideoParams;
+
+ const requests = spec.buildRequests([videoBidWithParams], BIDDER_REQUEST);
+ const request = requests[0].data;
+
+ expect(request.imp[0]).to.deep.include({
+ video: {
+ ...bidderVideoParams,
+ w: videoBidWithParams.mediaTypes.video.playerSize[0][0],
+ h: videoBidWithParams.mediaTypes.video.playerSize[0][1],
+ },
+ });
+ });
});
});
+
+ describe('interpretResponse()', function () {
+ context('when mediaType is banner', function () {
+ it('should correctly interpret valid banner response', function () {
+ const bid = utils.deepClone(BANNER_BID);
+ const [request] = spec.buildRequests([bid], BIDDER_REQUEST);
+ const response = utils.deepClone(BANNER_BID_RESPONSE);
+
+ const bids = spec.interpretResponse({ body: response }, request);
+ expect(bids).to.be.an('array').that.is.not.empty;
+
+ expect(bids[0].mediaType).to.equal('banner');
+ expect(bids[0].burl).to.equal(BANNER_BID_RESPONSE.seatbid[0].bid[0].burl);
+ expect(bids[0].currency).to.equal('USD');
+ expect(bids[0].requestId).to.equal(BANNER_BID_RESPONSE.seatbid[0].bid[0].impid);
+ expect(bids[0].cpm).to.equal(BANNER_BID_RESPONSE.seatbid[0].bid[0].price);
+ expect(bids[0].width).to.equal(BANNER_BID_RESPONSE.seatbid[0].bid[0].w);
+ expect(bids[0].height).to.equal(BANNER_BID_RESPONSE.seatbid[0].bid[0].h);
+ expect(bids[0].ad).to.equal(BANNER_BID_RESPONSE.seatbid[0].bid[0].adm);
+ expect(bids[0].creativeId).to.equal(BANNER_BID_RESPONSE.seatbid[0].bid[0].crid);
+ expect(bids[0].meta.advertiserDomains[0]).to.equal('https://dummydomain.com');
+ expect(bids[0].ttl).to.equal(30);
+ expect(bids[0].netRevenue).to.equal(true);
+ });
+
+ it('should handle empty bid response', function () {
+ const bid = utils.deepClone(BANNER_BID);
+
+ let request = spec.buildRequests([bid], BIDDER_REQUEST)[0];
+ const EMPTY_RESP = Object.assign({}, BANNER_BID_RESPONSE, { 'body': {} });
+ const bids = spec.interpretResponse(EMPTY_RESP, request);
+ expect(bids).to.be.empty;
+ });
+ });
+ if (FEATURES.VIDEO) {
+ context('when mediaType is video', function () {
+ it('should correctly interpret valid instream video response', () => {
+ const bid = utils.deepClone(VIDEO_BID);
+
+ const [request] = spec.buildRequests([bid], BIDDER_REQUEST);
+ const bids = spec.interpretResponse({ body: VIDEO_BID_RESPONSE }, request);
+ expect(bids).to.be.an('array').that.is.not.empty;
+
+ expect(bids[0].mediaType).to.equal('video');
+ expect(bids[0].burl).to.equal(VIDEO_BID_RESPONSE.seatbid[0].bid[0].burl);
+ expect(bids[0].currency).to.equal('USD');
+ expect(bids[0].requestId).to.equal(VIDEO_BID_RESPONSE.seatbid[0].bid[0].impid);
+ expect(bids[0].cpm).to.equal(VIDEO_BID_RESPONSE.seatbid[0].bid[0].price);
+ expect(bids[0].width).to.equal(VIDEO_BID_RESPONSE.seatbid[0].bid[0].w);
+ expect(bids[0].height).to.equal(VIDEO_BID_RESPONSE.seatbid[0].bid[0].h);
+ expect(bids[0].vastXml).to.equal(VIDEO_BID_RESPONSE.seatbid[0].bid[0].adm);
+ expect(bids[0].creativeId).to.equal(VIDEO_BID_RESPONSE.seatbid[0].bid[0].crid);
+ expect(bids[0].meta.advertiserDomains[0]).to.equal('https://dummydomain.com');
+ expect(bids[0].ttl).to.equal(30);
+ expect(bids[0].netRevenue).to.equal(true);
+ });
+ });
+ }
+ });
});