diff --git a/modules/proxistoreBidAdapter.js b/modules/proxistoreBidAdapter.js index c546337c47f..0b553ce995b 100644 --- a/modules/proxistoreBidAdapter.js +++ b/modules/proxistoreBidAdapter.js @@ -1,62 +1,83 @@ - import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { getStorageManager } from '../src/storageManager.js'; + const BIDDER_CODE = 'proxistore'; -const storage = getStorageManager(); const PROXISTORE_VENDOR_ID = 418; function _createServerRequest(bidRequests, bidderRequest) { - const sizeIds = []; - + var sizeIds = []; bidRequests.forEach(function (bid) { - const sizeId = { + var sizeId = { id: bid.bidId, sizes: bid.sizes.map(function (size) { return { width: size[0], - height: size[1] + height: size[1], }; - }) + }), + floor: _assignFloor(bid), + segments: _assignSegments(bid), }; sizeIds.push(sizeId); }); - const payload = { + var payload = { auctionId: bidRequests[0].auctionId, transactionId: bidRequests[0].auctionId, bids: sizeIds, website: bidRequests[0].params.website, language: bidRequests[0].params.language, gdpr: { - applies: false - } - }; - const options = { - contentType: 'application/json', - withCredentials: true + applies: false, + }, }; if (bidderRequest && bidderRequest.gdprConsent) { - if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean' && bidderRequest.gdprConsent.gdprApplies) { + if ( + typeof bidderRequest.gdprConsent.gdprApplies === 'boolean' && + bidderRequest.gdprConsent.gdprApplies + ) { payload.gdpr.applies = true; } - if (typeof bidderRequest.gdprConsent.consentString === 'string' && bidderRequest.gdprConsent.consentString) { + if ( + typeof bidderRequest.gdprConsent.consentString === 'string' && + bidderRequest.gdprConsent.consentString + ) { payload.gdpr.consentString = bidderRequest.gdprConsent.consentString; } - if (bidderRequest.gdprConsent.vendorData && bidderRequest.gdprConsent.vendorData.vendorConsents && typeof bidderRequest.gdprConsent.vendorData.vendorConsents[PROXISTORE_VENDOR_ID.toString(10)] !== 'undefined') { - payload.gdpr.consentGiven = !!bidderRequest.gdprConsent.vendorData.vendorConsents[PROXISTORE_VENDOR_ID.toString(10)]; + if ( + bidderRequest.gdprConsent.vendorData && + bidderRequest.gdprConsent.vendorData.vendorConsents && + typeof bidderRequest.gdprConsent.vendorData.vendorConsents[PROXISTORE_VENDOR_ID.toString(10)] !== 'undefined' + ) { + payload.gdpr.consentGiven = !!bidderRequest.gdprConsent.vendorData + .vendorConsents[PROXISTORE_VENDOR_ID.toString(10)]; } } + const options = { + contentType: 'application/json', + withCredentials: !!payload.gdpr.consentGiven, + }; + const endPointUri = payload.gdpr.consentGiven || !payload.gdpr.applies + ? `https://abs.proxistore.com/${payload.language}/v3/rtb/prebid/multi` + : `https://abs.proxistore.com/${payload.language}/v3/rtb/prebid/multi/cookieless`; + return { method: 'POST', - url: bidRequests[0].params.url || 'https://abs.proxistore.com/' + payload.language + '/v3/rtb/prebid/multi', + url: endPointUri, data: JSON.stringify(payload), - options: options + options: options, }; } +function _assignSegments(bid) { + if (bid.ortb2 && bid.ortb2.user && bid.ortb2.user.ext && bid.ortb2.user.ext.data) { + return bid.ortb2.user.ext.data || {segments: [], contextual_categories: {}}; + } + return {segments: [], contextual_categories: {}}; +} + function _createBidResponse(response) { return { requestId: response.requestId, @@ -70,7 +91,7 @@ function _createBidResponse(response) { netRevenue: response.netRevenue, vastUrl: response.vastUrl, vastXml: response.vastXml, - dealId: response.dealId + dealId: response.dealId, }; } /** @@ -81,23 +102,8 @@ function _createBidResponse(response) { */ function isBidRequestValid(bid) { - const hasNoAd = function() { - if (!storage.hasLocalStorage()) { - return false; - } - const pxNoAds = storage.getDataFromLocalStorage(`PX_NoAds_${bid.params.website}`); - if (!pxNoAds) { - return false; - } else { - const storedDate = new Date(pxNoAds); - const now = new Date(); - const diff = Math.abs(storedDate.getTime() - now.getTime()) / 60000; - return diff <= 5; - } - } - return !!(bid.params.website && bid.params.language) && !hasNoAd(); + return !!(bid.params.website && bid.params.language); } - /** * Make a server request from the list of BidRequests. * @@ -107,7 +113,7 @@ function isBidRequestValid(bid) { */ function buildRequests(bidRequests, bidderRequest) { - const request = _createServerRequest(bidRequests, bidderRequest); + var request = _createServerRequest(bidRequests, bidderRequest); return request; } /** @@ -119,34 +125,23 @@ function buildRequests(bidRequests, bidderRequest) { */ function interpretResponse(serverResponse, bidRequest) { - const itemName = `PX_NoAds_${websiteFromBidRequest(bidRequest)}`; - if (serverResponse.body.length > 0) { - storage.removeDataFromLocalStorage(itemName, true); - return serverResponse.body.map(_createBidResponse); - } else { - storage.setDataInLocalStorage(itemName, new Date()); - return []; - } + return serverResponse.body.map(_createBidResponse); } -const websiteFromBidRequest = function(bidR) { - if (bidR.data) { - return JSON.parse(bidR.data).website - } else if (bidR.params.website) { - return bidR.params.website; - } -} +function _assignFloor(bid) { + if (typeof bid.getFloor === 'function') { + var floorInfo = bid.getFloor({ + currency: 'EUR', + mediaType: 'banner', + size: '*', + }); -/** - * Register the user sync pixels which should be dropped after the auction. - * - * @param syncOptions Which user syncs are allowed? - * @param serverResponses List of server's responses. - * @return The user syncs which should be dropped. - */ + if (floorInfo.currency === 'EUR') { + return floorInfo.floor; + } + } -function getUserSyncs(syncOptions, serverResponses) { - return []; + return null; } export const spec = { @@ -154,7 +149,7 @@ export const spec = { isBidRequestValid: isBidRequestValid, buildRequests: buildRequests, interpretResponse: interpretResponse, - getUserSyncs: getUserSyncs + }; registerBidder(spec); diff --git a/test/spec/modules/proxistoreBidAdapter_spec.js b/test/spec/modules/proxistoreBidAdapter_spec.js index 410c3c59fb6..f98d9633320 100644 --- a/test/spec/modules/proxistoreBidAdapter_spec.js +++ b/test/spec/modules/proxistoreBidAdapter_spec.js @@ -1,55 +1,58 @@ import { expect } from 'chai'; let { spec } = require('modules/proxistoreBidAdapter'); - const BIDDER_CODE = 'proxistore'; describe('ProxistoreBidAdapter', function () { const bidderRequest = { - 'bidderCode': BIDDER_CODE, - 'auctionId': '1025ba77-5463-4877-b0eb-14b205cb9304', - 'bidderRequestId': '10edf38ec1a719', - 'gdprConsent': { - 'gdprApplies': true, - 'consentString': 'CONSENT_STRING', - 'vendorData': { - 'vendorConsents': { - '418': true - } - } - } + bidderCode: BIDDER_CODE, + auctionId: '1025ba77-5463-4877-b0eb-14b205cb9304', + bidderRequestId: '10edf38ec1a719', + gdprConsent: { + gdprApplies: true, + consentString: 'CONSENT_STRING', + vendorData: { + vendorConsents: { + 418: true, + }, + }, + }, }; let bid = { sizes: [[300, 600]], params: { website: 'example.fr', - language: 'fr' + language: 'fr', + }, + ortb2: { + user: { ext: { data: { segments: [], contextual_categories: {} } } }, }, auctionId: 442133079, bidId: 464646969, - transactionId: 511916005 + transactionId: 511916005, }; describe('isBidRequestValid', function () { it('it should be true if required params are presents and there is no info in the local storage', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - - it('it should be false if the value in the localstorage is less than 5minutes of the actual time', function() { + it('it should be false if the value in the localstorage is less than 5minutes of the actual time', function () { const date = new Date(); - date.setMinutes(date.getMinutes() - 1) - localStorage.setItem(`PX_NoAds_${bid.params.website}`, date) - expect(spec.isBidRequestValid(bid)).to.equal(false); + date.setMinutes(date.getMinutes() - 1); + localStorage.setItem(`PX_NoAds_${bid.params.website}`, date); + expect(spec.isBidRequestValid(bid)).to.equal(true); }); - - it('it should be true if the value in the localstorage is more than 5minutes of the actual time', function() { + it('it should be true if the value in the localstorage is more than 5minutes of the actual time', function () { const date = new Date(); - date.setMinutes(date.getMinutes() - 10) - localStorage.setItem(`PX_NoAds_${bid.params.website}`, date) + date.setMinutes(date.getMinutes() - 10); + localStorage.setItem(`PX_NoAds_${bid.params.website}`, date); expect(spec.isBidRequestValid(bid)).to.equal(true); }); }); - describe('buildRequests', function () { - const url = 'https://abs.proxistore.com/fr/v3/rtb/prebid/multi'; - const request = spec.buildRequests([bid], bidderRequest); + const url = { + cookieBase: 'https://abs.proxistore.com/fr/v3/rtb/prebid/multi', + cookieLess: + 'https://abs.proxistore.com/fr/v3/rtb/prebid/multi/cookieless', + }; + let request = spec.buildRequests([bid], bidderRequest); it('should return a valid object', function () { expect(request).to.be.an('object'); expect(request.method).to.exist; @@ -59,16 +62,22 @@ describe('ProxistoreBidAdapter', function () { it('request method should be POST', function () { expect(request.method).to.equal('POST'); }); - it('should contain a valid url', function () { - expect(request.url).equal(url); - }); it('should have the value consentGiven to true bc we have 418 in the vendor list', function () { const data = JSON.parse(request.data); - - expect(data.gdpr.consentString).equal(bidderRequest.gdprConsent.consentString); + expect(data.gdpr.consentString).equal( + bidderRequest.gdprConsent.consentString + ); expect(data.gdpr.applies).to.be.true; expect(data.gdpr.consentGiven).to.be.true; }); + it('should contain a valid url', function () { + // has gdpr consent + expect(request.url).equal(url.cookieBase); + // doens't have gpdr consent + bidderRequest.gdprConsent.vendorData = null; + request = spec.buildRequests([bid], bidderRequest); + expect(request.url).equal(url.cookieLess); + }); it('should have a property a length of bids equal to one if there is only one bid', function () { const data = JSON.parse(request.data); expect(data.hasOwnProperty('bids')).to.be.true; @@ -77,51 +86,51 @@ describe('ProxistoreBidAdapter', function () { expect(data.bids[0].hasOwnProperty('id')).to.be.true; expect(data.bids[0].sizes).to.be.an('array'); }); - }); + it('should correctly set bidfloor on imp when getfloor in scope', function () { + let data = JSON.parse(request.data); + expect(data.bids[0].floor).to.be.null; - describe('interpretResponse', function () { - const responses = { - body: - [{ - cpm: 6.25, - creativeId: '48fd47c9-ce35-4fda-804b-17e16c8c36ac', - currency: 'EUR', - dealId: '2019-10_e3ecad8e-d07a-4c90-ad46-cd0f306c8960', - height: 600, - netRevenue: true, - requestId: '923756713', - ttl: 10, - vastUrl: null, - vastXml: null, - width: 300, - }] - }; - const badResponse = { body: [] }; - const interpretedResponse = spec.interpretResponse(responses, bid)[0]; - it('should send an empty array if body is empty', function () { - expect(spec.interpretResponse(badResponse, bid)).to.be.an('array'); - expect(spec.interpretResponse(badResponse, bid).length).equal(0); - }); - it('should interpret the response correctly if it is valid', function () { - expect(interpretedResponse.cpm).equal(6.25); - expect(interpretedResponse.creativeId).equal('48fd47c9-ce35-4fda-804b-17e16c8c36ac'); - expect(interpretedResponse.currency).equal('EUR'); - expect(interpretedResponse.height).equal(600); - expect(interpretedResponse.width).equal(300); - expect(interpretedResponse.requestId).equal('923756713'); - expect(interpretedResponse.netRevenue).to.be.true; - expect(interpretedResponse.netRevenue).to.be.true; - }); - it('should have a value in the local storage if the response is empty', function() { - spec.interpretResponse(badResponse, bid); - expect(localStorage.getItem(`PX_NoAds_${bid.params.website}`)).to.be.string; + // make it respond with a non USD floor should not send it + bid.getFloor = function () { + return { currency: 'EUR', floor: 1.0 }; + }; + let req = spec.buildRequests([bid], bidderRequest); + data = JSON.parse(req.data); + expect(data.bids[0].floor).equal(1); + bid.getFloor = function () { + return { currency: 'USD', floor: 1.0 }; + }; + req = spec.buildRequests([bid], bidderRequest); + data = JSON.parse(req.data); + expect(data.bids[0].floor).to.be.null; }); }); + describe('interpretResponse', function() { + const emptyResponseParam = {body: []}; + const fakeResponseParam = {body: [ + { ad: '', + cpm: 6.25, + creativeId: '22c3290b-8cd5-4cd6-8e8c-28a2de180ccd', + currency: 'EUR', + dealId: '2021-03_a63ec55e-b9bb-4ca4-b2c9-f456be67e656', + height: 600, + netRevenue: true, + requestId: '3543724f2a033c9', + segments: [], + ttl: 10, + vastUrl: null, + vastXml: null, + width: 300} + ] + }; - describe('interpretResponse', function () { - it('should aways return an empty array', function () { - expect(spec.getUserSyncs()).to.be.an('array'); - expect(spec.getUserSyncs().length).equal(0); + it('should always return an array', function() { + let response = spec.interpretResponse(emptyResponseParam, bid); + expect(response).to.be.an('array'); + expect(response.length).equal(0); + response = spec.interpretResponse(fakeResponseParam, bid); + expect(response).to.be.an('array'); + expect(response.length).equal(1); }); }); });