diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js deleted file mode 100644 index d15a5434e0c..00000000000 --- a/modules/aolBidAdapter.js +++ /dev/null @@ -1,462 +0,0 @@ -import { isInteger, logError, isEmpty, logWarn, getUniqueIdentifierStr, _each, deepSetValue } from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER } from '../src/mediaTypes.js'; - -const AOL_BIDDERS_CODES = { - AOL: 'aol', - VERIZON: 'verizon', - ONEMOBILE: 'onemobile', - ONEDISPLAY: 'onedisplay' -}; - -const AOL_ENDPOINTS = { - DISPLAY: { - GET: 'display-get' - }, - MOBILE: { - GET: 'mobile-get', - POST: 'mobile-post' - } -}; - -const SYNC_TYPES = { - IFRAME: { - TAG: 'iframe', - TYPE: 'iframe' - }, - IMAGE: { - TAG: 'img', - TYPE: 'image' - } -}; - -const SUPPORTED_USER_ID_SOURCES = [ - 'admixer.net', - 'adserver.org', - 'adtelligent.com', - 'akamai.com', - 'amxdt.net', - 'audigent.com', - 'britepool.com', - 'criteo.com', - 'crwdcntrl.net', - 'deepintent.com', - 'epsilon.com', - 'hcn.health', - 'id5-sync.com', - 'idx.lat', - 'intentiq.com', - 'intimatemerger.com', - 'liveintent.com', - 'liveramp.com', - 'mediawallahscript.com', - 'merkleinc.com', - 'netid.de', - 'neustar.biz', - 'nextroll.com', - 'novatiq.com', - 'parrable.com', - 'pubcid.org', - 'quantcast.com', - 'tapad.com', - 'uidapi.com', - 'verizonmedia.com', - 'yahoo.com', - 'zeotap.com' -]; - -const pubapiTemplate = template`${'host'}/pubapi/3.0/${'network'}/${'placement'}/${'pageid'}/${'sizeid'}/ADTECH;v=2;cmd=bid;cors=yes;alias=${'alias'};misc=${'misc'};${'dynamicParams'}`; -const nexageBaseApiTemplate = template`${'host'}/bidRequest?`; -const nexageGetApiTemplate = template`dcn=${'dcn'}&pos=${'pos'}&cmd=bid${'dynamicParams'}`; -const MP_SERVER_MAP = { - us: 'adserver-us.adtech.advertising.com', - eu: 'adserver-eu.adtech.advertising.com', - as: 'adserver-as.adtech.advertising.com' -}; -const NEXAGE_SERVER = 'c2shb.ssp.yahoo.com'; -const ONE_DISPLAY_TTL = 60; -const ONE_MOBILE_TTL = 3600; -const DEFAULT_PROTO = 'https'; - -const NUMERIC_VALUES = { - TRUE: 1, - FALSE: 0 -}; - -function template(strings, ...keys) { - return function (...values) { - let dict = values[values.length - 1] || {}; - let result = [strings[0]]; - keys.forEach(function (key, i) { - let value = isInteger(key) ? values[key] : dict[key]; - result.push(value, strings[i + 1]); - }); - return result.join(''); - }; -} - -function _isMarketplaceBidder(bidderCode) { - return bidderCode === AOL_BIDDERS_CODES.AOL || - bidderCode === AOL_BIDDERS_CODES.VERIZON || - bidderCode === AOL_BIDDERS_CODES.ONEDISPLAY; -} - -function _isOneMobileBidder(bidderCode) { - return bidderCode === AOL_BIDDERS_CODES.AOL || - bidderCode === AOL_BIDDERS_CODES.VERIZON || - bidderCode === AOL_BIDDERS_CODES.ONEMOBILE; -} - -function _isNexageRequestPost(bid) { - if (_isOneMobileBidder(bid.bidder) && bid.params.id && bid.params.imp && bid.params.imp[0]) { - let imp = bid.params.imp[0]; - return imp.id && imp.tagid && imp.banner && imp.banner.w && imp.banner.h; - } -} - -function _isNexageRequestGet(bid) { - return _isOneMobileBidder(bid.bidder) && bid.params.dcn && bid.params.pos; -} - -function isMarketplaceBid(bid) { - return _isMarketplaceBidder(bid.bidder) && bid.params.placement && bid.params.network; -} - -function isMobileBid(bid) { - return _isNexageRequestGet(bid) || _isNexageRequestPost(bid); -} - -function resolveEndpointCode(bid) { - if (_isNexageRequestGet(bid)) { - return AOL_ENDPOINTS.MOBILE.GET; - } else if (_isNexageRequestPost(bid)) { - return AOL_ENDPOINTS.MOBILE.POST; - } else if (isMarketplaceBid(bid)) { - return AOL_ENDPOINTS.DISPLAY.GET; - } -} - -function getSupportedEids(bid) { - return bid.userIdAsEids.filter(eid => { - return SUPPORTED_USER_ID_SOURCES.indexOf(eid.source) !== -1 - }); -} - -export const spec = { - code: AOL_BIDDERS_CODES.AOL, - gvlid: 25, - aliases: [ - AOL_BIDDERS_CODES.ONEMOBILE, - AOL_BIDDERS_CODES.ONEDISPLAY, - AOL_BIDDERS_CODES.VERIZON - ], - supportedMediaTypes: [BANNER], - isBidRequestValid(bid) { - return isMarketplaceBid(bid) || isMobileBid(bid); - }, - buildRequests(bids, bidderRequest) { - const consentData = {}; - if (bidderRequest) { - consentData.gdpr = bidderRequest.gdprConsent; - consentData.uspConsent = bidderRequest.uspConsent; - consentData.gppConsent = bidderRequest.gppConsent; - if (!consentData.gppConsent && bidderRequest.ortb2?.regs?.gpp) { - consentData.gppConsent = { - gppString: bidderRequest.ortb2.regs.gpp, - applicableSections: bidderRequest.ortb2.regs.gpp_sid - } - } - } - - return bids.map(bid => { - const endpointCode = resolveEndpointCode(bid); - - if (endpointCode) { - return this.formatBidRequest(endpointCode, bid, consentData); - } - }); - }, - interpretResponse({ body }, bidRequest) { - if (!body) { - logError('Empty bid response', bidRequest.bidderCode, body); - } else { - let bid = this._parseBidResponse(body, bidRequest); - - if (bid) { - return bid; - } - } - }, - getUserSyncs(options, serverResponses) { - const bidResponse = !isEmpty(serverResponses) && serverResponses[0].body; - - if (bidResponse && bidResponse.ext && bidResponse.ext.pixels) { - return this.parsePixelItems(bidResponse.ext.pixels); - } - - return []; - }, - - formatBidRequest(endpointCode, bid, consentData) { - let bidRequest; - - switch (endpointCode) { - case AOL_ENDPOINTS.DISPLAY.GET: - bidRequest = { - url: this.buildMarketplaceUrl(bid, consentData), - method: 'GET', - ttl: ONE_DISPLAY_TTL - }; - break; - - case AOL_ENDPOINTS.MOBILE.GET: - bidRequest = { - url: this.buildOneMobileGetUrl(bid, consentData), - method: 'GET', - ttl: ONE_MOBILE_TTL - }; - break; - - case AOL_ENDPOINTS.MOBILE.POST: - bidRequest = { - url: this.buildOneMobileBaseUrl(bid), - method: 'POST', - ttl: ONE_MOBILE_TTL, - data: this.buildOpenRtbRequestData(bid, consentData), - options: { - contentType: 'application/json', - customHeaders: { - 'x-openrtb-version': '2.2' - } - } - }; - break; - } - - bidRequest.bidderCode = bid.bidder; - bidRequest.bidId = bid.bidId; - bidRequest.userSyncOn = bid.params.userSyncOn; - - return bidRequest; - }, - buildMarketplaceUrl(bid, consentData) { - const params = bid.params; - const serverParam = params.server; - let regionParam = params.region || 'us'; - let server; - - if (!MP_SERVER_MAP.hasOwnProperty(regionParam)) { - logWarn(`Unknown region '${regionParam}' for AOL bidder.`); - regionParam = 'us'; // Default region. - } - - if (serverParam) { - server = serverParam; - } else { - server = MP_SERVER_MAP[regionParam]; - } - - // Set region param, used by AOL analytics. - params.region = regionParam; - - return this.applyProtocol(pubapiTemplate({ - host: server, - network: params.network, - placement: parseInt(params.placement), - pageid: params.pageId || 0, - sizeid: params.sizeId || 0, - alias: params.alias || getUniqueIdentifierStr(), - misc: new Date().getTime(), // cache busting - dynamicParams: this.formatMarketplaceDynamicParams(params, consentData) - })); - }, - buildOneMobileGetUrl(bid, consentData) { - let { dcn, pos, ext } = bid.params; - if (typeof bid.userId === 'object') { - ext = ext || {}; - let eids = getSupportedEids(bid); - eids.forEach(eid => { - ext['eid' + eid.source] = eid.uids[0].id; - }); - } - let nexageApi = this.buildOneMobileBaseUrl(bid); - if (dcn && pos) { - let dynamicParams = this.formatOneMobileDynamicParams(ext, consentData); - nexageApi += nexageGetApiTemplate({ dcn, pos, dynamicParams }); - } - return nexageApi; - }, - buildOneMobileBaseUrl(bid) { - return this.applyProtocol(nexageBaseApiTemplate({ - host: bid.params.host || NEXAGE_SERVER - })); - }, - applyProtocol(url) { - if (/^https?:\/\//i.test(url)) { - return url; - } - return (url.indexOf('//') === 0) ? `${DEFAULT_PROTO}:${url}` : `${DEFAULT_PROTO}://${url}`; - }, - formatMarketplaceDynamicParams(params = {}, consentData = {}) { - let queryParams = {}; - - Object.assign(queryParams, this.formatKeyValues(params.keyValues)); - Object.assign(queryParams, this.formatConsentData(consentData)); - - let paramsFormatted = ''; - _each(queryParams, (value, key) => { - paramsFormatted += `${key}=${encodeURIComponent(value)};`; - }); - - return paramsFormatted; - }, - formatOneMobileDynamicParams(params = {}, consentData = {}) { - if (this.isSecureProtocol()) { - params.secure = NUMERIC_VALUES.TRUE; - } - - Object.assign(params, this.formatConsentData(consentData)); - - let paramsFormatted = ''; - _each(params, (value, key) => { - paramsFormatted += `&${key}=${encodeURIComponent(value)}`; - }); - - return paramsFormatted; - }, - buildOpenRtbRequestData(bid, consentData = {}) { - let openRtbObject = { - id: bid.params.id, - imp: bid.params.imp - }; - - if (this.isEUConsentRequired(consentData)) { - deepSetValue(openRtbObject, 'regs.ext.gdpr', NUMERIC_VALUES.TRUE); - if (consentData.gdpr.consentString) { - deepSetValue(openRtbObject, 'user.ext.consent', consentData.gdpr.consentString); - } - } - - if (consentData.uspConsent) { - deepSetValue(openRtbObject, 'regs.ext.us_privacy', consentData.uspConsent); - } - - if (typeof bid.userId === 'object') { - openRtbObject.user = openRtbObject.user || {}; - openRtbObject.user.ext = openRtbObject.user.ext || {}; - - let eids = getSupportedEids(bid); - if (eids.length > 0) { - openRtbObject.user.ext.eids = eids - } - } - - return openRtbObject; - }, - isEUConsentRequired(consentData) { - return !!(consentData && consentData.gdpr && consentData.gdpr.gdprApplies); - }, - formatKeyValues(keyValues) { - let keyValuesHash = {}; - - _each(keyValues, (value, key) => { - keyValuesHash[`kv${key}`] = value; - }); - - return keyValuesHash; - }, - formatConsentData(consentData) { - let params = {}; - - if (this.isEUConsentRequired(consentData)) { - params.gdpr = NUMERIC_VALUES.TRUE; - - if (consentData.gdpr.consentString) { - params.euconsent = consentData.gdpr.consentString; - } - } - - if (consentData.uspConsent) { - params.us_privacy = consentData.uspConsent; - } - - if (consentData.gppConsent && consentData.gppConsent.gppString) { - params.gpp = consentData.gppConsent.gppString; - params.gpp_sid = consentData.gppConsent.applicableSections; - } - - return params; - }, - parsePixelItems(pixels) { - let itemsRegExp = /(img|iframe)[\s\S]*?src\s*=\s*("|')(.*?)\2/gi; - let tagNameRegExp = /\w*(?=\s)/; - let srcRegExp = /src=("|')(.*?)\1/; - let pixelsItems = []; - - if (pixels) { - let matchedItems = pixels.match(itemsRegExp); - if (matchedItems) { - matchedItems.forEach(item => { - let tagName = item.match(tagNameRegExp)[0]; - let url = item.match(srcRegExp)[2]; - - if (tagName && url) { - pixelsItems.push({ - type: tagName === SYNC_TYPES.IMAGE.TAG ? SYNC_TYPES.IMAGE.TYPE : SYNC_TYPES.IFRAME.TYPE, - url: url - }); - } - }); - } - } - - return pixelsItems; - }, - - _parseBidResponse(response, bidRequest) { - let bidData; - - try { - bidData = response.seatbid[0].bid[0]; - } catch (e) { - return; - } - - let cpm; - - if (bidData.ext && bidData.ext.encp) { - cpm = bidData.ext.encp; - } else { - cpm = bidData.price; - - if (cpm === null || isNaN(cpm)) { - logError('Invalid price in bid response', AOL_BIDDERS_CODES.AOL, bidData); - return; - } - } - - return { - bidderCode: bidRequest.bidderCode, - requestId: bidRequest.bidId, - ad: bidData.adm, - cpm: cpm, - width: bidData.w, - height: bidData.h, - creativeId: bidData.crid || 0, - pubapiId: response.id, - currency: response.cur || 'USD', - dealId: bidData.dealid, - netRevenue: true, - meta: { - advertiserDomains: bidData && bidData.adomain ? bidData.adomain : [] - }, - ttl: bidRequest.ttl - }; - }, - isOneMobileBidder: _isOneMobileBidder, - isSecureProtocol() { - return document.location.protocol === 'https:'; - } -}; - -registerBidder(spec); diff --git a/modules/aolBidAdapter.md b/modules/aolBidAdapter.md deleted file mode 100644 index 8a9d1e3291d..00000000000 --- a/modules/aolBidAdapter.md +++ /dev/null @@ -1,46 +0,0 @@ -# Overview - -Module Name: AOL Bid Adapter - -Module Type: AOL Adapter - -Maintainer: hb-fe-tech@oath.com - -# Description - -Module that connects to AOL's demand sources - -# Test Parameters -```javascript - var adUnits = [ - { - code: 'test-ad', - sizes: [[300, 250]], - bids: [ - { - bidder: 'onedisplay', - params: { - placement: '3611253', - network: '9599.1', - keyValues: { - test: 'key' - } - } - } - ] - }, - { - code: 'test-mobile-ad', - sizes: [[300, 250]], - bids: [ - { - bidder: 'onemobile', - params: { - dcn: '2c9d2b50015a5aa95b70a9b0b5b10012', - pos: 'header' - } - } - ] - } - ]; -``` diff --git a/test/fixtures/fixtures.js b/test/fixtures/fixtures.js index b66d885c113..7317ea039d1 100644 --- a/test/fixtures/fixtures.js +++ b/test/fixtures/fixtures.js @@ -797,13 +797,6 @@ export function getAdUnits() { 'aId': 3080 } }, - { - 'bidder': 'aol', - 'params': { - 'network': '112345.45', - 'placement': 12345 - } - }, { 'bidder': 'sovrn', 'params': { diff --git a/test/spec/modules/aolBidAdapter_spec.js b/test/spec/modules/aolBidAdapter_spec.js deleted file mode 100644 index 92246f76c7a..00000000000 --- a/test/spec/modules/aolBidAdapter_spec.js +++ /dev/null @@ -1,890 +0,0 @@ -import {expect} from 'chai'; -import * as utils from 'src/utils.js'; -import {spec} from 'modules/aolBidAdapter.js'; -import {createEidsArray} from '../../../modules/userId/eids.js'; - -const DEFAULT_AD_CONTENT = ''; - -let getDefaultBidResponse = () => { - return { - id: '245730051428950632', - cur: 'USD', - seatbid: [{ - bid: [{ - id: 1, - impid: '245730051428950632', - price: 0.09, - adm: DEFAULT_AD_CONTENT, - crid: 'creative-id', - h: 90, - w: 728, - dealid: 'deal-id', - ext: {sizeid: 225} - }] - }] - }; -}; - -let getMarketplaceBidParams = () => { - return { - placement: 1234567, - network: '9599.1' - }; -}; - -let getNexageGetBidParams = () => { - return { - dcn: '2c9d2b50015c5ce9db6aeeed8b9500d6', - pos: 'header' - }; -}; - -let getNexagePostBidParams = () => { - return { - id: 'id-1', - imp: [{ - id: 'id-2', - banner: { - w: '100', - h: '100' - }, - tagid: 'header1' - }] - }; -}; - -let getDefaultBidRequest = () => { - return { - bidderCode: 'aol', - auctionId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', - bidderRequestId: '7101db09af0db2', - start: new Date().getTime(), - bids: [{ - bidder: 'aol', - bidId: '84ab500420319d', - bidderRequestId: '7101db09af0db2', - auctionId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', - placementCode: 'foo', - params: getMarketplaceBidParams() - }] - }; -}; - -let getPixels = () => { - return ''; -}; - -describe('AolAdapter', function () { - const MARKETPLACE_URL = 'https://adserver-us.adtech.advertising.com/pubapi/3.0/'; - const NEXAGE_URL = 'https://c2shb.ssp.yahoo.com/bidRequest?'; - const ONE_DISPLAY_TTL = 60; - const ONE_MOBILE_TTL = 3600; - const SUPPORTED_USER_ID_SOURCES = { - 'admixer.net': '100', - 'adserver.org': '200', - 'adtelligent.com': '300', - 'amxdt.net': '500', - 'audigent.com': '600', - 'britepool.com': '700', - 'criteo.com': '800', - 'crwdcntrl.net': '900', - 'deepintent.com': '1000', - 'epsilon.com': '1100', - 'hcn.health': '1200', - 'id5-sync.com': '1300', - 'idx.lat': '1400', - 'intentiq.com': '1500', - 'intimatemerger.com': '1600', - 'liveintent.com': '1700', - 'liveramp.com': '1800', - 'mediawallahscript.com': '1900', - 'netid.de': '2100', - 'neustar.biz': '2200', - 'pubcid.org': '2600', - 'quantcast.com': '2700', - 'tapad.com': '2800', - 'zeotap.com': '3200' - }; - - const USER_ID_DATA = { - admixerId: SUPPORTED_USER_ID_SOURCES['admixer.net'], - adtelligentId: SUPPORTED_USER_ID_SOURCES['adtelligent.com'], - amxId: SUPPORTED_USER_ID_SOURCES['amxdt.net'], - britepoolid: SUPPORTED_USER_ID_SOURCES['britepool.com'], - criteoId: SUPPORTED_USER_ID_SOURCES['criteo.com'], - connectid: SUPPORTED_USER_ID_SOURCES['verizonmedia.com'], - dmdId: SUPPORTED_USER_ID_SOURCES['hcn.health'], - hadronId: SUPPORTED_USER_ID_SOURCES['audigent.com'], - lotamePanoramaId: SUPPORTED_USER_ID_SOURCES['crwdcntrl.net'], - deepintentId: SUPPORTED_USER_ID_SOURCES['deepintent.com'], - fabrickId: SUPPORTED_USER_ID_SOURCES['neustar.biz'], - idl_env: SUPPORTED_USER_ID_SOURCES['liveramp.com'], - IDP: SUPPORTED_USER_ID_SOURCES['zeotap.com'], - lipb: { - lipbid: SUPPORTED_USER_ID_SOURCES['liveintent.com'], - segments: ['100', '200'] - }, - tdid: SUPPORTED_USER_ID_SOURCES['adserver.org'], - id5id: { - uid: SUPPORTED_USER_ID_SOURCES['id5-sync.com'], - ext: {foo: 'bar'} - }, - idx: SUPPORTED_USER_ID_SOURCES['idx.lat'], - imuid: SUPPORTED_USER_ID_SOURCES['intimatemerger.com'], - intentIqId: SUPPORTED_USER_ID_SOURCES['intentiq.com'], - mwOpenLinkId: SUPPORTED_USER_ID_SOURCES['mediawallahscript.com'], - netId: SUPPORTED_USER_ID_SOURCES['netid.de'], - quantcastId: SUPPORTED_USER_ID_SOURCES['quantcast.com'], - publinkId: SUPPORTED_USER_ID_SOURCES['epsilon.com'], - pubcid: SUPPORTED_USER_ID_SOURCES['pubcid.org'], - tapadId: SUPPORTED_USER_ID_SOURCES['tapad.com'] - }; - - function createCustomBidRequest({bids, params} = {}) { - var bidderRequest = getDefaultBidRequest(); - if (bids && Array.isArray(bids)) { - bidderRequest.bids = bids; - } - if (params) { - bidderRequest.bids.forEach(bid => bid.params = params); - } - return bidderRequest; - } - - describe('interpretResponse()', function () { - let bidderSettingsBackup; - let bidResponse; - let bidRequest; - let logWarnSpy; - let isOneMobileBidderStub; - - beforeEach(function () { - bidderSettingsBackup = $$PREBID_GLOBAL$$.bidderSettings; - bidRequest = { - bidderCode: 'test-bidder-code', - bidId: 'bid-id', - ttl: 1234 - }; - bidResponse = { - body: getDefaultBidResponse() - }; - logWarnSpy = sinon.spy(utils, 'logWarn'); - isOneMobileBidderStub = sinon.stub(spec, 'isOneMobileBidder'); - }); - - afterEach(function () { - $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsBackup; - logWarnSpy.restore(); - isOneMobileBidderStub.restore(); - }); - - it('should return formatted bid response with required properties', function () { - let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); - expect(formattedBidResponse).to.deep.equal({ - bidderCode: bidRequest.bidderCode, - requestId: 'bid-id', - ad: DEFAULT_AD_CONTENT, - cpm: 0.09, - width: 728, - height: 90, - creativeId: 'creative-id', - pubapiId: '245730051428950632', - currency: 'USD', - dealId: 'deal-id', - netRevenue: true, - meta: { - advertiserDomains: [] - }, - ttl: bidRequest.ttl - }); - }); - }); - - describe('buildRequests()', function () { - it('method exists and is a function', function () { - expect(spec.buildRequests).to.exist.and.to.be.a('function'); - }); - - describe('Marketplace', function () { - it('should not return request when no bids are present', function () { - let [request] = spec.buildRequests([]); - expect(request).to.be.undefined; - }); - - it('should return request for Marketplace endpoint', function () { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); - }); - - it('should return request for Marketplace via onedisplay bidder code', function () { - let bidRequest = createCustomBidRequest({ - bids: [{ - bidder: 'onedisplay' - }], - params: getMarketplaceBidParams() - }); - - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); - }); - - it('should return Marketplace request via onedisplay bidder code when' + - 'Marketplace and One Mobile GET params are present', () => { - let bidParams = Object.assign(getMarketplaceBidParams(), getNexageGetBidParams()); - let bidRequest = createCustomBidRequest({ - bids: [{ - bidder: 'onedisplay' - }], - params: bidParams - }); - - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); - }); - - it('should return Marketplace request via onedisplay bidder code when' + - 'Marketplace and One Mobile GET + POST params are present', () => { - let bidParams = Object.assign(getMarketplaceBidParams(), getNexageGetBidParams(), getNexagePostBidParams()); - let bidRequest = createCustomBidRequest({ - bids: [{ - bidder: 'onedisplay' - }], - params: bidParams - }); - - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); - }); - - it('should not resolve endpoint for onedisplay bidder code ' + - 'when only One Mobile params are present', () => { - let bidParams = Object.assign(getNexageGetBidParams(), getNexagePostBidParams()); - let bidRequest = createCustomBidRequest({ - bids: [{ - bidder: 'onedisplay' - }], - params: bidParams - }); - - let [request] = spec.buildRequests(bidRequest.bids); - expect(request).to.be.undefined; - }); - - it('should return Marketplace URL for eu region', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - region: 'eu' - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf('https://adserver-eu.adtech.advertising.com/pubapi/3.0/')) - .to.equal(0); - }); - - it('should return insecure MP URL if insecure server option is present', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - server: 'https://adserver-eu.adtech.advertising.com' - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf('https://adserver-eu.adtech.advertising.com/pubapi/3.0/')) - .to.equal(0); - }); - - it('should return a secure MP URL if relative proto server option is present', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - server: 'https://adserver-eu.adtech.advertising.com' - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf('https://adserver-eu.adtech.advertising.com/pubapi/3.0/')) - .to.equal(0); - }); - - it('should return a secure MP URL when server option without protocol is present', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - server: 'adserver-eu.adtech.advertising.com' - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf('https://adserver-eu.adtech.advertising.com/pubapi/3.0/')) - .to.equal(0); - }); - - it('should return default Marketplace URL in case of unknown region config option', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - region: 'an' - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); - }); - - it('should return url with pubapi bid option', function () { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('cmd=bid;'); - }); - - it('should return url with version 2 of pubapi', function () { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('v=2;'); - }); - - it('should return url with cache busting option', function () { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.match(/misc=\d+/); - }); - - it('should return url with default pageId and sizeId', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1' - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('/pubapi/3.0/9599.1/1234567/0/0/ADTECH;'); - }); - - it('should return url with custom pageId and sizeId when options are present', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - pageId: 1111, - sizeId: 2222 - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('/pubapi/3.0/9599.1/1234567/1111/2222/ADTECH;'); - }); - - it('should return url with default alias if alias param is missing', function () { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.match(/alias=\w+?;/); - }); - - it('should return url with custom alias if it is present', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - alias: 'desktop_articlepage_something_box_300_250' - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('alias=desktop_articlepage_something_box_300_250'); - }); - - it('should return url without bidfloor option if is is missing', function () { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).not.to.contain('bidfloor='); - }); - - it('should return url with key values if keyValues param is present', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - keyValues: { - age: 25, - height: 3.42, - test: 'key' - } - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('kvage=25;kvheight=3.42;kvtest=key'); - }); - - it('should return request object for One Display when configuration is present', function () { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.method).to.equal('GET'); - expect(request.ttl).to.equal(ONE_DISPLAY_TTL); - }); - }); - - describe('One Mobile', function () { - it('should return One Mobile url when One Mobile get params are present', function () { - let bidRequest = createCustomBidRequest({ - params: getNexageGetBidParams() - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(NEXAGE_URL); - }); - - it('should return One Mobile url with different host when host option is present', function () { - let bidParams = Object.assign({ - host: 'https://qa-hb.nexage.com' - }, getNexageGetBidParams()); - let bidRequest = createCustomBidRequest({ - params: bidParams - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('https://qa-hb.nexage.com/bidRequest?'); - }); - - it('should return One Mobile url when One Mobile and Marketplace params are present', function () { - let bidParams = Object.assign(getNexageGetBidParams(), getMarketplaceBidParams()); - let bidRequest = createCustomBidRequest({ - params: bidParams - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(NEXAGE_URL); - }); - - it('should return One Mobile url for onemobile bidder code ' + - 'when One Mobile GET and Marketplace params are present', () => { - let bidParams = Object.assign(getNexageGetBidParams(), getMarketplaceBidParams()); - let bidRequest = createCustomBidRequest({ - bids: [{ - bidder: 'onemobile' - }], - params: bidParams - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(NEXAGE_URL); - }); - - it('should not return any url for onemobile bidder code' + - 'when only Marketplace params are present', () => { - let bidRequest = createCustomBidRequest({ - bids: [{ - bidder: 'onemobile' - }], - params: getMarketplaceBidParams() - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request).to.be.undefined; - }); - - it('should return One Mobile url with required params - dcn & pos', function () { - let bidRequest = createCustomBidRequest({ - params: getNexageGetBidParams() - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(NEXAGE_URL + 'dcn=2c9d2b50015c5ce9db6aeeed8b9500d6&pos=header'); - }); - - it('should return One Mobile url with configured GPP data', function () { - let bidRequest = createCustomBidRequest({ - params: getNexageGetBidParams() - }); - bidRequest.ortb2 = { - regs: { - gpp: 'testgpp', - gpp_sid: [8] - } - } - let [request] = spec.buildRequests(bidRequest.bids, bidRequest); - expect(request.url).to.contain('gpp=testgpp&gpp_sid=8'); - }); - - it('should return One Mobile url with cmd=bid option', function () { - let bidRequest = createCustomBidRequest({ - params: getNexageGetBidParams() - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('cmd=bid'); - }); - - it('should return One Mobile url with generic params if ext option is present', function () { - let bidRequest = createCustomBidRequest({ - params: { - dcn: '54321123', - pos: 'footer-2324', - ext: { - param1: 'val1', - param2: 'val2', - param3: 'val3', - param4: 'val4' - } - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.equal('https://c2shb.ssp.yahoo.com/bidRequest?dcn=54321123&pos=footer-2324&cmd=bid' + - '¶m1=val1¶m2=val2¶m3=val3¶m4=val4'); - }); - - Object.keys(SUPPORTED_USER_ID_SOURCES).forEach(source => { - it(`should set the user ID query param for ${source}`, function () { - let bidRequest = createCustomBidRequest({ - params: getNexageGetBidParams() - }); - bidRequest.bids[0].userId = {}; - bidRequest.bids[0].userIdAsEids = createEidsArray(USER_ID_DATA); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(`&eid${source}=${encodeURIComponent(SUPPORTED_USER_ID_SOURCES[source])}`); - }); - }); - - it('should return request object for One Mobile POST endpoint when POST configuration is present', function () { - let bidConfig = getNexagePostBidParams(); - let bidRequest = createCustomBidRequest({ - params: bidConfig - }); - - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(NEXAGE_URL); - expect(request.method).to.equal('POST'); - expect(request.ttl).to.equal(ONE_MOBILE_TTL); - expect(request.data).to.deep.equal(bidConfig); - expect(request.options).to.deep.equal({ - contentType: 'application/json', - customHeaders: { - 'x-openrtb-version': '2.2' - } - }); - }); - - it('should not return request object for One Mobile POST endpoint' + - 'if required parameters are missed', () => { - let bidRequest = createCustomBidRequest({ - params: { - imp: [] - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request).to.be.undefined; - }); - }); - }); - - describe('buildOpenRtbRequestData', () => { - const bid = { - params: { - id: 'bid-id', - imp: [] - } - }; - let euConsentRequiredStub; - - beforeEach(function () { - euConsentRequiredStub = sinon.stub(spec, 'isEUConsentRequired'); - }); - - afterEach(function () { - euConsentRequiredStub.restore(); - }); - - it('returns the basic bid info when regulation data is omitted', () => { - expect(spec.buildOpenRtbRequestData(bid)).to.deep.equal({ - id: 'bid-id', - imp: [] - }); - }); - - it('returns the basic bid info with gdpr data when gdpr consent data is included', () => { - let consentData = { - gdpr: { - consentString: 'someEUConsent' - } - }; - euConsentRequiredStub.returns(true); - expect(spec.buildOpenRtbRequestData(bid, consentData)).to.deep.equal({ - id: 'bid-id', - imp: [], - regs: { - ext: { - gdpr: 1 - } - }, - user: { - ext: { - consent: 'someEUConsent' - } - } - }); - }); - - it('returns the basic bid info with CCPA data when CCPA consent data is included', () => { - let consentData = { - uspConsent: 'someUSPConsent' - }; - expect(spec.buildOpenRtbRequestData(bid, consentData)).to.deep.equal({ - id: 'bid-id', - imp: [], - regs: { - ext: { - us_privacy: 'someUSPConsent' - } - } - }); - }); - - it('returns the basic bid info with GDPR and CCPA data when GDPR and CCPA consent data is included', () => { - let consentData = { - gdpr: { - consentString: 'someEUConsent' - }, - uspConsent: 'someUSPConsent' - }; - euConsentRequiredStub.returns(true); - expect(spec.buildOpenRtbRequestData(bid, consentData)).to.deep.equal({ - id: 'bid-id', - imp: [], - regs: { - ext: { - gdpr: 1, - us_privacy: 'someUSPConsent' - } - }, - user: { - ext: { - consent: 'someEUConsent' - } - } - }); - }); - - it('returns the bid object with eid array populated with PB set eids', () => { - let userIdBid = Object.assign({ - userId: {} - }, bid); - userIdBid.userIdAsEids = createEidsArray(USER_ID_DATA); - expect(spec.buildOpenRtbRequestData(userIdBid)).to.deep.equal({ - id: 'bid-id', - imp: [], - user: { - ext: { - eids: userIdBid.userIdAsEids - } - } - }); - }); - }); - - describe('getUserSyncs()', function () { - let serverResponses; - let bidResponse; - - beforeEach(function () { - bidResponse = getDefaultBidResponse(); - bidResponse.ext = { - pixels: getPixels() - }; - - serverResponses = [ - {body: bidResponse} - ]; - }); - - it('should return user syncs if pixels are present in the response', function () { - let userSyncs = spec.getUserSyncs({}, serverResponses); - - expect(userSyncs).to.deep.equal([ - {type: 'image', url: 'img.org'}, - {type: 'iframe', url: 'pixels1.org'} - ]); - }); - - it('should not return user syncs if pixels are not present', function () { - bidResponse.ext.pixels = null; - let userSyncs = spec.getUserSyncs({}, serverResponses); - - expect(userSyncs).to.deep.equal([]); - }); - }); - - describe('isOneMobileBidder()', function () { - it('should return false when when bidderCode is not present', () => { - expect(spec.isOneMobileBidder(null)).to.be.false; - }); - - it('should return false for unknown bidder code', function () { - expect(spec.isOneMobileBidder('unknownBidder')).to.be.false; - }); - - it('should return true for aol bidder code', function () { - expect(spec.isOneMobileBidder('aol')).to.be.true; - }); - - it('should return true for one mobile bidder code', function () { - expect(spec.isOneMobileBidder('onemobile')).to.be.true; - }); - }); - - describe('isEUConsentRequired()', function () { - it('should return false when consentData object is not present', function () { - expect(spec.isEUConsentRequired(null)).to.be.false; - }); - - it('should return true when gdprApplies equals true and consentString is not present', function () { - let consentData = { - gdpr: { - consentString: null, - gdprApplies: true - } - }; - - expect(spec.isEUConsentRequired(consentData)).to.be.true; - }); - - it('should return false when consentString is present and gdprApplies equals false', function () { - let consentData = { - gdpr: { - consentString: 'consent-string', - gdprApplies: false - } - }; - - expect(spec.isEUConsentRequired(consentData)).to.be.false; - }); - - it('should return true when consentString is present and gdprApplies equals true', function () { - let consentData = { - gdpr: { - consentString: 'consent-string', - gdprApplies: true - } - }; - - expect(spec.isEUConsentRequired(consentData)).to.be.true; - }); - }); - - describe('formatMarketplaceDynamicParams()', function () { - let formatConsentDataStub; - let formatKeyValuesStub; - - beforeEach(function () { - formatConsentDataStub = sinon.stub(spec, 'formatConsentData'); - formatKeyValuesStub = sinon.stub(spec, 'formatKeyValues'); - }); - - afterEach(function () { - formatConsentDataStub.restore(); - formatKeyValuesStub.restore(); - }); - - it('should return empty string when params are not present', function () { - expect(spec.formatMarketplaceDynamicParams()).to.be.equal(''); - }); - - it('should return formatted EU consent params when formatConsentData returns GDPR data', function () { - formatConsentDataStub.returns({ - euconsent: 'test-consent', - gdpr: 1 - }); - expect(spec.formatMarketplaceDynamicParams()).to.be.equal('euconsent=test-consent;gdpr=1;'); - }); - - it('should return formatted US privacy params when formatConsentData returns USP data', function () { - formatConsentDataStub.returns({ - us_privacy: 'test-usp-consent' - }); - expect(spec.formatMarketplaceDynamicParams()).to.be.equal('us_privacy=test-usp-consent;'); - }); - - it('should return formatted EU and USP consent params when formatConsentData returns all data', function () { - formatConsentDataStub.returns({ - euconsent: 'test-consent', - gdpr: 1, - us_privacy: 'test-usp-consent' - }); - expect(spec.formatMarketplaceDynamicParams()).to.be.equal( - 'euconsent=test-consent;gdpr=1;us_privacy=test-usp-consent;'); - }); - - it('should return formatted gpp privacy params when formatConsentData returns GPP data', function () { - formatConsentDataStub.returns({ - gpp: 'gppstring', - gpp_sid: [6, 7] - }); - expect(spec.formatMarketplaceDynamicParams()).to.be.equal('gpp=gppstring;gpp_sid=6%2C7;'); - }); - - it('should return formatted params when formatKeyValues returns data', function () { - formatKeyValuesStub.returns({ - param1: 'val1', - param2: 'val2', - param3: 'val3' - }); - expect(spec.formatMarketplaceDynamicParams()).to.be.equal('param1=val1;param2=val2;param3=val3;'); - }); - }); - - describe('formatOneMobileDynamicParams()', function () { - let euConsentRequiredStub; - let secureProtocolStub; - - beforeEach(function () { - euConsentRequiredStub = sinon.stub(spec, 'isEUConsentRequired'); - secureProtocolStub = sinon.stub(spec, 'isSecureProtocol'); - }); - - afterEach(function () { - euConsentRequiredStub.restore(); - secureProtocolStub.restore(); - }); - - it('should return empty string when params are not present', function () { - expect(spec.formatOneMobileDynamicParams()).to.be.equal(''); - }); - - it('should return formatted params when params are present', function () { - let params = { - param1: 'val1', - param2: 'val2', - param3: 'val3' - }; - expect(spec.formatOneMobileDynamicParams(params)).to.contain('¶m1=val1¶m2=val2¶m3=val3'); - }); - - it('should return formatted gdpr params when isEUConsentRequired returns true', function () { - let consentData = { - gdpr: { - consentString: 'test-consent' - } - }; - euConsentRequiredStub.returns(true); - expect(spec.formatOneMobileDynamicParams({}, consentData)).to.be.equal('&gdpr=1&euconsent=test-consent'); - }); - - it('should return formatted US privacy params when consentData contains USP data', function () { - let consentData = { - uspConsent: 'test-usp-consent' - }; - expect(spec.formatMarketplaceDynamicParams({}, consentData)).to.be.equal('us_privacy=test-usp-consent;'); - }); - - it('should return formatted EU and USP consent params when consentData contains gdpr and usp values', function () { - euConsentRequiredStub.returns(true); - let consentData = { - gdpr: { - consentString: 'test-consent' - }, - uspConsent: 'test-usp-consent' - }; - expect(spec.formatMarketplaceDynamicParams({}, consentData)).to.be.equal( - 'gdpr=1;euconsent=test-consent;us_privacy=test-usp-consent;'); - }); - - it('should return formatted secure param when isSecureProtocol returns true', function () { - secureProtocolStub.returns(true); - expect(spec.formatOneMobileDynamicParams()).to.be.equal('&secure=1'); - }); - }); -});