diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index 7f59e46920e..a53597a9074 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -1,9 +1,10 @@ -import { BANNER } from '../src/mediaTypes.js'; +import { config } from '../src/config.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { getBidFloor } from '../libraries/equativUtils/equativUtils.js' +import { getStorageManager } from '../src/storageManager.js'; import { ortbConverter } from '../libraries/ortbConverter/converter.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { getStorageManager } from '../src/storageManager.js'; -import { deepAccess, deepSetValue, mergeDeep } from '../src/utils.js'; +import { deepAccess, deepSetValue, logError, logWarn, mergeDeep } from '../src/utils.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').Bid} Bid @@ -13,14 +14,26 @@ import { deepAccess, deepSetValue, mergeDeep } from '../src/utils.js'; const BIDDER_CODE = 'equativ'; const COOKIE_SYNC_ORIGIN = 'https://apps.smartadserver.com'; const COOKIE_SYNC_URL = `${COOKIE_SYNC_ORIGIN}/diff/templates/asset/csync.html`; +const LOG_PREFIX = 'Equativ:'; const PID_COOKIE_NAME = 'eqt_pid'; +/** + * Evaluates a bid request for validity. Returns false if the + * request contains a video media type with no properties, true + * otherwise. + * @param {*} bidReq A bid request object to evaluate + * @returns boolean + */ +function isValid(bidReq) { + return !(bidReq.mediaTypes.video && JSON.stringify(bidReq.mediaTypes.video) === '{}'); +} + export const storage = getStorageManager({ bidderCode: BIDDER_CODE }); export const spec = { code: BIDDER_CODE, gvlid: 45, - supportedMediaTypes: [BANNER], + supportedMediaTypes: [BANNER, VIDEO], /** * @param bidRequests @@ -28,11 +41,23 @@ export const spec = { * @returns {ServerRequest[]} */ buildRequests: (bidRequests, bidderRequest) => { - return { - data: converter.toORTB({ bidderRequest, bidRequests }), - method: 'POST', - url: 'https://ssb-global.smartadserver.com/api/bid?callerId=169' - }; + if (bidRequests.filter(isValid).length === 0) { + logError(`${LOG_PREFIX} No useful bid requests to process. No request will be sent.`, bidRequests); + return undefined; + } + + const requests = []; + + bidRequests.forEach(bid => { + const data = converter.toORTB({bidRequests: [bid], bidderRequest}); + requests.push({ + data, + method: 'POST', + url: 'https://ssb-global.smartadserver.com/api/bid?callerId=169', + }) + }); + + return requests; }, /** @@ -89,32 +114,23 @@ export const converter = ortbConverter({ imp(buildImp, bidRequest, context) { const imp = buildImp(bidRequest, context); + const mediaType = deepAccess(bidRequest, 'mediaTypes.video') ? VIDEO : BANNER; const { siteId, pageId, formatId } = bidRequest.params; delete imp.dt; - imp.bidfloor = imp.bidfloor || getBidFloor(bidRequest); - imp.secure = bidRequest.ortb2Imp?.secure ?? 1; - imp.tagid = bidRequest.adUnitCode; - - if (siteId || pageId || formatId) { - const bidder = {}; - - if (siteId) { - bidder.siteId = siteId; - } + imp.bidfloor = imp.bidfloor || getBidFloor(bidRequest, config.getConfig('currency.adServerCurrency'), mediaType); + imp.secure = 1; - if (pageId) { - bidder.pageId = pageId; - } + imp.tagid = bidRequest.adUnitCode; - if (formatId) { - bidder.formatId = formatId; - } + if (!deepAccess(bidRequest, 'ortb2Imp.rwdd') && deepAccess(bidRequest, 'mediaTypes.video.ext.rewarded')) { + mergeDeep(imp, { rwdd: bidRequest.mediaTypes.video.ext.rewarded }); + } - mergeDeep(imp, { - ext: { bidder }, - }); + const bidder = { ...(siteId && { siteId }), ...(pageId && { pageId }), ...(formatId && { formatId }) }; + if (Object.keys(bidder).length) { + mergeDeep(imp.ext, { bidder }); } return imp; @@ -124,14 +140,15 @@ export const converter = ortbConverter({ const bid = context.bidRequests[0]; const req = buildRequest(imps, bidderRequest, context); - if (deepAccess(bid, 'ortb2.site.publisher')) { - deepSetValue(req, 'site.publisher.id', bid.ortb2.site.publisher.id || bid.params.networkId); - } else if (deepAccess(bid, 'ortb2.app.publisher')) { - deepSetValue(req, 'app.publisher.id', bid.ortb2.app.publisher.id || bid.params.networkId); - } else if (deepAccess(bid, 'ortb2.dooh.publisher')) { - deepSetValue(req, 'dooh.publisher.id', bid.ortb2.dooh.publisher.id || bid.params.networkId); - } else { - deepSetValue(req, 'site.publisher.id', bid.params.networkId); + let env = ['ortb2.site.publisher', 'ortb2.app.publisher', 'ortb2.dooh.publisher'].find(propPath => deepAccess(bid, propPath)) || 'ortb2.site.publisher'; + deepSetValue(req, env.replace('ortb2.', '') + '.id', deepAccess(bid, env + '.id') || bid.params.networkId); + + if (deepAccess(bid, 'mediaTypes.video')) { + ['mimes', 'placement'].forEach(prop => { + if (!bid.mediaTypes.video[prop]) { + logWarn(`${LOG_PREFIX} Property "${prop}" is missing from request`, bid); + } + }); } const pid = storage.getCookie(PID_COOKIE_NAME); @@ -140,7 +157,7 @@ export const converter = ortbConverter({ } return req; - }, + } }); registerBidder(spec); diff --git a/test/spec/modules/equativBidAdapter_spec.js b/test/spec/modules/equativBidAdapter_spec.js index c52507a000b..9f767a3cd4e 100644 --- a/test/spec/modules/equativBidAdapter_spec.js +++ b/test/spec/modules/equativBidAdapter_spec.js @@ -1,9 +1,20 @@ import { BANNER } from 'src/mediaTypes.js'; import { getBidFloor } from 'libraries/equativUtils/equativUtils.js' import { converter, spec, storage } from 'modules/equativBidAdapter.js'; +import * as utils from '../../../src/utils.js'; describe('Equativ bid adapter tests', () => { - const DEFAULT_BID_REQUESTS = [ + let sandBox; + + beforeEach(() => { + sandBox = sinon.createSandbox(); + sandBox.stub(utils, 'logError'); + sandBox.stub(utils, 'logWarn'); + }); + + afterEach(() => sandBox.restore()); + + const DEFAULT_BANNER_BID_REQUESTS = [ { adUnitCode: 'eqtv_42', bidId: 'abcd1234', @@ -25,12 +36,56 @@ describe('Equativ bid adapter tests', () => { tid: 'zsfgzzg', }, }, - }, + } + ]; + + const DEFAULT_VIDEO_BID_REQUESTS = [ + { + adUnitCode: 'eqtv_43', + bidId: 'efgh5678', + mediaTypes: { + video: { + context: 'instream', + playerSize: [[640, 480]], + pos: 3, + skip: 1, + linearity: 1, + minduration: 10, + maxduration: 30, + minbitrate: 300, + maxbitrate: 600, + w: 640, + h: 480, + playbackmethod: [1], + api: [3], + mimes: ['video/x-flv', 'video/mp4'], + // protocols: [2, 3], // used in older adapter ... including as comment for reference + startdelay: 42, + battr: [13, 14], + placement: 1, + }, + }, + bidder: 'equativ', + params: { + networkId: 111, + }, + requestId: 'abcd1234', + ortb2Imp: { + ext: { + tid: 'zsgzgzz', + }, + }, + } ]; - const DEFAULT_BIDDER_REQUEST = { + const DEFAULT_BANNER_BIDDER_REQUEST = { + bidderCode: 'equativ', + bids: DEFAULT_BANNER_BID_REQUESTS, + }; + + const DEFAULT_VIDEO_BIDDER_REQUEST = { bidderCode: 'equativ', - bids: DEFAULT_BID_REQUESTS, + bids: DEFAULT_VIDEO_BID_REQUESTS, }; const SAMPLE_RESPONSE = { @@ -62,25 +117,18 @@ describe('Equativ bid adapter tests', () => { }, }; - // const RESPONSE_WITH_DSP_PIXELS = { - // ...SAMPLE_RESPONSE, - // body: { - // dspPixels: ['1st-pixel', '2nd-pixel', '3rd-pixel'] - // } - // }; - describe('buildRequests', () => { - it('should build correct request using ORTB converter', () => { + it('should build correct requests using ORTB converter', () => { const request = spec.buildRequests( - DEFAULT_BID_REQUESTS, - DEFAULT_BIDDER_REQUEST + DEFAULT_BANNER_BID_REQUESTS, + DEFAULT_BANNER_BIDDER_REQUEST ); const dataFromConverter = converter.toORTB({ - bidderRequest: DEFAULT_BIDDER_REQUEST, - bidRequests: DEFAULT_BID_REQUESTS, + bidderRequest: DEFAULT_BANNER_BIDDER_REQUEST, + bidRequests: DEFAULT_BANNER_BID_REQUESTS, }); - expect(request).to.deep.equal({ - data: { ...dataFromConverter, id: request.data.id }, + expect(request[0]).to.deep.equal({ + data: { ...dataFromConverter, id: request[0].data.id }, method: 'POST', url: 'https://ssb-global.smartadserver.com/api/bid?callerId=169', }); @@ -88,10 +136,10 @@ describe('Equativ bid adapter tests', () => { it('should add ext.bidder to imp object when siteId is defined', () => { const bidRequests = [ - { ...DEFAULT_BID_REQUESTS[0], params: { siteId: 123 } }, + { ...DEFAULT_BANNER_BID_REQUESTS[0], params: { siteId: 123 } }, ]; - const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; - const request = spec.buildRequests(bidRequests, bidderRequest); + const bidderRequest = { ...DEFAULT_BANNER_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.data.imp[0].ext.bidder).to.deep.equal({ siteId: 123, }); @@ -99,10 +147,10 @@ describe('Equativ bid adapter tests', () => { it('should add ext.bidder to imp object when pageId is defined', () => { const bidRequests = [ - { ...DEFAULT_BID_REQUESTS[0], params: { pageId: 123 } }, + { ...DEFAULT_BANNER_BID_REQUESTS[0], params: { pageId: 123 } }, ]; - const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; - const request = spec.buildRequests(bidRequests, bidderRequest); + const bidderRequest = { ...DEFAULT_BANNER_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.data.imp[0].ext.bidder).to.deep.equal({ pageId: 123, }); @@ -110,33 +158,33 @@ describe('Equativ bid adapter tests', () => { it('should add ext.bidder to imp object when formatId is defined', () => { const bidRequests = [ - { ...DEFAULT_BID_REQUESTS[0], params: { formatId: 123 } }, + { ...DEFAULT_BANNER_BID_REQUESTS[0], params: { formatId: 123 } }, ]; - const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; - const request = spec.buildRequests(bidRequests, bidderRequest); + const bidderRequest = { ...DEFAULT_BANNER_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.data.imp[0].ext.bidder).to.deep.equal({ formatId: 123, }); }); it('should not add ext.bidder to imp object when siteId, pageId, formatId are not defined', () => { - const bidRequests = [{ ...DEFAULT_BID_REQUESTS[0], params: {} }]; - const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; - const request = spec.buildRequests(bidRequests, bidderRequest); + const bidRequests = [{ ...DEFAULT_BANNER_BID_REQUESTS[0], params: {} }]; + const bidderRequest = { ...DEFAULT_BANNER_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.data.imp[0].ext.bidder).to.be.undefined; }); it('should add site.publisher.id param', () => { const request = spec.buildRequests( - DEFAULT_BID_REQUESTS, - DEFAULT_BIDDER_REQUEST - ); + DEFAULT_BANNER_BID_REQUESTS, + DEFAULT_BANNER_BIDDER_REQUEST + )[0]; expect(request.data.site.publisher.id).to.equal(111); }); it('should pass ortb2.site.publisher.id', () => { const bidRequests = [{ - ...DEFAULT_BID_REQUESTS[0], + ...DEFAULT_BANNER_BID_REQUESTS[0], ortb2: { site: { publisher: { @@ -146,28 +194,28 @@ describe('Equativ bid adapter tests', () => { } }]; delete bidRequests[0].params; - const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; - const request = spec.buildRequests(bidRequests, bidderRequest); + const bidderRequest = { ...DEFAULT_BANNER_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.data.site.publisher.id).to.equal(98); }); it('should pass networkId as site.publisher.id', () => { const bidRequests = [{ - ...DEFAULT_BID_REQUESTS[0], + ...DEFAULT_BANNER_BID_REQUESTS[0], ortb2: { site: { publisher: {} } } }]; - const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; - const request = spec.buildRequests(bidRequests, bidderRequest); + const bidderRequest = { ...DEFAULT_BANNER_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.data.site.publisher.id).to.equal(111); }); it('should pass ortb2.app.publisher.id', () => { const bidRequests = [{ - ...DEFAULT_BID_REQUESTS[0], + ...DEFAULT_BANNER_BID_REQUESTS[0], ortb2: { app: { publisher: { @@ -177,28 +225,28 @@ describe('Equativ bid adapter tests', () => { } }]; delete bidRequests[0].params; - const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; - const request = spec.buildRequests(bidRequests, bidderRequest); + const bidderRequest = { ...DEFAULT_BANNER_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.data.app.publisher.id).to.equal(27); }); it('should pass networkId as app.publisher.id', () => { const bidRequests = [{ - ...DEFAULT_BID_REQUESTS[0], + ...DEFAULT_BANNER_BID_REQUESTS[0], ortb2: { app: { publisher: {} } } }]; - const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; - const request = spec.buildRequests(bidRequests, bidderRequest); + const bidderRequest = { ...DEFAULT_BANNER_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.data.app.publisher.id).to.equal(111); }); it('should pass ortb2.dooh.publisher.id', () => { const bidRequests = [{ - ...DEFAULT_BID_REQUESTS[0], + ...DEFAULT_BANNER_BID_REQUESTS[0], ortb2: { dooh: { publisher: { @@ -208,55 +256,55 @@ describe('Equativ bid adapter tests', () => { } }]; delete bidRequests[0].params; - const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; - const request = spec.buildRequests(bidRequests, bidderRequest); + const bidderRequest = { ...DEFAULT_BANNER_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.data.dooh.publisher.id).to.equal(35); }); it('should pass networkId as dooh.publisher.id', () => { const bidRequests = [{ - ...DEFAULT_BID_REQUESTS[0], + ...DEFAULT_BANNER_BID_REQUESTS[0], ortb2: { dooh: { publisher: {} } } }]; - const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; - const request = spec.buildRequests(bidRequests, bidderRequest); + const bidderRequest = { ...DEFAULT_BANNER_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.data.dooh.publisher.id).to.equal(111); }); it('should send default floor of 0.0', () => { const request = spec.buildRequests( - DEFAULT_BID_REQUESTS, - DEFAULT_BIDDER_REQUEST - ); + DEFAULT_BANNER_BID_REQUESTS, + DEFAULT_BANNER_BIDDER_REQUEST + )[0]; expect(request.data.imp[0]).to.have.property('bidfloor').that.eq(0.0); }); it('should send secure connection', () => { const request = spec.buildRequests( - DEFAULT_BID_REQUESTS, - DEFAULT_BIDDER_REQUEST - ); + DEFAULT_BANNER_BID_REQUESTS, + DEFAULT_BANNER_BIDDER_REQUEST + )[0]; expect(request.data.imp[0]).to.have.property('secure').that.eq(1); }); it('should have tagid', () => { const request = spec.buildRequests( - DEFAULT_BID_REQUESTS, - DEFAULT_BIDDER_REQUEST - ); - expect(request.data.imp[0]).to.have.property('tagid').that.eq(DEFAULT_BID_REQUESTS[0].adUnitCode); + DEFAULT_BANNER_BID_REQUESTS, + DEFAULT_BANNER_BIDDER_REQUEST + )[0]; + expect(request.data.imp[0]).to.have.property('tagid').that.eq(DEFAULT_BANNER_BID_REQUESTS[0].adUnitCode); }); it('should remove dt', () => { const bidRequests = [ - { ...DEFAULT_BID_REQUESTS[0], ortb2Imp: { dt: 1728377558235 } } + { ...DEFAULT_BANNER_BID_REQUESTS[0], ortb2Imp: { dt: 1728377558235 } } ]; - const bidderRequest = { ...DEFAULT_BIDDER_REQUEST, bids: bidRequests }; - const request = spec.buildRequests(bidRequests, bidderRequest); + const bidderRequest = { ...DEFAULT_BANNER_BIDDER_REQUEST, bids: bidRequests }; + const request = spec.buildRequests(bidRequests, bidderRequest)[0]; expect(request.data.imp[0]).to.not.have.property('dt'); }); @@ -268,9 +316,9 @@ describe('Equativ bid adapter tests', () => { getCookieStub.callsFake(cookieName => cookieData[cookieName]); const request = spec.buildRequests( - DEFAULT_BID_REQUESTS, - DEFAULT_BIDDER_REQUEST - ); + DEFAULT_BANNER_BID_REQUESTS, + DEFAULT_BANNER_BIDDER_REQUEST + )[0]; expect(request.data.user).to.have.property('buyeruid').that.eq(cookieData['eqt_pid']); @@ -282,9 +330,9 @@ describe('Equativ bid adapter tests', () => { getCookieStub.callsFake(() => null); const request = spec.buildRequests( - DEFAULT_BID_REQUESTS, - DEFAULT_BIDDER_REQUEST - ); + DEFAULT_BANNER_BID_REQUESTS, + DEFAULT_BANNER_BIDDER_REQUEST + )[0]; expect(request.data).to.not.have.property('user'); @@ -296,25 +344,163 @@ describe('Equativ bid adapter tests', () => { getCookieStub.callsFake(() => undefined); const bidRequest = { - ...DEFAULT_BIDDER_REQUEST, + ...DEFAULT_BANNER_BIDDER_REQUEST, ortb2: { user: { buyeruid: 'buyeruid-provided-by-publisher' } } }; - const request = spec.buildRequests([ DEFAULT_BID_REQUESTS[0] ], bidRequest); + const request = spec.buildRequests([ DEFAULT_BANNER_BID_REQUESTS[0] ], bidRequest)[0]; expect(request.data.user.buyeruid).to.deep.eq(bidRequest.ortb2.user.buyeruid); getCookieStub.restore(); }); + + it('should build a video request properly under normal circumstances', () => { + // ASSEMBLE + if (FEATURES.VIDEO) { + // ACT + const request = spec.buildRequests(DEFAULT_VIDEO_BID_REQUESTS, {})[0].data; + + // ASSERT + expect(request.imp[0]).to.have.property('video'); + + const videoObj = request.imp[0].video; + + expect(videoObj).to.have.property('api').and.to.deep.equal([3]); + expect(videoObj).to.have.property('battr').and.to.deep.equal([13, 14]); + expect(videoObj).to.have.property('linearity').and.to.equal(1); + expect(videoObj).to.have.property('mimes').and.to.deep.equal(['video/x-flv', 'video/mp4']); + expect(videoObj).to.have.property('minbitrate').and.to.equal(300); + expect(videoObj).to.have.property('maxbitrate').and.to.equal(600); + expect(videoObj).to.have.property('minduration').and.to.equal(10); + expect(videoObj).to.have.property('maxduration').and.to.equal(30); + expect(videoObj).to.have.property('placement').and.to.equal(1); + expect(videoObj).to.have.property('playbackmethod').and.to.deep.equal([1]); + expect(videoObj).to.have.property('pos').and.to.equal(3); + expect(videoObj).to.have.property('skip').and.to.equal(1); + expect(videoObj).to.have.property('startdelay').and.to.equal(42); + expect(videoObj).to.have.property('w').and.to.equal(640); + expect(videoObj).to.have.property('h').and.to.equal(480); + expect(videoObj).not.to.have.property('ext'); + } + }); + + it('should read and pass ortb2Imp.rwdd', () => { + // ASSEMBLE + if (FEATURES.VIDEO) { + const bidRequestsWithOrtb2ImpRwdd = [ + { + ...DEFAULT_VIDEO_BID_REQUESTS[0], + ortb2Imp: { + rwdd: 1 + } + } + ]; + // ACT + const request = spec.buildRequests(bidRequestsWithOrtb2ImpRwdd, {})[0].data; + + // ASSERT + expect(request.imp[0]).to.have.property('rwdd').and.to.equal(1); + } + }); + + it('should read mediaTypes.video.ext.rewarded and pass as rwdd', () => { + // ASSEMBLE + if (FEATURES.VIDEO) { + const bidRequestsWithExtReworded = [ + { + ...DEFAULT_VIDEO_BID_REQUESTS[0], + mediaTypes: { + video: { + ext: { + rewarded: 1 + } + } + } + } + ]; + // ACT + const request = spec.buildRequests(bidRequestsWithExtReworded, {})[0].data; + + // ASSERT + expect(request.imp[0]).to.have.property('rwdd').and.to.equal(1); + } + }); + + it('should prioritize ortb2Imp.rwdd over mediaTypes.video.ext.rewarded', () => { + // ASSEMBLE + if (FEATURES.VIDEO) { + const bidRequestsWithBothRewordedParams = [ + { + ...DEFAULT_VIDEO_BID_REQUESTS[0], + mediaTypes: { + video: { + ext: { + rewarded: 1 + } + } + }, + ortb2Imp: { + rwdd: 2 + } + } + ]; + // ACT + const request = spec.buildRequests(bidRequestsWithBothRewordedParams, {})[0].data; + + // ASSERT + expect(request.imp[0]).to.have.property('rwdd').and.to.equal(2); + } + }); + + it('should warn about missing required properties for video requests', () => { + // ASSEMBLE + const missingRequiredVideoRequest = DEFAULT_VIDEO_BID_REQUESTS[0]; + + // removing required properties + delete missingRequiredVideoRequest.mediaTypes.video.mimes; + delete missingRequiredVideoRequest.mediaTypes.video.placement; + + const bidRequests = [ missingRequiredVideoRequest ]; + const bidderRequest = { ...DEFAULT_VIDEO_BIDDER_REQUEST, bids: bidRequests }; + + // ACT + spec.buildRequests(bidRequests, bidderRequest); + + // ASSERT + expect(utils.logWarn.callCount).to.equal(2); + expect(utils.logWarn.getCall(0).args[0]).to.satisfy(arg => arg.includes('"mimes" is missing')); + expect(utils.logWarn.getCall(1).args[0]).to.satisfy(arg => arg.includes('"placement" is missing')); + }); + + it('should not send a video request when it has an empty body and no other impressions with any media types are defined', () => { + // ASSEMBLE + const emptyVideoRequest = { + ...DEFAULT_VIDEO_BID_REQUESTS[0], + mediaTypes: { + video: {} + } + }; + const bidRequests = [ emptyVideoRequest ]; + const bidderRequest = { ...DEFAULT_VIDEO_BIDDER_REQUEST, bids: bidRequests }; + + // ACT + const request = spec.buildRequests(bidRequests, bidderRequest); + + // ASSERT + expect(utils.logError.calledOnce).to.equal(true); + expect(utils.logError.args[0][0]).to.satisfy(arg => arg.includes('No request')); + expect(request).to.be.undefined; + }); }); describe('getBidFloor', () => { it('should return floor of 0.0 if floor module not available', () => { const bid = { - ...DEFAULT_BID_REQUESTS[0], + ...DEFAULT_BANNER_BID_REQUESTS[0], getFloor: false, }; expect(getBidFloor(bid)).to.deep.eq(0.0); @@ -330,7 +516,7 @@ describe('Equativ bid adapter tests', () => { it('should return proper min floor', () => { const bid = { - ...DEFAULT_BID_REQUESTS[0], + ...DEFAULT_BANNER_BID_REQUESTS[0], getFloor: data => { if (data.size[0] === 300 && data.size[1] === 250) { return { floor: 1.13 }; @@ -346,7 +532,7 @@ describe('Equativ bid adapter tests', () => { it('should return global media type floor if no rule for size', () => { const bid = { - ...DEFAULT_BID_REQUESTS[0], + ...DEFAULT_BANNER_BID_REQUESTS[0], getFloor: data => { if (data.size[0] === 728 && data.size[1] === 90) { return { floor: 1.13 }; @@ -362,7 +548,7 @@ describe('Equativ bid adapter tests', () => { it('should return floor of 0 if no rule for size', () => { const bid = { - ...DEFAULT_BID_REQUESTS[0], + ...DEFAULT_BANNER_BID_REQUESTS[0], getFloor: data => { if (data.size[0] === 728 && data.size[1] === 90) { return { floor: 1.13 }; @@ -466,9 +652,9 @@ describe('Equativ bid adapter tests', () => { describe('interpretResponse', () => { it('should return data returned by ORTB converter', () => { const request = spec.buildRequests( - DEFAULT_BID_REQUESTS, - DEFAULT_BIDDER_REQUEST - ); + DEFAULT_BANNER_BID_REQUESTS, + DEFAULT_BANNER_BIDDER_REQUEST + )[0]; const bids = spec.interpretResponse(SAMPLE_RESPONSE, request); expect(bids).to.deep.equal( converter.fromORTB({