From 0d010d4dc3a0caa229013c10d609e1b5bb36fdce Mon Sep 17 00:00:00 2001 From: Mikhail Kuryshev Date: Fri, 20 Aug 2021 12:51:57 +0200 Subject: [PATCH 1/3] VIS.X: migrate from GET to POSTs & send additional userIDs --- modules/visxBidAdapter.js | 344 +++++++++----------- test/spec/modules/visxBidAdapter_spec.js | 389 +++++++++++++++-------- 2 files changed, 407 insertions(+), 326 deletions(-) diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js index 535beb8af3c..77c20dd1087 100644 --- a/modules/visxBidAdapter.js +++ b/modules/visxBidAdapter.js @@ -3,19 +3,21 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; import { INSTREAM as VIDEO_INSTREAM } from '../src/video.js'; -const { parseSizesInput, getKeys, logError, deepAccess } = utils; +const { parseSizesInput, logError, deepAccess } = utils; const BIDDER_CODE = 'visx'; const GVLID = 154; const BASE_URL = 'https://t.visx.net'; -const ENDPOINT_URL = BASE_URL + '/hb'; +const DEBUG_URL = 'https://t-stage.visx.net'; +const ENDPOINT_PATH = '/hb_post'; const TIME_TO_LIVE = 360; const DEFAULT_CUR = 'EUR'; -const ADAPTER_SYNC_URL = BASE_URL + '/push_sync'; -const TRACK_TIMEOUT_URL = BASE_URL + '/track/bid_timeout'; +const ADAPTER_SYNC_PATH = '/push_sync'; +const TRACK_TIMEOUT_PATH = '/track/bid_timeout'; const LOG_ERROR_MESS = { noAuid: 'Bid from response has no auid parameter - ', noAdm: 'Bid from response has no adm parameter - ', noBid: 'Array of bid objects is empty', + noImpId: 'Bid from response has no impid parameter - ', noPlacementCode: 'Can\'t find in requested bids the bid with auid - ', emptyUids: 'Uids should not be empty', emptySeatbid: 'Seatbid array from response has an empty item', @@ -28,7 +30,6 @@ const LOG_ERROR_MESS = { videoMissing: 'Bid request videoType property is missing - ' }; const currencyWhiteList = ['EUR', 'USD', 'GBP', 'PLN']; -const RE_EMPTY_OR_ONLY_COMMAS = /^,*$/; export const spec = { code: BIDDER_CODE, gvlid: GVLID, @@ -47,89 +48,53 @@ export const spec = { buildRequests: function(validBidRequests, bidderRequest) { const auids = []; const bidsMap = {}; - const slotsMapByUid = {}; - const sizeMap = {}; const bids = validBidRequests || []; const currency = config.getConfig(`currency.bidderCurrencyDefault.${BIDDER_CODE}`) || config.getConfig('currency.adServerCurrency') || DEFAULT_CUR; + let reqId; let payloadSchain; let payloadUserId; - const videoTypes = _initVideoTypes(bids); + let payloadUserEids; + let timeout; if (currencyWhiteList.indexOf(currency) === -1) { logError(LOG_ERROR_MESS.notAllowedCurrency + currency); return; } + const imp = []; + bids.forEach(bid => { reqId = bid.bidderRequestId; - const {params: {uid}, adUnitCode, schain, userId} = bid; - auids.push(uid); + + const impObj = buildImpObject(bid); + if (impObj) { + imp.push(impObj); + bidsMap[bid.bidId] = bid; + } + + const { params: { uid }, schain, userId, userIdAsEids } = bid; + if (!payloadSchain && schain) { payloadSchain = schain; } - if (!payloadUserId && userId) { - payloadUserId = userId; + if (!payloadUserEids && userIdAsEids) { + payloadUserEids = userIdAsEids; } - const sizesId = parseSizesInput(bid.sizes); - if (!slotsMapByUid[uid]) { - slotsMapByUid[uid] = {}; - } - const slotsMap = slotsMapByUid[uid]; - if (!slotsMap[adUnitCode]) { - slotsMap[adUnitCode] = {adUnitCode, bids: [bid], parents: []}; - } else { - slotsMap[adUnitCode].bids.push(bid); + if (!payloadUserId && userId) { + payloadUserId = userId; } - const slot = slotsMap[adUnitCode]; - - sizesId.forEach((sizeId) => { - sizeMap[sizeId] = true; - if (!bidsMap[uid]) { - bidsMap[uid] = {}; - } - - if (!bidsMap[uid][sizeId]) { - bidsMap[uid][sizeId] = [slot]; - } else { - bidsMap[uid][sizeId].push(slot); - } - slot.parents.push({parent: bidsMap[uid], key: sizeId, uid}); - }); + auids.push(uid); }); - const payload = { - pt: 'net', - auids: auids.join(','), - sizes: getKeys(sizeMap).join(','), - r: reqId, - cur: currency, - wrapperType: 'Prebid_js', - wrapperVersion: '$prebid.version$', - ...videoTypes - }; - - if (payloadSchain) { - payload.schain = JSON.stringify(payloadSchain); - } - - if (payloadUserId) { - if (payloadUserId.tdid) { - payload.tdid = payloadUserId.tdid; - } - if (payloadUserId.id5id && payloadUserId.id5id.uid) { - payload.id5 = payloadUserId.id5id.uid; - } - if (payloadUserId.digitrustid && payloadUserId.digitrustid.data && payloadUserId.digitrustid.data.id) { - payload.dtid = payloadUserId.digitrustid.data.id; - } - } + const payload = {}; if (bidderRequest) { + timeout = bidderRequest.timeout; if (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) { payload.u = bidderRequest.refererInfo.referer; } @@ -143,19 +108,50 @@ export const spec = { } } + const bidderTimeout = Number(config.getConfig('bidderTimeout')) || timeout; + const tmax = timeout ? Math.min(bidderTimeout, timeout) : bidderTimeout; + const source = { + ext: { + wrapperType: 'Prebid_js', + wrapperVersion: '$prebid.version$', + ...(payloadSchain && { schain: payloadSchain }) + } + }; + const user = { + ext: { + ...(payloadUserEids && { eids: payloadUserEids }), + ...(payload.gdpr_consent && { consent: payload.gdpr_consent }) + } + }; + const regs = ('gdpr_applies' in payload) && { + ext: { + gdpr: payload.gdpr_applies + } + }; + + const request = { + id: reqId, + imp, + tmax, + cur: [currency], + source, + site: { page: payload.u }, + ...(Object.keys(user.ext).length && { user }), + ...(regs && { regs }) + }; + return { - method: 'GET', - url: ENDPOINT_URL, - data: payload, - bidsMap: bidsMap, + method: 'POST', + url: buildUrl(ENDPOINT_PATH) + '?auids=' + encodeURIComponent(auids.join(',')), + data: request, + bidsMap }; }, interpretResponse: function(serverResponse, bidRequest) { serverResponse = serverResponse && serverResponse.body; const bidResponses = []; - const bidsWithoutSizeMatching = []; const bidsMap = bidRequest.bidsMap; - const currency = bidRequest.data.cur; + const currency = bidRequest.data.cur[0]; let errorMessage; @@ -166,10 +162,7 @@ export const spec = { if (!errorMessage && serverResponse.seatbid) { serverResponse.seatbid.forEach(respItem => { - _addBidResponse(_getBidFromResponse(respItem), bidsMap, currency, bidResponses, bidsWithoutSizeMatching); - }); - bidsWithoutSizeMatching.forEach(serverBid => { - _addBidResponse(serverBid, bidsMap, currency, bidResponses); + _addBidResponse(_getBidFromResponse(respItem), bidsMap, currency, bidResponses); }); } if (errorMessage) logError(errorMessage); @@ -188,7 +181,7 @@ export const spec = { } return [{ type: 'image', - url: ADAPTER_SYNC_URL + (query.length ? '?' + query.join('&') : '') + url: buildUrl(ADAPTER_SYNC_PATH) + (query.length ? '?' + query.join('&') : '') }]; } }, @@ -206,10 +199,61 @@ export const spec = { }, onTimeout: function(timeoutData) { // Call '/track/bid_timeout' with timeout data - utils.triggerPixel(TRACK_TIMEOUT_URL + '?data=' + JSON.stringify(timeoutData)); + utils.triggerPixel(buildUrl(TRACK_TIMEOUT_PATH) + '?data=' + JSON.stringify(timeoutData)); } }; +function buildUrl(path) { + return (config.getConfig('devMode') ? DEBUG_URL : BASE_URL) + path; +} + +function makeBanner(bannerParams) { + const bannerSizes = bannerParams && bannerParams.sizes; + if (bannerSizes) { + const sizes = utils.parseSizesInput(bannerSizes); + if (sizes.length) { + const format = sizes.map(size => { + const [ width, height ] = size.split('x'); + const w = parseInt(width, 10); + const h = parseInt(height, 10); + return { w, h }; + }); + + return { format }; + } + } +} + +function makeVideo(videoParams = {}) { + const video = Object.keys(videoParams).filter((param) => param !== 'context' && param !== 'playerSize') + .reduce((result, param) => { + result[param] = videoParams[param]; + return result; + }, { w: utils.deepAccess(videoParams, 'playerSize.0.0'), h: utils.deepAccess(videoParams, 'playerSize.0.1') }); + + if (video.w && video.h && video.mimes) { + return video; + } +} + +function buildImpObject(bid) { + const { params: { uid }, bidId, mediaTypes, sizes } = bid; + const banner = makeBanner(mediaTypes ? mediaTypes.banner : { sizes }); + const video = mediaTypes && _isVideoBid(bid) && _isValidVideoBid(bid) && makeVideo(mediaTypes.video); + const impObject = { + id: bidId, + ...(banner && { banner }), + ...(video && { video }), + ext: { + bidder: { uid: Number(uid) }, + } + }; + + if (impObject.ext.bidder.uid && (impObject.banner || impObject.video)) { + return impObject; + } +} + function _getBidFromResponse(respItem) { if (!respItem) { logError(LOG_ERROR_MESS.emptySeatbid); @@ -221,69 +265,47 @@ function _getBidFromResponse(respItem) { return respItem && respItem.bid && respItem.bid[0]; } -function _addBidResponse(serverBid, bidsMap, currency, bidResponses, bidsWithoutSizeMatching) { +function _addBidResponse(serverBid, bidsMap, currency, bidResponses) { if (!serverBid) return; let errorMessage; if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid); + if (!serverBid.impid) errorMessage = LOG_ERROR_MESS.noImpId + JSON.stringify(serverBid); if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid); else { const reqCurrency = currency || DEFAULT_CUR; - const awaitingBids = bidsMap[serverBid.auid]; - if (awaitingBids) { + const bid = bidsMap[serverBid.impid]; + if (bid) { if (serverBid.cur && serverBid.cur !== reqCurrency) { errorMessage = LOG_ERROR_MESS.currencyMismatch + reqCurrency + ' - ' + serverBid.cur; } else { - const sizeId = bidsWithoutSizeMatching ? `${serverBid.w}x${serverBid.h}` : Object.keys(awaitingBids)[0]; - if (awaitingBids[sizeId]) { - const slot = awaitingBids[sizeId][0]; - - const bid = slot.bids.shift(); - const bidResponse = { - requestId: bid.bidId, - cpm: serverBid.price, - width: serverBid.w, - height: serverBid.h, - creativeId: serverBid.auid, - currency: reqCurrency, - netRevenue: true, - ttl: TIME_TO_LIVE, - dealId: serverBid.dealid, - meta: { - advertiserDomains: serverBid.advertiserDomains ? serverBid.advertiserDomains : [], - mediaType: serverBid.mediaType - }, - }; - - if (serverBid.ext && serverBid.ext.prebid) { - bidResponse.ext = serverBid.ext.prebid; - } - - if (!_isVideoInstreamBid(bid)) { - bidResponse.ad = serverBid.adm; - } else { - bidResponse.vastXml = serverBid.adm; - bidResponse.mediaType = 'video'; - } - - bidResponses.push(bidResponse); - - if (!slot.bids.length) { - slot.parents.forEach(({parent, key, uid}) => { - const index = parent[key].indexOf(slot); - if (index > -1) { - parent[key].splice(index, 1); - } - if (!parent[key].length) { - delete parent[key]; - if (!getKeys(parent).length) { - delete bidsMap[uid]; - } - } - }); - } + const bidResponse = { + requestId: bid.bidId, + cpm: serverBid.price, + width: serverBid.w, + height: serverBid.h, + creativeId: serverBid.auid, + currency: reqCurrency, + netRevenue: true, + ttl: TIME_TO_LIVE, + dealId: serverBid.dealid, + meta: { + advertiserDomains: serverBid.advertiserDomains ? serverBid.advertiserDomains : [], + mediaType: serverBid.mediaType + }, + }; + + if (serverBid.ext && serverBid.ext.prebid) { + bidResponse.ext = serverBid.ext.prebid; + } + + if (!_isVideoInstreamBid(bid)) { + bidResponse.ad = serverBid.adm; } else { - bidsWithoutSizeMatching && bidsWithoutSizeMatching.push(serverBid); + bidResponse.vastXml = serverBid.adm; + bidResponse.mediaType = 'video'; } + + bidResponses.push(bidResponse); } } else { errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid; @@ -336,74 +358,4 @@ function _isValidVideoBid(bid, logErrors = false) { return result; } -function _initVideoTypes(bids) { - const result = {}; - let _playerSize = []; - let _protocols = []; - let _api = []; - let _mimes = []; - let _minduration = []; - let _maxduration = []; - let _skip = []; - if (bids && bids.length) { - bids.forEach(function (bid) { - const mediaTypes = deepAccess(bid, 'mediaTypes.video', {}); - let bidPlayerSize = ''; - let bidProtocols = ''; - let bidApi = ''; - let bidMimes = ''; - let bidMinduration = null; - let bidMaxduration = null; - let bidSkip = null; - if (_isVideoBid(bid) && _isValidVideoBid(bid)) { - bidPlayerSize = parseSizesInput(deepAccess(mediaTypes, 'playerSize', [])).join('|'); - bidProtocols = deepAccess(mediaTypes, 'protocols', []).join('|'); - bidApi = deepAccess(mediaTypes, 'api', []).join('|'); - bidMimes = deepAccess(mediaTypes, 'mimes', []).join('|'); - bidMinduration = deepAccess(mediaTypes, 'minduration', null); - bidMaxduration = deepAccess(mediaTypes, 'maxduration', null); - bidSkip = deepAccess(mediaTypes, 'skip', null); - } - _playerSize.push(bidPlayerSize); - _protocols.push(bidProtocols); - _api.push(bidApi); - _mimes.push(bidMimes); - _minduration.push(bidMinduration); - _maxduration.push(bidMaxduration); - _skip.push(bidSkip); - }); - } - _playerSize = _playerSize.join(','); - _protocols = _protocols.join(','); - _api = _api.join(','); - _mimes = _mimes.join(','); - _minduration = _minduration.join(','); - _maxduration = _maxduration.join(','); - _skip = _skip.join(','); - - if (!RE_EMPTY_OR_ONLY_COMMAS.test(_playerSize)) { - result.playerSize = _playerSize; - } - if (!RE_EMPTY_OR_ONLY_COMMAS.test(_protocols)) { - result.protocols = _protocols; - } - if (!RE_EMPTY_OR_ONLY_COMMAS.test(_api)) { - result.api = _api; - } - if (!RE_EMPTY_OR_ONLY_COMMAS.test(_mimes)) { - result.mimes = _mimes; - } - if (!RE_EMPTY_OR_ONLY_COMMAS.test(_minduration)) { - result.minduration = _minduration; - } - if (!RE_EMPTY_OR_ONLY_COMMAS.test(_maxduration)) { - result.maxduration = _maxduration; - } - if (!RE_EMPTY_OR_ONLY_COMMAS.test(_skip)) { - result.skip = _skip; - } - - return result; -} - registerBidder(spec); diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index 4a8207768ab..28245b3281b 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -65,7 +65,16 @@ describe('VisxAdapter', function () { }); describe('buildRequests', function () { + function parseRequest(url) { + const res = {}; + (url.split('?')[1] || '').split('&').forEach((it) => { + const couple = it.split('='); + res[couple[0]] = decodeURIComponent(couple[1]); + }); + return res; + } const bidderRequest = { + timeout: 3000, refererInfo: { referer: 'https://example.com' } @@ -83,7 +92,7 @@ describe('VisxAdapter', function () { { 'bidder': 'visx', 'params': { - 'uid': '903535' + 'uid': 903535 }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], @@ -94,7 +103,7 @@ describe('VisxAdapter', function () { { 'bidder': 'visx', 'params': { - 'uid': '903535' + 'uid': 903535 }, 'adUnitCode': 'adunit-code-2', 'sizes': [[728, 90], [300, 250]], @@ -105,7 +114,7 @@ describe('VisxAdapter', function () { { 'bidder': 'visx', 'params': { - 'uid': '903536' + 'uid': 903536 }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], @@ -116,7 +125,7 @@ describe('VisxAdapter', function () { { 'bidder': 'visx', 'params': { - 'uid': '903537' + 'uid': 903537 }, 'adUnitCode': 'adunit-code-video-3', 'mediaTypes': { @@ -135,83 +144,91 @@ describe('VisxAdapter', function () { } ]; + const expectedFullImps = [{ + 'id': '30b31c1838de1e', + 'banner': {'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}]}, + 'ext': {'bidder': {'uid': 903535}} + }, + { + 'id': '3150ccb55da321', + 'banner': {'format': [{'w': 728, 'h': 90}, {'w': 300, 'h': 250}]}, + 'ext': {'bidder': {'uid': 903535}} + }, + { + 'id': '42dbe3a7168a6a', + 'banner': {'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}]}, + 'ext': {'bidder': {'uid': 903536}} + }, + { + 'id': '42dbe3a7168a6a', + 'video': { + 'w': 400, + 'h': 300, + 'mimes': ['video/mp4', 'video/mpeg'], + 'protocols': [3, 6], + 'minduration': 5, + 'maxduration': 30 + }, + 'ext': {'bidder': {'uid': 903537}} + }]; + it('should attach valid params to the tag', function () { - const request = spec.buildRequests([bidRequests[0]], bidderRequest); - const payload = request.data; - expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', referrer); - expect(payload).to.have.property('pt', 'net'); + const firstBid = bidRequests[0]; + const bids = [firstBid]; + const request = spec.buildRequests(bids, bidderRequest); + const payload = parseRequest(request.url); + expect(request.url).to.be.an('string'); expect(payload).to.have.property('auids', '903535'); - expect(payload).to.have.property('sizes', '300x250,300x600'); - expect(payload).to.have.property('r', '22edbae2733bf6'); - expect(payload).to.have.property('cur', 'EUR'); - }); - it('sizes must not be duplicated', function () { - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = request.data; - expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', referrer); - expect(payload).to.have.property('pt', 'net'); - expect(payload).to.have.property('auids', '903535,903535,903536,903537'); - expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); - expect(payload).to.have.property('r', '22edbae2733bf6'); - expect(payload).to.have.property('cur', 'EUR'); + const postData = request.data; + expect(postData).to.be.an('object'); + expect(postData).to.deep.equal({ + 'id': '22edbae2733bf6', + 'imp': [expectedFullImps[0]], + 'tmax': 3000, + 'cur': ['EUR'], + 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, + 'site': {'page': referrer} + }); }); - it('pt parameter must be "net" if params.priceType === "gross"', function () { - bidRequests[1].params.priceType = 'gross'; + it('should attach valid params to the tag with multiformat request', function () { const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = request.data; + const payload = parseRequest(request.url); expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', referrer); - expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536,903537'); - expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); - expect(payload).to.have.property('r', '22edbae2733bf6'); - expect(payload).to.have.property('cur', 'EUR'); - delete bidRequests[1].params.priceType; - }); - it('pt parameter must be "net" if params.priceType === "net"', function () { - bidRequests[1].params.priceType = 'net'; - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = request.data; - expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', referrer); - expect(payload).to.have.property('pt', 'net'); - expect(payload).to.have.property('auids', '903535,903535,903536,903537'); - expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); - expect(payload).to.have.property('r', '22edbae2733bf6'); - expect(payload).to.have.property('cur', 'EUR'); - delete bidRequests[1].params.priceType; - }); - it('pt parameter must be "net" if params.priceType === "undefined"', function () { - bidRequests[1].params.priceType = 'undefined'; - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = request.data; - expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', referrer); - expect(payload).to.have.property('pt', 'net'); - expect(payload).to.have.property('auids', '903535,903535,903536,903537'); - expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); - expect(payload).to.have.property('r', '22edbae2733bf6'); - expect(payload).to.have.property('cur', 'EUR'); - delete bidRequests[1].params.priceType; + const postData = request.data; + expect(postData).to.be.an('object'); + expect(postData).to.deep.equal({ + 'id': '22edbae2733bf6', + 'imp': expectedFullImps, + 'tmax': 3000, + 'cur': ['EUR'], + 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, + 'site': {'page': referrer} + }); }); it('should add currency from currency.bidderCurrencyDefault', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( arg => arg === 'currency.bidderCurrencyDefault.visx' ? 'GBP' : 'USD'); const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = request.data; + const payload = parseRequest(request.url); expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', referrer); - expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536,903537'); - expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); - expect(payload).to.have.property('r', '22edbae2733bf6'); - expect(payload).to.have.property('cur', 'GBP'); + + const postData = request.data; + expect(postData).to.be.an('object'); + expect(postData).to.deep.equal({ + 'id': '22edbae2733bf6', + 'imp': expectedFullImps, + 'tmax': 3000, + 'cur': ['GBP'], + 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, + 'site': {'page': referrer} + }); + getConfigStub.restore(); }); @@ -219,39 +236,73 @@ describe('VisxAdapter', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( arg => arg === 'currency.bidderCurrencyDefault.visx' ? '' : 'USD'); const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = request.data; + const payload = parseRequest(request.url); expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', referrer); - expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536,903537'); - expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); - expect(payload).to.have.property('r', '22edbae2733bf6'); - expect(payload).to.have.property('cur', 'USD'); + + const postData = request.data; + expect(postData).to.be.an('object'); + expect(postData).to.deep.equal({ + 'id': '22edbae2733bf6', + 'imp': expectedFullImps, + 'tmax': 3000, + 'cur': ['USD'], + 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, + 'site': {'page': referrer} + }); + getConfigStub.restore(); }); it('if gdprConsent is present payload must have gdpr params', function () { - const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}}); - const payload = request.data; - expect(payload).to.be.an('object'); - expect(payload).to.have.property('gdpr_consent', 'AAA'); - expect(payload).to.have.property('gdpr_applies', 1); + const request = spec.buildRequests(bidRequests, Object.assign({gdprConsent: {consentString: 'AAA', gdprApplies: true}}, bidderRequest)); + + const postData = request.data; + expect(postData).to.be.an('object'); + expect(postData).to.deep.equal({ + 'id': '22edbae2733bf6', + 'imp': expectedFullImps, + 'tmax': 3000, + 'cur': ['EUR'], + 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, + 'site': {'page': referrer}, + 'user': {'ext': {'consent': 'AAA'}}, + 'regs': {'ext': {'gdpr': 1}} + }); }); it('if gdprApplies is false gdpr_applies must be 0', function () { - const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: false}}); - const payload = request.data; - expect(payload).to.be.an('object'); - expect(payload).to.have.property('gdpr_consent', 'AAA'); - expect(payload).to.have.property('gdpr_applies', 0); + const request = spec.buildRequests(bidRequests, Object.assign({gdprConsent: {consentString: 'AAA', gdprApplies: false}}, bidderRequest)); + + const postData = request.data; + expect(postData).to.be.an('object'); + expect(postData).to.deep.equal({ + 'id': '22edbae2733bf6', + 'imp': expectedFullImps, + 'tmax': 3000, + 'cur': ['EUR'], + 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, + 'site': {'page': referrer}, + 'user': {'ext': {'consent': 'AAA'}}, + 'regs': {'ext': {'gdpr': 0}} + }); }); it('if gdprApplies is undefined gdpr_applies must be 1', function () { - const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA'}}); - const payload = request.data; - expect(payload).to.be.an('object'); - expect(payload).to.have.property('gdpr_consent', 'AAA'); - expect(payload).to.have.property('gdpr_applies', 1); + const request = spec.buildRequests(bidRequests, Object.assign({gdprConsent: {consentString: 'AAA'}}, bidderRequest)); + + const postData = request.data; + expect(postData).to.be.an('object'); + expect(postData).to.deep.equal({ + 'id': '22edbae2733bf6', + 'imp': expectedFullImps, + 'tmax': 3000, + 'cur': ['EUR'], + 'source': {'ext': {'wrapperType': 'Prebid_js', 'wrapperVersion': '$prebid.version$'}}, + 'site': {'page': referrer}, + 'user': {'ext': {'consent': 'AAA'}}, + 'regs': {'ext': {'gdpr': 1}} + }); }); it('if schain is present payload must have schain param', function () { @@ -261,49 +312,111 @@ describe('VisxAdapter', function () { bidRequests[2] ]; const request = spec.buildRequests(schainBidRequests, bidderRequest); - const payload = request.data; + const payload = parseRequest(request.url); expect(payload).to.be.an('object'); - expect(payload).to.have.property('schain', schainString); - expect(payload).to.have.property('u', referrer); - expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903535,903535,903536'); - expect(payload).to.have.property('sizes', '300x250,300x600,728x90'); - expect(payload).to.have.property('r', '22edbae2733bf6'); - expect(payload).to.have.property('cur', 'EUR'); + + const postData = request.data; + expect(postData).to.be.an('object'); + expect(postData).to.deep.equal({ + 'id': '22edbae2733bf6', + 'imp': expectedFullImps.slice(0, -1), + 'tmax': 3000, + 'cur': ['EUR'], + 'source': { + 'ext': { + 'wrapperType': 'Prebid_js', + 'wrapperVersion': '$prebid.version$', + 'schain': schainObject + } + }, + 'site': {'page': referrer}, + }); }); it('if userId is available payload must have appropriate params', function () { - const schainBidRequests = [ + const eids = [ + { + source: 'pubcid.org', + uids: [{ + id: 'some-random-id-value', + atype: 1 + }] + }, + { + source: 'adserver.org', + uids: [{ + id: 'some-random-id-value', + atype: 1, + ext: { + rtiPartner: 'TDID' + } + }] + } + ]; + const userIdBidRequests = [ Object.assign({userId: { tdid: '111', id5id: { uid: '222' }, digitrustid: {data: {id: 'DTID', keyv: 4, privacy: {optout: false}, producer: 'ABC', version: 2}} - }}, bidRequests[0]), + }, + userIdAsEids: eids}, bidRequests[0]), bidRequests[1], bidRequests[2] ]; - const request = spec.buildRequests(schainBidRequests, bidderRequest); - const payload = request.data; - expect(payload).to.be.an('object'); - expect(payload).to.have.property('tdid', '111'); - expect(payload).to.have.property('id5', '222'); - expect(payload).to.have.property('dtid', 'DTID'); + const request = spec.buildRequests(userIdBidRequests, bidderRequest); + + const postData = request.data; + expect(postData).to.be.an('object'); + expect(postData).to.deep.equal({ + 'id': '22edbae2733bf6', + 'imp': expectedFullImps.slice(0, -1), + 'tmax': 3000, + 'cur': ['EUR'], + 'source': { + 'ext': { + 'wrapperType': 'Prebid_js', + 'wrapperVersion': '$prebid.version$', + 'schain': schainObject + } + }, + 'site': {'page': referrer}, + 'user': {'ext': {'eids': eids}} + }); }); it('should pass grouped video bid\'s params in payload', function () { const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = request.data; - expect(payload).to.have.property('protocols', ',,,3|6'); - expect(payload).to.have.property('mimes', ',,,video/mp4|video/mpeg'); - expect(payload).to.have.property('playerSize', ',,,400x300'); - expect(payload).to.have.property('minduration', ',,,5'); - expect(payload).to.have.property('maxduration', ',,,30'); - expect(payload).to.not.have.property('skip'); + + const postData = request.data; + expect(postData).to.be.an('object'); + expect(postData).to.deep.equal({ + 'id': '22edbae2733bf6', + 'imp': expectedFullImps, + 'tmax': 3000, + 'cur': ['EUR'], + 'source': { + 'ext': { + 'wrapperType': 'Prebid_js', + 'wrapperVersion': '$prebid.version$' + } + }, + 'site': {'page': referrer} + }); }); }); describe('buildRequests (multiple media types w/ unsupported video+outstream)', function () { + function parseRequest(url) { + const res = {}; + (url.split('?')[1] || '').split('&').forEach((it) => { + const couple = it.split('='); + res[couple[0]] = decodeURIComponent(couple[1]); + }); + return res; + } const bidderRequest = { + timeout: 3000, refererInfo: { referer: 'https://example.com' } @@ -331,22 +444,38 @@ describe('VisxAdapter', function () { it('should send requst for banner bid', function () { const request = spec.buildRequests([bidRequests[0]], bidderRequest); - const payload = request.data; + const payload = parseRequest(request.url); expect(payload).to.be.an('object'); - expect(payload).to.have.property('u', referrer); - expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '903538'); - expect(payload).to.have.property('sizes', '300x250,300x600'); - expect(payload).to.not.have.property('playerSize'); + + const postData = request.data; + expect(postData).to.be.an('object'); + expect(postData).to.deep.equal({ + 'id': '22edbae2733bf6', + 'imp': [{ + 'id': '39aff3a7169a6a', + 'banner': {'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}]}, + 'ext': {'bidder': {'uid': 903538}} + }], + 'tmax': 3000, + 'cur': ['EUR'], + 'source': { + 'ext': { + 'wrapperType': 'Prebid_js', + 'wrapperVersion': '$prebid.version$' + } + }, + 'site': {'page': referrer} + }); }); }); describe('interpretResponse', function () { const responses = [ - {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner', 'advertiserDomains': ['some_domain.com']}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 903536, 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0.15, 'adm': '
test content 3
', 'auid': 903535, 'h': 90, 'w': 728, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0, 'auid': 903537, 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'impid': '300bfeb0d71a5b', 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner', 'advertiserDomains': ['some_domain.com']}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'impid': '4dff80cc4ee346', 'adm': '
test content 2
', 'auid': 903536, 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'impid': '5703af74d0472a', 'adm': '
test content 3
', 'auid': 903535, 'h': 90, 'w': 728, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 0, 'impid': '300bfeb0d7190gf', 'auid': 903537, 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, {'bid': [{'price': 0, 'adm': '
test content 5
', 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, undefined, {'bid': [], 'seat': '1'}, @@ -362,7 +491,7 @@ describe('VisxAdapter', function () { }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], - 'bidId': '659423fff799cb', + 'bidId': '300bfeb0d71a5b', 'bidderRequestId': '5f2009617a7c0a', 'auctionId': '1cbd2feafe5e8b', } @@ -370,7 +499,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests(bidRequests); const expectedResponse = [ { - 'requestId': '659423fff799cb', + 'requestId': '300bfeb0d71a5b', 'cpm': 1.15, 'creativeId': 903535, 'dealId': undefined, @@ -492,7 +621,7 @@ describe('VisxAdapter', function () { }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], - 'bidId': '659423fff799cb', + 'bidId': '300bfeb0d71a5b', 'bidderRequestId': '5f2009617a7c0a', 'auctionId': '1cbd2feafe5e8b', } @@ -501,7 +630,7 @@ describe('VisxAdapter', function () { const request = spec.buildRequests(bidRequests); const expectedResponse = [ { - 'requestId': '659423fff799cb', + 'requestId': '300bfeb0d71a5b', 'cpm': 1.15, 'creativeId': 903535, 'dealId': undefined, @@ -568,11 +697,11 @@ describe('VisxAdapter', function () { it('complicated case', function () { const fullResponse = [ - {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner', 'advertiserDomains': ['some_domain.com']}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 903536, 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0.15, 'adm': '
test content 3
', 'auid': 903535, 'h': 90, 'w': 728, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0.15, 'adm': '
test content 4
', 'auid': 903535, 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'adm': '
test content 5
', 'auid': 903536, 'h': 600, 'w': 350, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'impid': '2164be6358b9', 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner', 'advertiserDomains': ['some_domain.com']}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'impid': '4e111f1b66e4', 'adm': '
test content 2
', 'auid': 903536, 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'impid': '26d6f897b516', 'adm': '
test content 3
', 'auid': 903535, 'h': 90, 'w': 728, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 0.15, 'impid': '326bde7fbf69', 'adm': '
test content 4
', 'auid': 903535, 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'impid': '1751cd90161', 'adm': '
test content 5
', 'auid': 903536, 'h': 600, 'w': 350, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, ]; const bidRequests = [ { @@ -721,8 +850,8 @@ describe('VisxAdapter', function () { it('dublicate uids and sizes in one slot', function () { const fullResponse = [ - {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, - {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'impid': '5126e301f4be', 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'impid': '57b2ebe70e16', 'adm': '
test content 2
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, ]; const bidRequests = [ { @@ -801,7 +930,7 @@ describe('VisxAdapter', function () { it('handles video bid', function () { const fullResponse = [ - {'bid': [{'price': 0.5, 'adm': '', 'auid': 903537, 'w': 400, 'h': 300, 'cur': 'EUR', 'mediaType': 'video'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'impid': '2164be6358b9', 'adm': '', 'auid': 903537, 'w': 400, 'h': 300, 'cur': 'EUR', 'mediaType': 'video'}], 'seat': '1'}, ]; const bidRequests = [ { @@ -908,7 +1037,7 @@ describe('VisxAdapter', function () { }, 'adUnitCode': 'adunit-code-1', 'sizes': [[300, 250], [300, 600]], - 'bidId': '659423fff799cb', + 'bidId': '300bfeb0d71a5b', 'bidderRequestId': '5f2009617a7c0a', 'auctionId': '1cbd2feafe5e8b', } @@ -918,7 +1047,7 @@ describe('VisxAdapter', function () { const winUrl = 'https://t.visx.net/track/win/53245341'; const expectedResponse = [ { - 'requestId': '659423fff799cb', + 'requestId': '300bfeb0d71a5b', 'cpm': 1.15, 'creativeId': 903535, 'dealId': undefined, From f19cfd50c5c2e202a7b47e20fe7bef4ae1c7d110 Mon Sep 17 00:00:00 2001 From: Mikhail Kuryshev Date: Wed, 1 Sep 2021 12:16:01 +0200 Subject: [PATCH 2/3] VIS.X: fix tests --- modules/visxBidAdapter.js | 2 +- test/spec/modules/visxBidAdapter_spec.js | 22 ++++++++++------------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js index 77c20dd1087..2677b970dfd 100644 --- a/modules/visxBidAdapter.js +++ b/modules/visxBidAdapter.js @@ -238,8 +238,8 @@ function makeVideo(videoParams = {}) { function buildImpObject(bid) { const { params: { uid }, bidId, mediaTypes, sizes } = bid; - const banner = makeBanner(mediaTypes ? mediaTypes.banner : { sizes }); const video = mediaTypes && _isVideoBid(bid) && _isValidVideoBid(bid) && makeVideo(mediaTypes.video); + const banner = makeBanner((mediaTypes && mediaTypes.banner) || (!video && { sizes })); const impObject = { id: bidId, ...(banner && { banner }), diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index 28245b3281b..74ab959b5f2 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -44,7 +44,7 @@ describe('VisxAdapter', function () { videoBid.mediaTypes = { video: { context: 'instream', - playerSize: [400, 300] + playerSize: [[400, 300]] } }; expect(spec.isBidRequestValid(videoBid)).to.equal(false); @@ -55,7 +55,7 @@ describe('VisxAdapter', function () { videoBid.mediaTypes = { video: { context: 'instream', - playerSize: [400, 300], + playerSize: [[400, 300]], mimes: ['video/mp4'], protocols: [3, 6] } @@ -87,7 +87,6 @@ describe('VisxAdapter', function () { {asi: 'exchange1.com', sid: '1234!abcd', hp: 1, name: 'publisher, Inc.', domain: 'publisher.com'} ] }; - const schainString = JSON.stringify(schainObject); let bidRequests = [ { 'bidder': 'visx', @@ -131,7 +130,7 @@ describe('VisxAdapter', function () { 'mediaTypes': { 'video': { 'context': 'instream', - 'playerSize': [400, 300], + 'playerSize': [[400, 300]], 'mimes': ['video/mp4', 'video/mpeg'], 'protocols': [3, 6], 'minduration': 5, @@ -160,7 +159,7 @@ describe('VisxAdapter', function () { 'ext': {'bidder': {'uid': 903536}} }, { - 'id': '42dbe3a7168a6a', + 'id': '39a4e3a7168a6a', 'video': { 'w': 400, 'h': 300, @@ -376,8 +375,7 @@ describe('VisxAdapter', function () { 'source': { 'ext': { 'wrapperType': 'Prebid_js', - 'wrapperVersion': '$prebid.version$', - 'schain': schainObject + 'wrapperVersion': '$prebid.version$' } }, 'site': {'page': referrer}, @@ -433,11 +431,11 @@ describe('VisxAdapter', function () { 'mediaTypes': { 'video': { 'context': 'outstream', - 'playerSize': [400, 300] + 'playerSize': [[400, 300]] } }, 'bidId': '39aff3a7169a6a', - 'bidderRequestId': '22edffe2733bf6', + 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a476', } ]; @@ -942,7 +940,7 @@ describe('VisxAdapter', function () { 'mediaTypes': { 'video': { 'context': 'instream', - 'playerSize': [400, 300], + 'playerSize': [[400, 300]], 'mimes': ['video/mp4'], 'protocols': [3, 6] } @@ -979,7 +977,7 @@ describe('VisxAdapter', function () { it('handles multiformat bid response with outstream+banner as banner', function () { const fullResponse = [ - {'bid': [{'price': 0.5, 'adm': '', 'auid': 903537, 'w': 400, 'h': 300, 'cur': 'EUR', 'mediaType': 'video'}], 'seat': '1'}, + {'bid': [{'price': 0.5, 'impid': '2164be6358b9', 'adm': '', 'auid': 903537, 'w': 400, 'h': 300, 'cur': 'EUR', 'mediaType': 'video'}], 'seat': '1'}, ]; const bidRequests = [ { @@ -991,7 +989,7 @@ describe('VisxAdapter', function () { 'mediaTypes': { 'video': { 'context': 'outstream', - 'playerSize': [400, 300], + 'playerSize': [[400, 300]], 'mimes': ['video/mp4'], 'protocols': [3, 6] } From 5ed9668100a2b88a9be97f1d8c4c9c909c9f6534 Mon Sep 17 00:00:00 2001 From: Mikhail Kuryshev Date: Wed, 8 Sep 2021 12:59:13 +0200 Subject: [PATCH 3/3] VIS.X: pass bid.ext.prebid.targeting to bidResponse.adserverTargeting --- modules/visxBidAdapter.js | 5 ++ test/spec/modules/visxBidAdapter_spec.js | 62 ++++++++++++++++++++---- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js index 2677b970dfd..fb9b21dc167 100644 --- a/modules/visxBidAdapter.js +++ b/modules/visxBidAdapter.js @@ -298,6 +298,11 @@ function _addBidResponse(serverBid, bidsMap, currency, bidResponses) { bidResponse.ext = serverBid.ext.prebid; } + const visxTargeting = deepAccess(serverBid, 'ext.prebid.targeting'); + if (visxTargeting) { + bidResponse.adserverTargeting = visxTargeting; + } + if (!_isVideoInstreamBid(bid)) { bidResponse.ad = serverBid.adm; } else { diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index 74ab959b5f2..99ab327eda4 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -470,7 +470,7 @@ describe('VisxAdapter', function () { describe('interpretResponse', function () { const responses = [ - {'bid': [{'price': 1.15, 'impid': '300bfeb0d71a5b', 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner', 'advertiserDomains': ['some_domain.com']}], 'seat': '1'}, + {'bid': [{'price': 1.15, 'impid': '300bfeb0d71a5b', 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner', 'advertiserDomains': ['some_domain.com'], 'ext': {'prebid': {'targeting': {'hb_visx_product': 'understitial', 'hb_visx_width': 300, 'hb_visx_height': 250}}}}], 'seat': '1'}, {'bid': [{'price': 0.5, 'impid': '4dff80cc4ee346', 'adm': '
test content 2
', 'auid': 903536, 'h': 600, 'w': 300, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, {'bid': [{'price': 0.15, 'impid': '5703af74d0472a', 'adm': '
test content 3
', 'auid': 903535, 'h': 90, 'w': 728, 'cur': 'EUR', 'mediaType': 'banner'}], 'seat': '1'}, {'bid': [{'price': 0, 'impid': '300bfeb0d7190gf', 'auid': 903537, 'h': 250, 'w': 300, 'cur': 'EUR'}], 'seat': '1'}, @@ -511,6 +511,18 @@ describe('VisxAdapter', function () { 'advertiserDomains': ['some_domain.com'], 'mediaType': 'banner', }, + 'adserverTargeting': { + 'hb_visx_product': 'understitial', + 'hb_visx_width': 300, + 'hb_visx_height': 250, + }, + 'ext': { + 'targeting': { + 'hb_visx_product': 'understitial', + 'hb_visx_width': 300, + 'hb_visx_height': 250, + } + } } ]; @@ -571,6 +583,18 @@ describe('VisxAdapter', function () { 'advertiserDomains': ['some_domain.com'], 'mediaType': 'banner', }, + 'adserverTargeting': { + 'hb_visx_product': 'understitial', + 'hb_visx_width': 300, + 'hb_visx_height': 250, + }, + 'ext': { + 'targeting': { + 'hb_visx_product': 'understitial', + 'hb_visx_width': 300, + 'hb_visx_height': 250, + } + } }, { 'requestId': '4dff80cc4ee346', @@ -642,6 +666,18 @@ describe('VisxAdapter', function () { 'advertiserDomains': ['some_domain.com'], 'mediaType': 'banner', }, + 'adserverTargeting': { + 'hb_visx_product': 'understitial', + 'hb_visx_width': 300, + 'hb_visx_height': 250, + }, + 'ext': { + 'targeting': { + 'hb_visx_product': 'understitial', + 'hb_visx_width': 300, + 'hb_visx_height': 250, + } + } } ]; @@ -1059,23 +1095,31 @@ describe('VisxAdapter', function () { 'advertiserDomains': ['some_domain.com'], 'mediaType': 'banner', }, + 'adserverTargeting': { + 'hb_visx_product': 'understitial', + 'hb_visx_width': 300, + 'hb_visx_height': 250, + }, 'ext': { 'events': { 'pending': pendingUrl, 'win': winUrl + }, + 'targeting': { + 'hb_visx_product': 'understitial', + 'hb_visx_width': 300, + 'hb_visx_height': 250, } } } ]; const serverResponse = Object.assign({}, responses[0]); - serverResponse.bid = [Object.assign({}, {ext: { - prebid: { - events: { - 'pending': pendingUrl, - 'win': winUrl - } - } - }}, serverResponse.bid[0])]; + serverResponse.bid = [Object.assign({}, serverResponse.bid[0])]; + serverResponse.bid[0].ext.prebid = Object.assign({}, serverResponse.bid[0].ext.prebid); + utils.deepSetValue(serverResponse.bid[0], 'ext.prebid.events', { + pending: pendingUrl, + win: winUrl, + }); const result = spec.interpretResponse({'body': {'seatbid': [serverResponse]}}, request); expect(result).to.deep.equal(expectedResponse); });