diff --git a/modules/invibesBidAdapter.js b/modules/invibesBidAdapter.js index 75da1509f19..d715ecf6663 100644 --- a/modules/invibesBidAdapter.js +++ b/modules/invibesBidAdapter.js @@ -77,12 +77,14 @@ function isBidRequestValid(bid) { function buildRequest(bidRequests, bidderRequest) { bidderRequest = bidderRequest || {}; const _placementIds = []; + const _adUnitCodes = []; let _loginId, _customEndpoint, _userId; let _ivAuctionStart = bidderRequest.auctionStart || Date.now(); bidRequests.forEach(function (bidRequest) { bidRequest.startTime = new Date().getTime(); _placementIds.push(bidRequest.params.placementId); + _adUnitCodes.push(bidRequest.adUnitCode); _loginId = _loginId || bidRequest.params.loginId; _customEndpoint = _customEndpoint || bidRequest.params.customEndpoint; _customUserSync = _customUserSync || bidRequest.params.customUserSync; @@ -99,6 +101,7 @@ function buildRequest(bidRequests, bidderRequest) { let userIdModel = getUserIds(_userId); let bidParamsJson = { placementIds: _placementIds, + adUnitCodes: _adUnitCodes, loginId: _loginId, auctionStartTime: _ivAuctionStart, bidVersion: CONSTANTS.PREBID_VERSION @@ -181,9 +184,12 @@ function handleResponse(responseObj, bidRequests) { const bidResponses = []; for (let i = 0; i < bidRequests.length; i++) { let bidRequest = bidRequests[i]; + let usedPlacementId = responseObj.UseAdUnitCode === true + ? bidRequest.params.placementId + '_' + bidRequest.adUnitCode + : bidRequest.params.placementId; - if (invibes.placementBids.indexOf(bidRequest.params.placementId) > -1) { - logInfo('Invibes Adapter - Placement was previously bid on ' + bidRequest.params.placementId); + if (invibes.placementBids.indexOf(usedPlacementId) > -1) { + logInfo('Invibes Adapter - Placement was previously bid on ' + usedPlacementId); continue; } @@ -191,21 +197,21 @@ function handleResponse(responseObj, bidRequests) { if (responseObj.AdPlacements != null) { for (let j = 0; j < responseObj.AdPlacements.length; j++) { let bidModel = responseObj.AdPlacements[j].BidModel; - if (bidModel != null && bidModel.PlacementId == bidRequest.params.placementId) { + if (bidModel != null && bidModel.PlacementId == usedPlacementId) { requestPlacement = responseObj.AdPlacements[j]; break; } } } else { let bidModel = responseObj.BidModel; - if (bidModel != null && bidModel.PlacementId == bidRequest.params.placementId) { + if (bidModel != null && bidModel.PlacementId == usedPlacementId) { requestPlacement = responseObj; } } - let bid = createBid(bidRequest, requestPlacement, responseObj.MultipositionEnabled); + let bid = createBid(bidRequest, requestPlacement, responseObj.MultipositionEnabled, usedPlacementId); if (bid !== null) { - invibes.placementBids.push(bidRequest.params.placementId); + invibes.placementBids.push(usedPlacementId); bidResponses.push(bid); } } @@ -213,9 +219,9 @@ function handleResponse(responseObj, bidRequests) { return bidResponses; } -function createBid(bidRequest, requestPlacement, multipositionEnabled) { +function createBid(bidRequest, requestPlacement, multipositionEnabled, usedPlacementId) { if (requestPlacement === null || requestPlacement.BidModel === null) { - logInfo('Invibes Adapter - Placement not configured for bidding ' + bidRequest.params.placementId); + logInfo('Invibes Adapter - Placement not configured for bidding ' + usedPlacementId); return null; } @@ -684,7 +690,7 @@ let keywords = (function () { return kw; }()); -// ===================== +// ====================== export function resetInvibes() { invibes.optIn = undefined; diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 74b7b39b0da..366a0326054 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -867,10 +867,10 @@ function _handleEids(payload, validBidRequests) { function _checkMediaType(bid, newBid) { // Create a regex here to check the strings - if (bid.ext && bid.ext['BidType'] != undefined) { - newBid.mediaType = MEDIATYPE[bid.ext.BidType]; + if (bid.ext && bid.ext['bidtype'] != undefined) { + newBid.mediaType = MEDIATYPE[bid.ext.bidtype]; } else { - logInfo(LOG_WARN_PREFIX + 'bid.ext.BidType does not exist, checking alternatively for mediaType') + logInfo(LOG_WARN_PREFIX + 'bid.ext.bidtype does not exist, checking alternatively for mediaType') var adm = bid.adm; var admStr = ''; var videoRegex = new RegExp(/VAST\s+version/); diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index da63331cd0f..00c962445d9 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -161,11 +161,20 @@ export const spec = { domain: domain, publisher: { id: publisherId + }, + content: { + ext: { + prebid: { + name: 'pbjs', + version: '$prebid.version$' + } + } } }, device: device, at: at, - cur: cur + cur: cur, + ext: {} }; const userExt = {}; @@ -194,6 +203,8 @@ export const spec = { }; } + // requestPayload.user.ext.ver = pbjs.version; + // Targeting if (getBidIdParameter('data', bid.params.user)) { var targetingarr = []; @@ -336,6 +347,7 @@ function createOutstreamConfig(bid) { let confTitle = getBidIdParameter('title', bid.renderer.config.outstream_options); let confSkipOffset = getBidIdParameter('skipOffset', bid.renderer.config.outstream_options); let confDesiredBitrate = getBidIdParameter('desiredBitrate', bid.renderer.config.outstream_options); + let confVisibilityThreshold = getBidIdParameter('visibilityThreshold', bid.renderer.config.outstream_options); let elementId = getBidIdParameter('slot', bid.renderer.config.outstream_options) || bid.adUnitCode; logMessage('[SMARTX][renderer] Handle SmartX outstream renderer'); @@ -384,6 +396,10 @@ function createOutstreamConfig(bid) { smartPlayObj.desiredBitrate = confDesiredBitrate; } + if (confVisibilityThreshold) { + smartPlayObj.visibilityThreshold = confVisibilityThreshold; + } + smartPlayObj.adResponse = bid.vastContent; const divID = '[id="' + elementId + '"]'; diff --git a/modules/undertoneBidAdapter.js b/modules/undertoneBidAdapter.js index d9c9f84e050..fda6f47b2af 100644 --- a/modules/undertoneBidAdapter.js +++ b/modules/undertoneBidAdapter.js @@ -98,9 +98,16 @@ export const spec = { 'commons': commons }; const referer = bidderRequest.refererInfo.referer; + const canonicalUrl = getCanonicalUrl(); + if (referer) { + commons.referrer = referer; + } + if (canonicalUrl) { + commons.canonicalUrl = canonicalUrl; + } const hostname = parseUrl(referer).hostname; let domain = extractDomainFromHost(hostname); - const pageUrl = getCanonicalUrl() || referer; + const pageUrl = canonicalUrl || referer; const pubid = validBidRequests[0].params.publisherId; let reqUrl = `${URL}?pid=${pubid}&domain=${domain}`; diff --git a/modules/yieldoneBidAdapter.js b/modules/yieldoneBidAdapter.js index b12f314da2e..fe5a63cab51 100644 --- a/modules/yieldoneBidAdapter.js +++ b/modules/yieldoneBidAdapter.js @@ -1,4 +1,4 @@ -import { deepAccess, isEmpty, parseSizesInput, isStr, logWarn } from '../src/utils.js'; +import {deepAccess, isEmpty, isStr, logWarn, parseSizesInput} from '../src/utils.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import { Renderer } from '../src/Renderer.js'; @@ -11,6 +11,8 @@ const VIDEO_PLAYER_URL = 'https://img.ak.impact-ad.jp/ic/pone/ivt/firstview/js/d const CMER_PLAYER_URL = 'https://an.cmertv.com/hb/renderer/cmertv-video-yone-prebid.min.js'; const VIEWABLE_PERCENTAGE_URL = 'https://img.ak.impact-ad.jp/ic/pone/ivt/firstview/js/prebid-adformat-config.js'; +const DEFAULT_VIDEO_SIZE = {w: 640, h: 360}; + export const spec = { code: BIDDER_CODE, aliases: ['y1'], @@ -40,16 +42,18 @@ export const spec = { t: 'i' }; - const videoMediaType = deepAccess(bidRequest, 'mediaTypes.video'); - if ((isEmpty(bidRequest.mediaType) && isEmpty(bidRequest.mediaTypes)) || - (bidRequest.mediaType === BANNER || (bidRequest.mediaTypes && bidRequest.mediaTypes[BANNER]))) { - const sizes = deepAccess(bidRequest, 'mediaTypes.banner.sizes') || bidRequest.sizes; - payload.sz = parseSizesInput(sizes).join(','); - } else if (bidRequest.mediaType === VIDEO || videoMediaType) { - const sizes = deepAccess(bidRequest, 'mediaTypes.video.playerSize') || bidRequest.sizes; - const size = parseSizesInput(sizes)[0]; - payload.w = size.split('x')[0]; - payload.h = size.split('x')[1]; + const mediaType = getMediaType(bidRequest); + switch (mediaType) { + case BANNER: + payload.sz = getBannerSizes(bidRequest); + break; + case VIDEO: + const videoSize = getVideoSize(bidRequest); + payload.w = videoSize.w; + payload.h = videoSize.h; + break; + default: + break; } // LiveRampID @@ -167,6 +171,106 @@ export const spec = { }, } +/** + * NOTE: server side does not yet support multiple formats. + * @param {Object} bidRequest - + * @param {boolean} [enabledOldFormat = true] - default: `true`. + * @return {string|null} - `"banner"` or `"video"` or `null`. + */ +function getMediaType(bidRequest, enabledOldFormat = true) { + let hasBannerType = Boolean(deepAccess(bidRequest, 'mediaTypes.banner')); + let hasVideoType = Boolean(deepAccess(bidRequest, 'mediaTypes.video')); + + if (enabledOldFormat) { + hasBannerType = hasBannerType || bidRequest.mediaType === BANNER || + (isEmpty(bidRequest.mediaTypes) && isEmpty(bidRequest.mediaType)); + hasVideoType = hasVideoType || bidRequest.mediaType === VIDEO; + } + + if (hasBannerType && hasVideoType) { + const playerParams = deepAccess(bidRequest, 'params.playerParams') + if (playerParams) { + return VIDEO; + } else { + return BANNER; + } + } else if (hasBannerType) { + return BANNER; + } else if (hasVideoType) { + return VIDEO; + } + + return null; +} + +/** + * NOTE: + * If `mediaTypes.banner` exists, then `mediaTypes.banner.sizes` must also exist. + * The reason for this is that Prebid.js will perform the verification and + * if `mediaTypes.banner.sizes` is inappropriate, it will delete the entire `mediaTypes.banner`. + * @param {Object} bidRequest - + * @param {Object} bidRequest.banner - + * @param {Array} bidRequest.banner.sizes - + * @param {boolean} [enabledOldFormat = true] - default: `true`. + * @return {string} - strings like `"300x250"` or `"300x250,728x90"`. + */ +function getBannerSizes(bidRequest, enabledOldFormat = true) { + let sizes = deepAccess(bidRequest, 'mediaTypes.banner.sizes'); + + if (enabledOldFormat) { + sizes = sizes || bidRequest.sizes; + } + + return parseSizesInput(sizes).join(','); +} + +/** + * @param {Object} bidRequest - + * @param {boolean} [enabledOldFormat = true] - default: `true`. + * @param {boolean} [enabledFlux = true] - default: `true`. + * @return {{w: number, h: number}} - + */ +function getVideoSize(bidRequest, enabledOldFormat = true, enabledFlux = true) { + /** + * @param {Array | Array>} sizes - + * @return {{w: number, h: number} | null} - + */ + const _getPlayerSize = (sizes) => { + let result = null; + + const size = parseSizesInput(sizes)[0]; + if (isEmpty(size)) { + return result; + } + + const splited = size.split('x'); + const sizeObj = {w: parseInt(splited[0], 10), h: parseInt(splited[1], 10)}; + const _isValidPlayerSize = !(isEmpty(sizeObj)) && (isFinite(sizeObj.w) && isFinite(sizeObj.h)); + if (!_isValidPlayerSize) { + return result; + } + + result = sizeObj; + return result; + } + + let playerSize = _getPlayerSize(deepAccess(bidRequest, 'mediaTypes.video.playerSize')); + + if (enabledOldFormat) { + playerSize = playerSize || _getPlayerSize(bidRequest.sizes); + } + + if (enabledFlux) { + // NOTE: `video.playerSize` in Flux is always [1,1]. + if (playerSize && (playerSize.w === 1 && playerSize.h === 1)) { + // NOTE: `params.playerSize` is a specific object to support `FLUX`. + playerSize = _getPlayerSize(deepAccess(bidRequest, 'params.playerSize')); + } + } + + return playerSize || DEFAULT_VIDEO_SIZE; +} + function newRenderer(response) { const renderer = Renderer.install({ id: response.uid, diff --git a/test/spec/modules/invibesBidAdapter_spec.js b/test/spec/modules/invibesBidAdapter_spec.js index 8b92e0ee81b..a61c4fa5267 100644 --- a/test/spec/modules/invibesBidAdapter_spec.js +++ b/test/spec/modules/invibesBidAdapter_spec.js @@ -15,7 +15,7 @@ describe('invibesBidAdapter:', function () { params: { placementId: PLACEMENT_ID }, - adUnitCode: 'test-div', + adUnitCode: 'test-div1', auctionId: 'a1', sizes: [ [300, 250], @@ -30,7 +30,7 @@ describe('invibesBidAdapter:', function () { params: { placementId: 'abcde' }, - adUnitCode: 'test-div', + adUnitCode: 'test-div2', auctionId: 'a2', sizes: [ [300, 250], @@ -48,7 +48,7 @@ describe('invibesBidAdapter:', function () { params: { placementId: PLACEMENT_ID }, - adUnitCode: 'test-div', + adUnitCode: 'test-div1', auctionId: 'a1', sizes: [ [300, 250], @@ -67,7 +67,7 @@ describe('invibesBidAdapter:', function () { params: { placementId: 'abcde' }, - adUnitCode: 'test-div', + adUnitCode: 'test-div2', auctionId: 'a2', sizes: [ [300, 250], @@ -223,6 +223,12 @@ describe('invibesBidAdapter:', function () { expect(JSON.parse(request.data.bidParamsJson).placementIds).to.contain(bidRequests[1].params.placementId); }); + it('sends all adUnitCodes', function () { + const request = spec.buildRequests(bidRequests); + expect(JSON.parse(request.data.bidParamsJson).adUnitCodes).to.contain(bidRequests[0].adUnitCode); + expect(JSON.parse(request.data.bidParamsJson).adUnitCodes).to.contain(bidRequests[1].adUnitCode); + }); + it('sends all Placement Ids and userId', function () { const request = spec.buildRequests(bidRequestsWithUserId); expect(JSON.parse(request.data.bidParamsJson).userId).to.exist; @@ -823,6 +829,20 @@ describe('invibesBidAdapter:', function () { } }; + let responseWithAdUnit = { + Ads: [{ + BidPrice: 0.5, + VideoExposedId: 123 + }], + BidModel: { + BidVersion: 1, + PlacementId: '12345_test-div1', + AuctionStartTime: Date.now(), + CreativeHtml: '' + }, + UseAdUnitCode: true + }; + var buildResponse = function(placementId, cid, blcids, creativeId) { return { MultipositionEnabled: true, @@ -911,6 +931,11 @@ describe('invibesBidAdapter:', function () { let secondResult = spec.interpretResponse({body: response}, {bidRequests}); expect(secondResult).to.be.empty; }); + + it('bids using the adUnitCode', function () { + let result = spec.interpretResponse({body: responseWithAdUnit}, {bidRequests}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); }); context('when the response has meta', function () { diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 8905dfa5924..9696501437b 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -3457,7 +3457,7 @@ describe('PubMatic adapter', function () { 'h': 0, 'dealId': 'ASEA-MS-KLY-TTD-DESKTOP-ID-VID-6S-030420', 'ext': { - 'BidType': 1 + 'bidtype': 1 } }], 'ext': { diff --git a/test/spec/modules/smartxBidAdapter_spec.js b/test/spec/modules/smartxBidAdapter_spec.js index 4e560c87df3..ddee2fa3347 100644 --- a/test/spec/modules/smartxBidAdapter_spec.js +++ b/test/spec/modules/smartxBidAdapter_spec.js @@ -189,6 +189,14 @@ describe('The smartx adapter', function () { domain: '', publisher: { id: '__name__' + }, + content: { + ext: { + prebid: { + name: 'pbjs', + version: '$prebid.version$' + } + } } }); }); @@ -525,6 +533,7 @@ describe('The smartx adapter', function () { bidderRequestObj.bidRequest.bids[0].params.outstream_options.title = 'abc'; bidderRequestObj.bidRequest.bids[0].params.outstream_options.skipOffset = 2; bidderRequestObj.bidRequest.bids[0].params.outstream_options.desiredBitrate = 123; + bidderRequestObj.bidRequest.bids[0].params.outstream_options.visibilityThreshold = 30; responses[0].renderer.render(responses[0]); diff --git a/test/spec/modules/yieldoneBidAdapter_spec.js b/test/spec/modules/yieldoneBidAdapter_spec.js index 4186c5da41a..1b38bb94a8c 100644 --- a/test/spec/modules/yieldoneBidAdapter_spec.js +++ b/test/spec/modules/yieldoneBidAdapter_spec.js @@ -7,6 +7,8 @@ const ENDPOINT = 'https://y.one.impact-ad.jp/h_bid'; const USER_SYNC_URL = 'https://y.one.impact-ad.jp/push_sync'; const VIDEO_PLAYER_URL = 'https://img.ak.impact-ad.jp/ic/pone/ivt/firstview/js/dac-video-prebid.min.js'; +const DEFAULT_VIDEO_SIZE = {w: 640, h: 360}; + describe('yieldoneBidAdapter', function() { const adapter = newBidder(spec); @@ -40,32 +42,7 @@ describe('yieldoneBidAdapter', function() { }); describe('buildRequests', function () { - let bidRequests = [ - { - 'bidder': 'yieldone', - 'params': { - placementId: '36891' - }, - 'adUnitCode': 'adunit-code1', - 'sizes': [[300, 250], [336, 280]], - 'bidId': '23beaa6af6cdde', - 'bidderRequestId': '19c0c1efdf37e7', - 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', - }, - { - 'bidder': 'yieldone', - 'params': { - placementId: '47919' - }, - 'adUnitCode': 'adunit-code2', - 'sizes': [[300, 250]], - 'bidId': '382091349b149f"', - 'bidderRequestId': '"1f9c98192de251"', - 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', - } - ]; - - let bidderRequest = { + const bidderRequest = { refererInfo: { numIframes: 0, reachedTop: true, @@ -74,49 +51,318 @@ describe('yieldoneBidAdapter', function() { } }; - const request = spec.buildRequests(bidRequests, bidderRequest); + describe('Basic', function () { + const bidRequests = [ + { + 'bidder': 'yieldone', + 'params': {placementId: '36891'}, + 'adUnitCode': 'adunit-code1', + 'bidId': '23beaa6af6cdde', + 'bidderRequestId': '19c0c1efdf37e7', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + }, + { + 'bidder': 'yieldone', + 'params': {placementId: '47919'}, + 'adUnitCode': 'adunit-code2', + 'bidId': '382091349b149f"', + 'bidderRequestId': '"1f9c98192de251"', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + } + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); - it('sends bid request to our endpoint via GET', function () { - expect(request[0].method).to.equal('GET'); - expect(request[1].method).to.equal('GET'); + it('sends bid request to our endpoint via GET', function () { + expect(request[0].method).to.equal('GET'); + expect(request[1].method).to.equal('GET'); + }); + it('attaches source and version to endpoint URL as query params', function () { + expect(request[0].url).to.equal(ENDPOINT); + expect(request[1].url).to.equal(ENDPOINT); + }); + it('adUnitCode should be sent as uc parameters on any requests', function () { + expect(request[0].data.uc).to.equal('adunit-code1'); + expect(request[1].data.uc).to.equal('adunit-code2'); + }); }); - it('attaches source and version to endpoint URL as query params', function () { - expect(request[0].url).to.equal(ENDPOINT); - expect(request[1].url).to.equal(ENDPOINT); - }); + describe('Old Format', function () { + const bidRequests = [ + { + params: {placementId: '0'}, + mediaType: 'banner', + sizes: [[300, 250], [336, 280]], + }, + { + params: {placementId: '1'}, + mediaType: 'banner', + sizes: [[336, 280]], + }, + { + // It doesn't actually exist. + params: {placementId: '2'}, + }, + { + params: {placementId: '3'}, + mediaType: 'video', + sizes: [[1280, 720], [1920, 1080]], + }, + { + params: {placementId: '4'}, + mediaType: 'video', + sizes: [[1920, 1080]], + }, + { + params: {placementId: '5'}, + mediaType: 'video', + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); - it('parameter sz has more than one size on banner requests', function () { - expect(request[0].data.sz).to.equal('300x250,336x280'); - expect(request[1].data.sz).to.equal('300x250'); + it('parameter sz has more than one size on banner requests', function () { + expect(request[0].data.sz).to.equal('300x250,336x280'); + expect(request[1].data.sz).to.equal('336x280'); + expect(request[2].data.sz).to.equal(''); + expect(request[3].data).to.not.have.property('sz'); + expect(request[4].data).to.not.have.property('sz'); + expect(request[5].data).to.not.have.property('sz'); + }); + + it('width and height should be set as separate parameters on outstream requests', function () { + expect(request[0].data).to.not.have.property('w'); + expect(request[1].data).to.not.have.property('w'); + expect(request[2].data).to.not.have.property('w'); + expect(request[3].data.w).to.equal(1280); + expect(request[3].data.h).to.equal(720); + expect(request[4].data.w).to.equal(1920); + expect(request[4].data.h).to.equal(1080); + expect(request[5].data.w).to.equal(DEFAULT_VIDEO_SIZE.w); + expect(request[5].data.h).to.equal(DEFAULT_VIDEO_SIZE.h); + }); }); - it('width and height should be set as separate parameters on outstream requests', function () { - const bidRequest = Object.assign({}, bidRequests[0]); - bidRequest.mediaTypes = {}; - bidRequest.mediaTypes.video = {context: 'outstream'}; - const request = spec.buildRequests([bidRequest], bidderRequest); - expect(request[0].data.w).to.equal('300'); - expect(request[0].data.h).to.equal('250'); + describe('New Format', function () { + const bidRequests = [ + { + params: {placementId: '0'}, + mediaTypes: { + banner: { + sizes: [[300, 250], [336, 280]], + }, + }, + }, + { + params: {placementId: '1'}, + mediaTypes: { + banner: { + sizes: [[336, 280]], + }, + }, + }, + { + // It doesn't actually exist. + params: {placementId: '2'}, + mediaTypes: { + banner: { + }, + }, + }, + { + params: {placementId: '3'}, + mediaTypes: { + video: { + context: 'outstream', + playerSize: [[1280, 720], [1920, 1080]], + }, + }, + }, + { + params: {placementId: '4'}, + mediaTypes: { + video: { + context: 'outstream', + playerSize: [1920, 1080], + }, + }, + }, + { + params: {placementId: '5'}, + mediaTypes: { + video: { + context: 'outstream', + }, + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + + it('parameter sz has more than one size on banner requests', function () { + expect(request[0].data.sz).to.equal('300x250,336x280'); + expect(request[1].data.sz).to.equal('336x280'); + expect(request[2].data.sz).to.equal(''); + expect(request[3].data).to.not.have.property('sz'); + expect(request[4].data).to.not.have.property('sz'); + expect(request[5].data).to.not.have.property('sz'); + }); + + it('width and height should be set as separate parameters on outstream requests', function () { + expect(request[0].data).to.not.have.property('w'); + expect(request[1].data).to.not.have.property('w'); + expect(request[2].data).to.not.have.property('w'); + expect(request[3].data.w).to.equal(1280); + expect(request[3].data.h).to.equal(720); + expect(request[4].data.w).to.equal(1920); + expect(request[4].data.h).to.equal(1080); + expect(request[5].data.w).to.equal(DEFAULT_VIDEO_SIZE.w); + expect(request[5].data.h).to.equal(DEFAULT_VIDEO_SIZE.h); + }); }); - it('adUnitCode should be sent as uc parameters on any requests', function () { - expect(request[0].data.uc).to.equal('adunit-code1'); - expect(request[1].data.uc).to.equal('adunit-code2'); + describe('Multiple Format', function () { + const bidRequests = [ + { + // It will be treated as a banner. + params: { + placementId: '0', + }, + mediaTypes: { + banner: { + sizes: [[300, 250], [336, 280]], + }, + video: { + context: 'outstream', + playerSize: [1920, 1080], + }, + }, + }, + { + // It will be treated as a video. + params: { + placementId: '1', + playerParams: {}, + }, + mediaTypes: { + banner: { + sizes: [[300, 250], [336, 280]], + }, + video: { + context: 'outstream', + playerSize: [1920, 1080], + }, + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + + it('parameter sz has more than one size on banner requests', function () { + expect(request[0].data.sz).to.equal('300x250,336x280'); + expect(request[1].data).to.not.have.property('sz'); + }); + + it('width and height should be set as separate parameters on outstream requests', function () { + expect(request[0].data).to.not.have.property('w'); + expect(request[1].data.w).to.equal(1920); + expect(request[1].data.h).to.equal(1080); + }); }); - describe('userid idl_env should be passed to querystring', function () { - const bid = deepClone([bidRequests[0]]); + describe('FLUX Format', function () { + const bidRequests = [ + { + // It will be treated as a banner. + params: { + placementId: '0', + }, + mediaTypes: { + banner: { + sizes: [[300, 250], [336, 280]], + }, + video: { + context: 'outstream', + playerSize: [[1, 1]], + }, + }, + }, + { + // It will be treated as a video. + params: { + placementId: '1', + playerParams: {}, + playerSize: [1920, 1080], + }, + mediaTypes: { + banner: { + sizes: [[300, 250], [336, 280]], + }, + video: { + context: 'outstream', + playerSize: [[1, 1]], + }, + }, + }, + { + // It will be treated as a video. + params: { + placementId: '2', + playerParams: {}, + }, + mediaTypes: { + banner: { + sizes: [[300, 250], [336, 280]], + }, + video: { + context: 'outstream', + playerSize: [[1, 1]], + }, + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + + it('parameter sz has more than one size on banner requests', function () { + expect(request[0].data.sz).to.equal('300x250,336x280'); + expect(request[1].data).to.not.have.property('sz'); + expect(request[2].data).to.not.have.property('sz'); + }); + + it('width and height should be set as separate parameters on outstream requests', function () { + expect(request[0].data).to.not.have.property('w'); + expect(request[1].data.w).to.equal(1920); + expect(request[1].data.h).to.equal(1080); + expect(request[2].data.w).to.equal(DEFAULT_VIDEO_SIZE.w); + expect(request[2].data.h).to.equal(DEFAULT_VIDEO_SIZE.h); + }); + }); + describe('LiveRampID', function () { it('dont send LiveRampID if undefined', function () { - bid[0].userId = {}; - const request = spec.buildRequests(bid, bidderRequest); + const bidRequests = [ + { + params: {placementId: '0'}, + }, + { + params: {placementId: '1'}, + userId: {}, + }, + { + params: {placementId: '2'}, + userId: undefined, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); expect(request[0].data).to.not.have.property('lr_env'); + expect(request[1].data).to.not.have.property('lr_env'); + expect(request[2].data).to.not.have.property('lr_env'); }); it('should send LiveRampID if available', function () { - bid[0].userId = {idl_env: 'idl_env_sample'}; - const request = spec.buildRequests(bid, bidderRequest); + const bidRequests = [ + { + params: {placementId: '0'}, + userId: {idl_env: 'idl_env_sample'}, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); expect(request[0].data.lr_env).to.equal('idl_env_sample'); }); });