From 17877934b843824315c971d932fc3d4ac244eeb2 Mon Sep 17 00:00:00 2001 From: yegorWaardex <59033363+yegorWaardex@users.noreply.github.com> Date: Fri, 15 Jan 2021 12:14:27 +0200 Subject: [PATCH] Waardex Bid Adapter: Add video support, refactor code (#6149) * Add video support, refactor code * Add zoneId, refactor Co-authored-by: yegorheiz --- modules/waardexBidAdapter.js | 431 ++++++++++++-------- modules/waardexBidAdapter.md | 107 +++-- test/spec/modules/waardexBidAdapter_spec.js | 338 +++++++++++---- 3 files changed, 590 insertions(+), 286 deletions(-) diff --git a/modules/waardexBidAdapter.js b/modules/waardexBidAdapter.js index b9114d4f1bfa..a5ba4fb02984 100644 --- a/modules/waardexBidAdapter.js +++ b/modules/waardexBidAdapter.js @@ -1,217 +1,294 @@ -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER } from '../src/mediaTypes.js'; -import { config } from '../src/config.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {BANNER, VIDEO} from '../src/mediaTypes.js'; +import {config} from '../src/config.js'; +import * as utils from '../src/utils.js'; -const domain = 'hb.justbidit.xyz'; -const httpsPort = 8843; -const path = '/prebid'; +const ENDPOINT = `https://hb.justbidit.xyz:8843/prebid`; +const BIDDER_CODE = 'waardex'; -const ENDPOINT = `https://${domain}:${httpsPort}${path}`; +const isBidRequestValid = bid => { + if (!bid.bidId) { + utils.logError(BIDDER_CODE + ': bid.bidId should be non-empty'); + return false; + } -const BIDDER_CODE = 'waardex'; + if (!bid.params) { + utils.logError(BIDDER_CODE + ': bid.params should be non-empty'); + return false; + } -/** - * @param {Array} requestSizes - * - * @returns {Array} - * */ -function transformSizes(requestSizes) { - let sizes = []; - if ( - Array.isArray(requestSizes) && - !Array.isArray(requestSizes[0]) - ) { - sizes[0] = { - width: parseInt(requestSizes[0], 10) || 0, - height: parseInt(requestSizes[1], 10) || 0, - }; - } else if ( - Array.isArray(requestSizes) && - Array.isArray(requestSizes[0]) - ) { - sizes = requestSizes.map(item => { - return { - width: parseInt(item[0], 10) || 0, - height: parseInt(item[1], 10) || 0, - } - }); + if (!+bid.params.zoneId) { + utils.logError(BIDDER_CODE + ': bid.params.zoneId should be non-empty Number'); + return false; } - return sizes; -} -/** - * @param {Object} banner - * @param {Array} banner.sizes - * - * @returns {Object} - * */ -function createBannerObject(banner) { - return { - sizes: transformSizes(banner.sizes), - }; -} - -/** - * @param {Array} validBidRequests - * - * @returns {Object} - * */ -function buildBidRequests(validBidRequests) { - return validBidRequests.map((validBidRequest) => { - const params = validBidRequest.params; - - const item = { - bidId: validBidRequest.bidId, - bidfloor: parseFloat(params.bidfloor) || 0, - position: parseInt(params.position) || 1, - instl: parseInt(params.instl) || 0, - }; - if (validBidRequest.mediaTypes[BANNER]) { - item[BANNER] = createBannerObject(validBidRequest.mediaTypes[BANNER]); + if (bid.mediaTypes && bid.mediaTypes.video) { + if (!bid.mediaTypes.video.playerSize) { + utils.logError(BIDDER_CODE + ': bid.mediaTypes.video.playerSize should be non-empty'); + return false; + } + + if (!utils.isArray(bid.mediaTypes.video.playerSize)) { + utils.logError(BIDDER_CODE + ': bid.mediaTypes.video.playerSize should be an Array'); + return false; } - return item; - }); -} - -/** - * @param {Object} bidderRequest - * @param {String} bidderRequest.userAgent - * @param {String} bidderRequest.refererInfo - * @param {String} bidderRequest.uspConsent - * @param {Object} bidderRequest.gdprConsent - * @param {String} bidderRequest.gdprConsent.consentString - * @param {String} bidderRequest.gdprConsent.gdprApplies - * - * @returns {Object} - { - * ua: string, - * language: string, - * [referer]: string, - * [us_privacy]: string, - * [consent_string]: string, - * [consent_required]: string, - * [coppa]: boolean, - * } - * */ -function getCommonBidsData(bidderRequest) { + + if (!bid.mediaTypes.video.playerSize[0]) { + utils.logError(BIDDER_CODE + ': bid.mediaTypes.video.playerSize should be non-empty'); + return false; + } + + if (!utils.isArray(bid.mediaTypes.video.playerSize[0])) { + utils.logError(BIDDER_CODE + ': bid.mediaTypes.video.playerSize should be non-empty Array'); + return false; + } + } + + return true; +}; + +const buildRequests = (validBidRequests, bidderRequest) => { + const dataToSend = { + ...getCommonBidsData(bidderRequest), + bidRequests: getBidRequestsToSend(validBidRequests) + }; + + let zoneId = ''; + if (validBidRequests[0] && validBidRequests[0].params && +validBidRequests[0].params.zoneId) { + zoneId = +validBidRequests[0].params.zoneId; + } + + return {method: 'POST', url: `${ENDPOINT}?pubId=${zoneId}`, data: dataToSend}; +}; + +const getCommonBidsData = bidderRequest => { const payload = { ua: navigator.userAgent || '', language: navigator.language && navigator.language.indexOf('-') !== -1 ? navigator.language.split('-')[0] : '', - }; + if (bidderRequest && bidderRequest.refererInfo) { payload.referer = encodeURIComponent(bidderRequest.refererInfo.referer); } + if (bidderRequest && bidderRequest.uspConsent) { payload.us_privacy = bidderRequest.uspConsent; } + if (bidderRequest && bidderRequest.gdprConsent) { payload.gdpr_consent = { consent_string: bidderRequest.gdprConsent.consentString, consent_required: bidderRequest.gdprConsent.gdprApplies, } } + payload.coppa = !!config.getConfig('coppa'); return payload; -} - -/** - * this function checks either bid response is valid or noŠµ - * - * @param {Object} bid - * @param {string} bid.requestId - * @param {number} bid.cpm - * @param {string} bid.creativeId - * @param {number} bid.ttl - * @param {string} bid.currency - * @param {number} bid.width - * @param {number} bid.height - * @param {string} bid.ad - * - * @returns {boolean} - * */ -function isBidValid(bid) { - if (!bid.requestId || !bid.cpm || !bid.creativeId || !bid.ttl || !bid.currency) { - return false; +}; + +const getBidRequestsToSend = validBidRequests => { + return validBidRequests.map(getBidRequestToSend); +}; + +const getBidRequestToSend = validBidRequest => { + const result = { + bidId: validBidRequest.bidId, + bidfloor: parseFloat(validBidRequest.params.bidfloor) || 0, + position: parseInt(validBidRequest.params.position) || 1, + instl: parseInt(validBidRequest.params.instl) || 0, + }; + + if (validBidRequest.mediaTypes[BANNER]) { + result[BANNER] = createBannerObject(validBidRequest.mediaTypes[BANNER]); } - return Boolean(bid.width && bid.height && bid.ad); -} - -/** - * @param {Object} serverBid - * - * @returns {Object|null} - * */ -function createBid(serverBid) { - const bid = { - requestId: serverBid.id, - cpm: serverBid.price, + if (validBidRequest.mediaTypes[VIDEO]) { + result[VIDEO] = createVideoObject(validBidRequest.mediaTypes[VIDEO], validBidRequest.params); + } + + return result; +}; + +const createBannerObject = banner => { + return { + sizes: transformSizes(banner.sizes), + }; +}; + +const transformSizes = requestSizes => { + let result = []; + + if (Array.isArray(requestSizes) && !Array.isArray(requestSizes[0])) { + result[0] = { + width: parseInt(requestSizes[0], 10) || 0, + height: parseInt(requestSizes[1], 10) || 0, + }; + } else if (Array.isArray(requestSizes) && Array.isArray(requestSizes[0])) { + result = requestSizes.map(item => { + return { + width: parseInt(item[0], 10) || 0, + height: parseInt(item[1], 10) || 0, + } + }); + } + + return result; +}; + +const createVideoObject = (videoMediaTypes, videoParams) => { + return { + w: utils.deepAccess(videoMediaTypes, 'playerSize')[0][0], + h: utils.deepAccess(videoMediaTypes, 'playerSize')[0][1], + mimes: utils.getBidIdParameter('mimes', videoParams) || ['application/javascript', 'video/mp4', 'video/webm'], + minduration: utils.getBidIdParameter('minduration', videoParams) || 0, + maxduration: utils.getBidIdParameter('maxduration', videoParams) || 500, + protocols: utils.getBidIdParameter('protocols', videoParams) || [2, 3, 5, 6], + startdelay: utils.getBidIdParameter('startdelay', videoParams) || 0, + placement: utils.getBidIdParameter('placement', videoParams) || videoMediaTypes.context === 'outstream' ? 3 : 1, + skip: utils.getBidIdParameter('skip', videoParams) || 1, + skipafter: utils.getBidIdParameter('skipafter', videoParams) || 0, + minbitrate: utils.getBidIdParameter('minbitrate', videoParams) || 0, + maxbitrate: utils.getBidIdParameter('maxbitrate', videoParams) || 3500, + delivery: utils.getBidIdParameter('delivery', videoParams) || [2], + playbackmethod: utils.getBidIdParameter('playbackmethod', videoParams) || [1, 2, 3, 4], + api: utils.getBidIdParameter('api', videoParams) || [2], + linearity: utils.getBidIdParameter('linearity', videoParams) || 1 + }; +}; + +const interpretResponse = (serverResponse, bidRequest) => { + try { + const responseBody = serverResponse.body; + + if (!responseBody.seatbid || !responseBody.seatbid[0]) { + return []; + } + + return responseBody.seatbid[0].bid + .map(openRtbBid => { + const hbRequestBid = getHbRequestBid(openRtbBid, bidRequest.data); + if (!hbRequestBid) return; + + const hbRequestMediaType = getHbRequestMediaType(hbRequestBid); + if (!hbRequestMediaType) return; + + return mapOpenRtbToHbBid(openRtbBid, hbRequestMediaType, hbRequestBid); + }) + .filter(x => x); + } catch (e) { + return []; + } +}; + +const getHbRequestBid = (openRtbBid, bidRequest) => { + return bidRequest.bidRequests.find(x => x.bidId === openRtbBid.impid); +}; + +const getHbRequestMediaType = hbRequestBid => { + if (hbRequestBid.banner) return BANNER; + if (hbRequestBid.video) return VIDEO; + return null; +}; + +const mapOpenRtbToHbBid = (openRtbBid, mediaType, hbRequestBid) => { + let bid = null; + + if (mediaType === BANNER) { + bid = mapOpenRtbBannerToHbBid(openRtbBid, hbRequestBid); + } + + if (mediaType === VIDEO) { + bid = mapOpenRtbVideoToHbBid(openRtbBid, hbRequestBid); + } + + return isBidValid(bid) ? bid : null; +}; + +const mapOpenRtbBannerToHbBid = (openRtbBid, hbRequestBid) => { + return { + mediaType: BANNER, + requestId: hbRequestBid.bidId, + cpm: openRtbBid.price, currency: 'USD', - width: serverBid.w, - height: serverBid.h, - creativeId: serverBid.crid, + width: openRtbBid.w, + height: openRtbBid.h, + creativeId: openRtbBid.crid, netRevenue: true, ttl: 3000, - ad: serverBid.adm, - dealId: serverBid.dealid, + ad: openRtbBid.adm, + dealId: openRtbBid.dealid, meta: { - cid: serverBid.cid, - adomain: serverBid.adomain, - mediaType: serverBid.ext.mediaType + cid: openRtbBid.cid, + adomain: openRtbBid.adomain, + mediaType: openRtbBid.ext && openRtbBid.ext.mediaType }, }; +}; - return isBidValid(bid) ? bid : null; -} +const mapOpenRtbVideoToHbBid = (openRtbBid, hbRequestBid) => { + return { + mediaType: VIDEO, + requestId: hbRequestBid.bidId, + cpm: openRtbBid.price, + currency: 'USD', + width: hbRequestBid.video.w, + height: hbRequestBid.video.h, + ad: openRtbBid.adm, + ttl: 3000, + creativeId: openRtbBid.crid, + netRevenue: true, + vastUrl: getVastUrl(openRtbBid), + // An impression tracking URL to serve with video Ad + // Optional; only usable with vastUrl and requires prebid cache to be enabled + // Example: "https://vid.exmpale.com/imp/134" + // For now we don't need this field + // vastImpUrl: null, + vastXml: openRtbBid.adm, + dealId: openRtbBid.dealid, + meta: { + cid: openRtbBid.cid, + adomain: openRtbBid.adomain, + networkId: null, + networkName: null, + agencyId: null, + agencyName: null, + advertiserId: null, + advertiserName: null, + advertiserDomains: null, + brandId: null, + brandName: null, + primaryCatId: null, + secondaryCatIds: null, + mediaType: 'video', + }, + } +}; -export const spec = { - code: BIDDER_CODE, - supportedMediaTypes: [BANNER], - - isBidRequestValid: (bid) => Boolean(bid.bidId && bid.params && +bid.params.zoneId), - - /** - * @param {Object[]} validBidRequests - array of valid bid requests - * @param {Object} bidderRequest - an array of valid bid requests - * - * */ - buildRequests(validBidRequests, bidderRequest) { - const payload = getCommonBidsData(bidderRequest); - payload.bidRequests = buildBidRequests(validBidRequests); - - let zoneId = ''; - if (validBidRequests[0] && validBidRequests[0].params && +validBidRequests[0].params.zoneId) { - zoneId = +validBidRequests[0].params.zoneId; - } +const getVastUrl = openRtbBid => { + const adm = (openRtbBid.adm || '').trim(); - const url = `${ENDPOINT}?pubId=${zoneId}`; + if (adm.startsWith('http')) { + return adm; + } else { + return null + } +}; - return { - method: 'POST', - url, - data: payload - }; - }, - - /** - * Unpack the response from the server into a list of bids. - */ - interpretResponse(serverResponse, bidRequest) { - const bids = []; - serverResponse = serverResponse.body; - - if (serverResponse.seatbid && serverResponse.seatbid[0]) { - const oneSeatBid = serverResponse.seatbid[0]; - oneSeatBid.bid.forEach(serverBid => { - const bid = createBid(serverBid); - if (bid) { - bids.push(bid); - } - }); - } - return bids; - }, -} +const isBidValid = bid => { + if (!bid.requestId || !bid.cpm || !bid.creativeId || !bid.ttl || !bid.currency) { + return false; + } + + return Boolean(bid.width && bid.height && bid.ad); +}; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER, VIDEO], + isBidRequestValid, + buildRequests, + interpretResponse, +}; registerBidder(spec); diff --git a/modules/waardexBidAdapter.md b/modules/waardexBidAdapter.md index 44ee720d31a6..8eade8409f48 100644 --- a/modules/waardexBidAdapter.md +++ b/modules/waardexBidAdapter.md @@ -10,51 +10,84 @@ Maintainer: info@prebid.org Connects to Waardex exchange for bids. -Waardex bid adapter supports Banner. +Waardex bid adapter supports Banner and Video. # Test Parameters - -``` - +## Banner +```javascript var sizes = [ [300, 250] ]; var PREBID_TIMEOUT = 5000; var FAILSAFE_TIMEOUT = 5000; -var adUnits = [{ - code: '/19968336/header-bid-tag-0', - mediaTypes: { - banner: { - sizes: sizes, - }, - }, - bids: [{ - bidder: 'waardex', - params: { - placementId: 13144370, - position: 1, // add position openrtb - bidfloor: 0.5, - instl: 0, // 1 - full screen - pubId: 1, +var adUnits = [ + { + code: '/19968336/header-bid-tag-0', + mediaTypes: { + banner: { + sizes: sizes + } + }, + bids: [ + { + bidder: 'waardex', + params: { + bidfloor: 1.5, + position: 1, + instl: 1, + zoneId: 1 + } + } + ] } - }] -},{ - code: '/19968336/header-bid-tag-1', - mediaTypes: { - banner: { - sizes: sizes, +]; +``` + +## Video + +```javascript +const PREBID_TIMEOUT = 1000; +const FAILSAFE_TIMEOUT = 3000; + +const sizes = [ + [640, 480] +]; + +const adUnits = [ + { + code: 'video1', + mediaTypes: { + video: { + context: 'instream', + playerSize: sizes[0] + } }, - }, - bids: [{ - bidder: 'waardex', - params: { - placementId: 333333333333, - position: 1, // add position openrtb - bidfloor: 0.5, - instl: 0, // 1 - full screen - pubId: 1, - } - }] -}]; + bids: [ + { + bidder: 'waardex', + params: { + bidfloor: 1.5, + position: 1, + instl: 1, + zoneId: 1, + mimes: ['video/x-ms-wmv', 'video/mp4'], + minduration: 2, + maxduration: 10, + protocols: ['VAST 1.0', 'VAST 2.0'], + startdelay: -1, + placement: 1, + skip: 1, + skipafter: 2, + minbitrate: 0, + maxbitrate: 0, + delivery: [1, 2, 3], + playbackmethod: [1, 2], + api: [1, 2, 3, 4, 5, 6], + linearity: 1, + } + } + ] + } +] ``` diff --git a/test/spec/modules/waardexBidAdapter_spec.js b/test/spec/modules/waardexBidAdapter_spec.js index 8732b2bd51f5..73094dd72a01 100644 --- a/test/spec/modules/waardexBidAdapter_spec.js +++ b/test/spec/modules/waardexBidAdapter_spec.js @@ -1,51 +1,201 @@ import {expect} from 'chai'; import {spec} from '../../../modules/waardexBidAdapter.js'; -import { auctionManager } from 'src/auctionManager.js'; -import { deepClone } from 'src/utils.js'; +import {auctionManager} from 'src/auctionManager.js'; +import {deepClone} from 'src/utils.js'; describe('waardexBidAdapter', () => { - const validBid = { - bidId: '112435ry', - bidder: 'waardex', - params: { - placementId: 1, - traffic: 'banner', - zoneId: 1, - } - }; - describe('isBidRequestValid', () => { - it('Should return true. bidId and params such as placementId and zoneId are present', () => { - expect(spec.isBidRequestValid(validBid)).to.be.true; + it('should return true. bidId and params such as placementId and zoneId are present', () => { + const result = spec.isBidRequestValid({ + bidId: '112435ry', + bidder: 'waardex', + params: { + placementId: 1, + traffic: 'banner', + zoneId: 1, + } + }); + + expect(result).to.be.true; + }); + + it('should return false. bidId is not present in bid object', () => { + const result = spec.isBidRequestValid({ + bidder: 'waardex', + params: { + placementId: 1, + traffic: 'banner', + zoneId: 1, + } + }); + + expect(result).to.be.false; + }); + + it('should return false. zoneId is not present in bid.params object', () => { + const result = spec.isBidRequestValid({ + bidId: '112435ry', + bidder: 'waardex', + params: { + placementId: 1, + traffic: 'banner', + } + }); + + expect(result).to.be.false; + }); + + it('should return true when mediaTypes field is empty', () => { + const result = spec.isBidRequestValid({ + bidId: '112435ry', + bidder: 'waardex', + params: { + placementId: 1, + traffic: 'banner', + zoneId: 1, + } + }); + + expect(result).to.be.true; }); - it('Should return false. bidId is not present in bid object', () => { - const invalidBid = deepClone(validBid); - delete invalidBid.bidId; - expect(spec.isBidRequestValid(invalidBid)).to.be.false; + + it('should return false when mediaTypes.video.playerSize field is empty', () => { + const result = spec.isBidRequestValid({ + bidId: '112435ry', + bidder: 'waardex', + params: { + placementId: 1, + traffic: 'banner', + zoneId: 1, + }, + mediaTypes: { + video: {} + } + }); + + expect(result).to.be.false; }); - it('Should return false. zoneId is not present in bid.params object', () => { - const invalidBid = deepClone(validBid); - delete invalidBid.params.zoneId; - expect(spec.isBidRequestValid(invalidBid)).to.be.false; + + it('should return false when mediaTypes.video.playerSize field is not an array', () => { + const result = spec.isBidRequestValid({ + bidId: '112435ry', + bidder: 'waardex', + params: { + placementId: 1, + traffic: 'banner', + zoneId: 1, + }, + mediaTypes: { + video: { + playerSize: 'not-array' + } + } + }); + + expect(result).to.be.false; + }); + + it('should return false when mediaTypes.video.playerSize field is an empty array', () => { + const result = spec.isBidRequestValid({ + bidId: '112435ry', + bidder: 'waardex', + params: { + placementId: 1, + traffic: 'banner', + zoneId: 1, + }, + mediaTypes: { + video: { + playerSize: [] + } + } + }); + + expect(result).to.be.false; + }); + + it('should return false when mediaTypes.video.playerSize field is empty array', () => { + const result = spec.isBidRequestValid({ + bidId: '112435ry', + bidder: 'waardex', + params: { + placementId: 1, + traffic: 'banner', + zoneId: 1, + }, + mediaTypes: { + video: { + playerSize: [] + } + } + }); + + expect(result).to.be.false; + }); + + it('should return true when mediaTypes.video.playerSize field is non-empty array', () => { + const result = spec.isBidRequestValid({ + bidId: '112435ry', + bidder: 'waardex', + params: { + placementId: 1, + traffic: 'banner', + zoneId: 1, + }, + mediaTypes: { + video: { + playerSize: [[640, 400]] + } + } + }); + + expect(result).to.be.true; }); }); describe('buildRequests', () => { let getAdUnitsStub; - const validBidRequests = [{ - bidId: 'fergr675ujgh', - mediaTypes: { - banner: { - sizes: [[300, 600], [300, 250]] - } - }, - params: { - bidfloor: 1.5, - position: 1, - instl: 1, - zoneId: 100 + const validBidRequests = [ + { + bidId: 'fergr675ujgh', + mediaTypes: { + banner: { + sizes: [[300, 600], [300, 250]] + } + }, + params: { + bidfloor: 1.5, + position: 1, + instl: 1, + zoneId: 100 + }, }, - }]; + { + bidId: 'unique-bid-id-2', + mediaTypes: { + video: { + context: 'outstream', + playerSize: [[640, 400]] + } + }, + params: { + mimes: ['video/x-ms-wmv', 'video/mp4'], + minduration: 2, + maxduration: 10, + protocols: ['VAST 1.0', 'VAST 2.0'], + startdelay: -1, + placement: 1, + skip: 1, + skipafter: 2, + minbitrate: 0, + maxbitrate: 0, + delivery: [1, 2, 3], + playbackmethod: [1, 2], + api: [1, 2, 3, 4, 5, 6], + linearity: 1, + } + } + ]; const bidderRequest = { refererInfo: { @@ -57,12 +207,13 @@ describe('waardexBidAdapter', () => { afterEach(() => getAdUnitsStub.restore()); it('should return valid build request object', () => { - const request = spec.buildRequests(validBidRequests, bidderRequest); const { data: payload, url, method, - } = request; + } = spec.buildRequests(validBidRequests, bidderRequest); + + const ENDPOINT = `https://hb.justbidit.xyz:8843/prebid?pubId=${validBidRequests[0].params.zoneId}`; expect(payload.bidRequests[0]).deep.equal({ bidId: validBidRequests[0].bidId, @@ -82,7 +233,6 @@ describe('waardexBidAdapter', () => { ], } }); - const ENDPOINT = `https://hb.justbidit.xyz:8843/prebid?pubId=${validBidRequests[0].params.zoneId}`; expect(url).to.equal(ENDPOINT); expect(method).to.equal('POST'); }); @@ -91,44 +241,88 @@ describe('waardexBidAdapter', () => { describe('interpretResponse', () => { const serverResponse = { body: { - seatbid: [{ - bid: [{ - id: 'someId', - price: 3.3, - w: 250, - h: 300, - crid: 'dspCreativeIdHere', - adm: 'html markup here', - dealId: '123456789', - cid: 'dsp campaign id', - adomain: 'advertisers domain', - ext: { - mediaType: 'banner', - }, - }], - }], + seatbid: [ + { + bid: [ + { + 'id': 'ec90d4ee25433c0875c56f59acc12109', + 'adm': 'banner should be here', + 'w': 300, + 'h': 250, + 'price': 0.15827000000000002, + 'nurl': 'http://n63.justbidit.xyz?w=n&p=${AUCTION_PRICE}&t=b&uq=eb31018b3da8965dde414c0006b1fb31', + 'impid': 'unique-bid-id-1', + 'adomain': [ + 'www.kraeuterhaus.de' + ], + 'cat': [ + 'IAB24' + ], + 'attr': [ + 4 + ], + 'iurl': 'https://rtb.bsmartdata.com/preview.php?id=13', + 'cid': '286557fda4585dc1c7f98b773de92509', + 'crid': 'dd2b5a1f3f1fc5e63b042ebf4b00ca80' + }, + ], + } + ], }, }; + const request = { + 'ua': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/86.0.4240.198 Safari/537.36', + 'language': 'en', + 'referer': 'https%3A%2F%2Fwww.google.com%2F%3Fsome_param%3Dsome_value', + 'coppa': false, + 'data': { + 'bidRequests': [ + { + 'bidId': 'unique-bid-id-1', + 'bidfloor': 0.1, + 'position': 1, + 'instl': 1, + 'banner': { + 'sizes': [ + { + 'width': 300, + 'height': 600 + }, + { + 'width': 300, + 'height': 250 + } + ] + } + }, + ] + } + }; + it('bid response is valid', () => { - const result = spec.interpretResponse(serverResponse); - const expected = [{ - requestId: serverResponse.body.seatbid[0].bid[0].id, - cpm: serverResponse.body.seatbid[0].bid[0].price, - currency: 'USD', - width: serverResponse.body.seatbid[0].bid[0].w, - height: serverResponse.body.seatbid[0].bid[0].h, - creativeId: serverResponse.body.seatbid[0].bid[0].crid, - netRevenue: true, - ttl: 3000, - ad: serverResponse.body.seatbid[0].bid[0].adm, - dealId: serverResponse.body.seatbid[0].bid[0].dealid, - meta: { - cid: serverResponse.body.seatbid[0].bid[0].cid, - adomain: serverResponse.body.seatbid[0].bid[0].adomain, - mediaType: serverResponse.body.seatbid[0].bid[0].ext.mediaType, - }, - }]; + const result = spec.interpretResponse(serverResponse, request); + + const expected = [ + { + requestId: 'unique-bid-id-1', + cpm: serverResponse.body.seatbid[0].bid[0].price, + currency: 'USD', + width: serverResponse.body.seatbid[0].bid[0].w, + height: serverResponse.body.seatbid[0].bid[0].h, + mediaType: 'banner', + creativeId: serverResponse.body.seatbid[0].bid[0].crid, + netRevenue: true, + ttl: 3000, + ad: serverResponse.body.seatbid[0].bid[0].adm, + dealId: serverResponse.body.seatbid[0].bid[0].dealid, + meta: { + cid: serverResponse.body.seatbid[0].bid[0].cid, + adomain: serverResponse.body.seatbid[0].bid[0].adomain, + mediaType: (serverResponse.body.seatbid[0].bid[0].ext || {}).mediaType, + }, + } + ]; expect(result).deep.equal(expected); });