diff --git a/integrationExamples/gpt/userId_example.html b/integrationExamples/gpt/userId_example.html index 7886e5b13ca..53c58e8e87e 100644 --- a/integrationExamples/gpt/userId_example.html +++ b/integrationExamples/gpt/userId_example.html @@ -189,6 +189,16 @@ name: "sharedid", expires: 28 } + }, { + name: "liveIntentId", + params: { + publisherId: "9896876" + }, + storage: { + type: "cookie", + name: "_li_pbid", + expires: 28 + } }], syncDelay: 5000, auctionDelay: 1000 diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 95524190e74..5df2af7f32e 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -5,8 +5,12 @@ import * as utils from '../src/utils.js'; const BIDDER_CODE = '33across'; const END_POINT = 'https://ssc.33across.com/api/v1/hb'; const SYNC_ENDPOINT = 'https://ssc-cms.33across.com/ps/?m=xch&rt=html&ru=deb'; +const MEDIA_TYPE = 'banner'; +const CURRENCY = 'USD'; -const adapterState = {}; +const adapterState = { + uniqueSiteIds: [] +}; const NON_MEASURABLE = 'nm'; @@ -65,11 +69,27 @@ function _getAdSlotHTMLElement(adUnitCode) { // Infer the necessary data from valid bid for a minimal ttxRequest and create HTTP request // NOTE: At this point, TTX only accepts request for a single impression -function _createServerRequest(bidRequest, gdprConsent = {}, pageUrl) { +function _createServerRequest({bidRequest, gdprConsent = {}, uspConsent, pageUrl}) { const ttxRequest = {}; const params = bidRequest.params; const element = _getAdSlotHTMLElement(bidRequest.adUnitCode); const sizes = _transformSizes(bidRequest.sizes); + + let format; + + // We support size based bidfloors so obtain one if there's a rule associated + if (typeof bidRequest.getFloor === 'function') { + let getFloor = bidRequest.getFloor.bind(bidRequest); + + format = sizes.map((size) => { + const formatExt = _getBidFloors(getFloor, size); + + return Object.assign({}, size, formatExt); + }); + } else { + format = sizes; + } + const minSize = _getMinSize(sizes); const viewabilityAmount = _isViewabilityMeasurable(element) @@ -84,7 +104,7 @@ function _createServerRequest(bidRequest, gdprConsent = {}, pageUrl) { ttxRequest.imp = []; ttxRequest.imp[0] = { banner: { - format: sizes.map(size => Object.assign(size, {ext: {}})) + format }, ext: { ttx: { @@ -97,6 +117,7 @@ function _createServerRequest(bidRequest, gdprConsent = {}, pageUrl) { if (pageUrl) { ttxRequest.site.page = pageUrl; } + // Go ahead send the bidId in request to 33exchange so it's kept track of in the bid response and // therefore in ad targetting process ttxRequest.id = bidRequest.bidId; @@ -109,19 +130,28 @@ function _createServerRequest(bidRequest, gdprConsent = {}, pageUrl) { }; ttxRequest.regs = { ext: { - gdpr: (gdprConsent.gdprApplies === true) ? 1 : 0 + gdpr: (gdprConsent.gdprApplies === true) ? 1 : 0, + us_privacy: uspConsent || null } }; ttxRequest.ext = { ttx: { prebidStartedAt: Date.now(), - caller: [{ + caller: [ { 'name': 'prebidjs', 'version': '$prebid.version$' - }] + } ] } }; + if (bidRequest.schain) { + ttxRequest.source = { + ext: { + schain: bidRequest.schain + } + } + } + // Finally, set the openRTB 'test' param if this is to be a test bid if (params.test === 1) { ttxRequest.test = 1; @@ -134,6 +164,7 @@ function _createServerRequest(bidRequest, gdprConsent = {}, pageUrl) { contentType: 'text/plain', withCredentials: true }; + // Allow the ability to configure the HB endpoint for testing purposes. const ttxSettings = config.getConfig('ttxSettings'); const url = (ttxSettings && ttxSettings.url) || END_POINT; @@ -148,15 +179,15 @@ function _createServerRequest(bidRequest, gdprConsent = {}, pageUrl) { } // Sync object will always be of type iframe for TTX -function _createSync({siteId = 'zzz000000000003zzz', gdprConsent = {}}) { +function _createSync({ siteId = 'zzz000000000003zzz', gdprConsent = {}, uspConsent }) { const ttxSettings = config.getConfig('ttxSettings'); const syncUrl = (ttxSettings && ttxSettings.syncUrl) || SYNC_ENDPOINT; - const {consentString, gdprApplies} = gdprConsent; + const { consentString, gdprApplies } = gdprConsent; const sync = { type: 'iframe', - url: `${syncUrl}&id=${siteId}&gdpr_consent=${encodeURIComponent(consentString)}` + url: `${syncUrl}&id=${siteId}&gdpr_consent=${encodeURIComponent(consentString)}&us_privacy=${encodeURIComponent(uspConsent)}` }; if (typeof gdprApplies === 'boolean') { @@ -166,6 +197,24 @@ function _createSync({siteId = 'zzz000000000003zzz', gdprConsent = {}}) { return sync; } +function _getBidFloors(getFloor, size) { + const bidFloors = getFloor({ + currency: CURRENCY, + mediaType: MEDIA_TYPE, + size: [ size.w, size.h ] + }); + + if (!isNaN(bidFloors.floor) && (bidFloors.currency === CURRENCY)) { + return { + ext: { + ttx: { + bidfloors: [ bidFloors.floor ] + } + } + } + } +} + function _getSize(size) { return { w: parseInt(size[0], 10), @@ -192,7 +241,7 @@ function _getBoundingBox(element, { w, h } = {}) { function _transformSizes(sizes) { if (utils.isArray(sizes) && sizes.length === 2 && !utils.isArray(sizes[0])) { - return [_getSize(sizes)]; + return [ _getSize(sizes) ]; } return sizes.map(_getSize); @@ -239,7 +288,8 @@ function _getPercentInView(element, topWin, { w, h } = {}) { bottom: topWin.innerHeight }, elementBoundingBox ]); - let elementInViewArea, elementTotalArea; + let elementInViewArea, + elementTotalArea; if (elementInViewBoundingBox !== null) { // Some or all of the element is in view @@ -301,11 +351,19 @@ function buildRequests(bidRequests, bidderRequest) { gdprApplies: false }, bidderRequest && bidderRequest.gdprConsent); + const uspConsent = bidderRequest && bidderRequest.uspConsent; const pageUrl = (bidderRequest && bidderRequest.refererInfo) ? (bidderRequest.refererInfo.referer) : (undefined); adapterState.uniqueSiteIds = bidRequests.map(req => req.params.siteId).filter(utils.uniques); - return bidRequests.map(req => _createServerRequest(req, gdprConsent, pageUrl)); + return bidRequests.map(bidRequest => _createServerRequest( + { + bidRequest, + gdprConsent, + uspConsent, + pageUrl + }) + ); } // NOTE: At this point, the response from 33exchange will only ever contain one bid i.e. the highest bid @@ -324,8 +382,17 @@ function interpretResponse(serverResponse, bidRequest) { // Else no syncs // For logic on how we handle gdpr data see _createSyncs and module's unit tests // '33acrossBidAdapter#getUserSyncs' -function getUserSyncs(syncOptions, responses, gdprConsent) { - return (syncOptions.iframeEnabled) ? adapterState.uniqueSiteIds.map((siteId) => _createSync({gdprConsent, siteId})) : ([]); +function getUserSyncs(syncOptions, responses, gdprConsent, uspConsent) { + const syncUrls = ( + (syncOptions.iframeEnabled) + ? adapterState.uniqueSiteIds.map((siteId) => _createSync({ gdprConsent, uspConsent, siteId })) + : ([]) + ); + + // Clear adapter state of siteID's since we don't need this info anymore. + adapterState.uniqueSiteIds = []; + + return syncUrls; } export const spec = { diff --git a/modules/appierBidAdapter.js b/modules/appierBidAdapter.js index 660820daca3..1940233a0b4 100644 --- a/modules/appierBidAdapter.js +++ b/modules/appierBidAdapter.js @@ -16,6 +16,7 @@ const BIDDER_API_ENDPOINT = '/v1/prebid/bid'; export const spec = { code: 'appier', + aliases: ['appierBR', 'appierExt', 'appierGM'], supportedMediaTypes: SUPPORTED_AD_TYPES, /** diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 5e3b6a06011..d853ca184ce 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -11,11 +11,29 @@ import { getStorageManager } from '../src/storageManager.js'; const BIDDER_CODE = 'appnexus'; const URL = 'https://ib.adnxs.com/ut/v3/prebid'; -const VIDEO_TARGETING = ['id', 'mimes', 'minduration', 'maxduration', - 'startdelay', 'skippable', 'playback_method', 'frameworks']; +const VIDEO_TARGETING = ['id', 'minduration', 'maxduration', + 'skippable', 'playback_method', 'frameworks', 'context', 'skipoffset']; const USER_PARAMS = ['age', 'externalUid', 'segments', 'gender', 'dnt', 'language']; const APP_DEVICE_PARAMS = ['geo', 'device_id']; // appid is collected separately const DEBUG_PARAMS = ['enabled', 'dongle', 'member_id', 'debug_timeout']; +const VIDEO_MAPPING = { + playback_method: { + 'unknown': 0, + 'auto_play_sound_on': 1, + 'auto_play_sound_off': 2, + 'click_to_play': 3, + 'mouse_over': 4, + 'auto_play_sound_unknown': 5 + }, + context: { + 'unknown': 0, + 'pre_roll': 1, + 'mid_roll': 2, + 'post_roll': 3, + 'outstream': 4, + 'in-banner': 5 + } +}; const NATIVE_MAPPING = { body: 'description', body2: 'desc2', @@ -711,7 +729,18 @@ function bidToTag(bid) { // place any valid video params on the tag Object.keys(bid.params.video) .filter(param => includes(VIDEO_TARGETING, param)) - .forEach(param => tag.video[param] = bid.params.video[param]); + .forEach(param => { + switch (param) { + case 'context': + case 'playback_method': + let type = bid.params.video[param]; + type = (utils.isArray(type)) ? type[0] : type; + tag.video[param] = VIDEO_MAPPING[param][type]; + break; + default: + tag.video[param] = bid.params.video[param]; + } + }); } if (bid.renderer) { diff --git a/modules/appnexusBidAdapter.md b/modules/appnexusBidAdapter.md index a1d12243888..6ec40e83b41 100644 --- a/modules/appnexusBidAdapter.md +++ b/modules/appnexusBidAdapter.md @@ -99,7 +99,7 @@ var adUnits = [ placementId: 13232385, video: { skippable: true, - playback_method: ['auto_play_sound_off'] + playback_method: 'auto_play_sound_off' } } } diff --git a/modules/gmosspBidAdapter.js b/modules/gmosspBidAdapter.js new file mode 100644 index 00000000000..d9dc8f7641a --- /dev/null +++ b/modules/gmosspBidAdapter.js @@ -0,0 +1,134 @@ +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import * as utils from '../src/utils.js'; +import { config } from '../src/config.js'; +import { BANNER } from '../src/mediaTypes.js'; + +const BIDDER_CODE = 'gmossp'; +const ENDPOINT = 'https://sp.gmossp-sp.jp/hb/prebid/query.ad'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + + /** + * Determines whether or not the given bid request is valid. + * + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: function (bid) { + return !!(bid.params.sid); + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {validBidRequests[]} - an array of bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function (validBidRequests, bidderRequest) { + const bidRequests = []; + + const url = bidderRequest.refererInfo.referer; + const cur = getCurrencyType(); + const dnt = utils.getDNT() ? '1' : '0'; + + for (let i = 0; i < validBidRequests.length; i++) { + let queryString = ''; + + const request = validBidRequests[i]; + const tid = request.transactionId; + const bid = request.bidId; + const ver = '$prebid.version$'; + const sid = utils.getBidIdParameter('sid', request.params); + + queryString = utils.tryAppendQueryString(queryString, 'tid', tid); + queryString = utils.tryAppendQueryString(queryString, 'bid', bid); + queryString = utils.tryAppendQueryString(queryString, 'ver', ver); + queryString = utils.tryAppendQueryString(queryString, 'sid', sid); + queryString = utils.tryAppendQueryString(queryString, 'url', url); + queryString = utils.tryAppendQueryString(queryString, 'cur', cur); + queryString = utils.tryAppendQueryString(queryString, 'dnt', dnt); + + bidRequests.push({ + method: 'GET', + url: ENDPOINT, + data: queryString + }); + } + return bidRequests; + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} serverResponse A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function (bidderResponse, requests) { + const res = bidderResponse.body; + + if (utils.isEmpty(res)) { + return []; + } + + try { + res.imps.forEach(impTracker => { + const tracker = utils.createTrackPixelHtml(impTracker); + res.ad += tracker; + }); + } catch (error) { + utils.logError('Error appending tracking pixel', error); + } + + const bid = { + requestId: res.bid, + cpm: res.price, + currency: res.cur, + width: res.w, + height: res.h, + ad: res.ad, + creativeId: res.creativeId, + netRevenue: true, + ttl: res.ttl || 300 + }; + + return [bid]; + }, + + /** + * Register the user sync pixels which should be dropped after the auction. + * + * @param {SyncOptions} syncOptions Which user syncs are allowed? + * @param {ServerResponse[]} serverResponses List of server's responses. + * @return {UserSync[]} The user syncs which should be dropped. + */ + getUserSyncs: function(syncOptions, serverResponses) { + const syncs = []; + if (!serverResponses.length) { + return syncs; + } + + serverResponses.forEach(res => { + if (syncOptions.pixelEnabled && res.body && res.body.syncs.length) { + res.body.syncs.forEach(sync => { + syncs.push({ + type: 'image', + url: sync + }) + }) + } + }) + return syncs; + }, + +}; + +function getCurrencyType() { + if (config.getConfig('currency.adServerCurrency')) { + return config.getConfig('currency.adServerCurrency'); + } + return 'JPY'; +} + +registerBidder(spec); diff --git a/modules/gmosspBidAdapter.md b/modules/gmosspBidAdapter.md new file mode 100644 index 00000000000..4f63582ef9a --- /dev/null +++ b/modules/gmosspBidAdapter.md @@ -0,0 +1,36 @@ +# Overview + +``` +Module Name: GMOSSP Bid Adapter +Module Type: Bidder Adapter +Maintainer: dev@ml.gmo-am.jp +``` + +# Description +Connects to GMOSSP exchange for bids. +GMOSSP bid adapter supports Banner. + +# Test Parameters +``` +var adUnits = [ + // Banner adUnit + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [320, 50], + [320, 100] + ] + } + }, + bids: [{ + bidder: 'gmossp', + params: { + sid: '61590' + } + }] + } +]; +``` \ No newline at end of file diff --git a/modules/liveIntentIdSystem.js b/modules/liveIntentIdSystem.js index b0e8cfc1c0f..bd2638e5936 100644 --- a/modules/liveIntentIdSystem.js +++ b/modules/liveIntentIdSystem.js @@ -21,6 +21,9 @@ let liveConnect = null; * This function is used in tests */ export function reset() { + if (window && window.liQ) { + window.liQ = []; + } eventFired = false; liveConnect = null; } @@ -45,16 +48,12 @@ function parseLiveIntentCollectorConfig(collectConfig) { } function initializeLiveConnect(configParams) { + configParams = configParams || {}; if (liveConnect) { return liveConnect; } - const publisherId = configParams && configParams.publisherId; - if (!publisherId && typeof publisherId !== 'string') { - utils.logError(`${MODULE_NAME} - publisherId must be defined, not a '${publisherId}'`); - return; - } - + const publisherId = configParams.publisherId || 'any'; const identityResolutionConfig = { source: 'prebid', publisherId: publisherId @@ -65,20 +64,11 @@ function initializeLiveConnect(configParams) { if (configParams.partner) { identityResolutionConfig.source = configParams.partner } - if (configParams.storage && configParams.storage.expires) { - identityResolutionConfig.expirationDays = configParams.storage.expires; - } - if (configParams.ajaxTimeout) { - identityResolutionConfig.ajaxTimeout = configParams.ajaxTimeout; - } const liveConnectConfig = parseLiveIntentCollectorConfig(configParams.liCollectConfig); liveConnectConfig.wrapperName = 'prebid'; liveConnectConfig.identityResolutionConfig = identityResolutionConfig; liveConnectConfig.identifiersToResolve = configParams.identifiersToResolve || []; - if (configParams.providedIdentifierName) { - liveConnectConfig.providedIdentifierName = configParams.providedIdentifierName; - } const usPrivacyString = uspDataHandler.getConsentData(); if (usPrivacyString) { liveConnectConfig.usPrivacyString = usPrivacyString; @@ -120,10 +110,10 @@ export const liveIntentIdSubmodule = { return { 'lipb': { ...base, ...value } }; } - if (configParams) { + if (!liveConnect) { initializeLiveConnect(configParams); - tryFireEvent(); } + tryFireEvent(); return (value && typeof value['unifiedId'] === 'string') ? composeIdObject(value) : undefined; }, diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 4502dc66a65..7314d81aee6 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -10,7 +10,6 @@ const USER_SYNC_URL_IFRAME = 'https://ads.pubmatic.com/AdServer/js/showad.js#PIX const USER_SYNC_URL_IMAGE = 'https://image8.pubmatic.com/AdServer/ImgSync?p='; const DEFAULT_CURRENCY = 'USD'; const AUCTION_TYPE = 1; -const PUBMATIC_DIGITRUST_KEY = 'nFIn8aLzbd'; const UNDEFINED = undefined; const DEFAULT_WIDTH = 0; const DEFAULT_HEIGHT = 0; @@ -586,96 +585,41 @@ function _createImpressionObject(bid, conf) { impObj.banner = bannerObj; } + _addFloorFromFloorModule(impObj, bid); + return impObj.hasOwnProperty(BANNER) || impObj.hasOwnProperty(NATIVE) || impObj.hasOwnProperty(VIDEO) ? impObj : UNDEFINED; } -function _getDigiTrustObject(key) { - function getDigiTrustId() { - let digiTrustUser = window.DigiTrust && (config.getConfig('digiTrustId') || window.DigiTrust.getUser({member: key})); - return (digiTrustUser && digiTrustUser.success && digiTrustUser.identity) || null; - } - let digiTrustId = getDigiTrustId(); - // Verify there is an ID and this user has not opted out - if (!digiTrustId || (digiTrustId.privacy && digiTrustId.privacy.optout)) { - return null; - } - return digiTrustId; -} - -function _handleDigitrustId(eids) { - let digiTrustId = _getDigiTrustObject(PUBMATIC_DIGITRUST_KEY); - if (digiTrustId !== null) { - eids.push({ - 'source': 'digitru.st', - 'uids': [{ - 'id': digiTrustId.id || '', - 'atype': 1, - 'ext': { - 'keyv': parseInt(digiTrustId.keyv) || 0 +function _addFloorFromFloorModule(impObj, bid) { + let bidFloor = -1; + // get lowest floor from floorModule + if (typeof bid.getFloor === 'function' && !config.getConfig('pubmatic.disableFloors')) { + [BANNER, VIDEO, NATIVE].forEach(mediaType => { + if (impObj.hasOwnProperty(mediaType)) { + let floorInfo = bid.getFloor({ currency: impObj.bidfloorcur, mediaType: mediaType, size: '*' }); + if (typeof floorInfo === 'object' && floorInfo.currency === impObj.bidfloorcur && !isNaN(parseInt(floorInfo.floor))) { + let mediaTypeFloor = parseFloat(floorInfo.floor); + bidFloor = (bidFloor == -1 ? mediaTypeFloor : Math.min(mediaTypeFloor, bidFloor)) } - }] + } }); } -} - -function _handleTTDId(eids, validBidRequests) { - let ttdId = null; - let adsrvrOrgId = config.getConfig('adsrvrOrgId'); - if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.tdid'))) { - ttdId = validBidRequests[0].userId.tdid; - } else if (adsrvrOrgId && utils.isStr(adsrvrOrgId.TDID)) { - ttdId = adsrvrOrgId.TDID; - } - - if (ttdId !== null) { - eids.push({ - 'source': 'adserver.org', - 'uids': [{ - 'id': ttdId, - 'atype': 1, - 'ext': { - 'rtiPartner': 'TDID' - } - }] - }); + // get highest from impObj.bidfllor and floor from floor module + // as we are using Math.max, it is ok if we have not got any floor from floorModule, then value of bidFloor will be -1 + if (impObj.bidfloor) { + bidFloor = Math.max(bidFloor, impObj.bidfloor) } -} -/** - * Produces external userid object in ortb 3.0 model. - */ -function _addExternalUserId(eids, value, source, atype) { - if (utils.isStr(value)) { - eids.push({ - source, - uids: [{ - id: value, - atype - }] - }); - } + // assign value only if bidFloor is > 0 + impObj.bidfloor = ((!isNaN(bidFloor) && bidFloor > 0) ? bidFloor : UNDEFINED); } function _handleEids(payload, validBidRequests) { - let eids = []; - _handleDigitrustId(eids); - _handleTTDId(eids, validBidRequests); - const bidRequest = validBidRequests[0]; - if (bidRequest && bidRequest.userId) { - _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.pubcid`), 'pubcid.org', 1); - _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.digitrustid.data.id`), 'digitru.st', 1); - _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.id5id`), 'id5-sync.com', 1); - _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.criteoId`), 'criteo.com', 1);// replacing criteoRtus - _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.idl_env`), 'liveramp.com', 1); - _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.lipb.lipbid`), 'liveintent.com', 1); - _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.parrableid`), 'parrable.com', 1); - _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.britepoolid`), 'britepool.com', 1); - _addExternalUserId(eids, utils.deepAccess(bidRequest, `userId.netId`), 'netid.de', 1); - } - if (eids.length > 0) { - payload.user.eids = eids; + const bidUserIdAsEids = utils.deepAccess(validBidRequests, '0.userIdAsEids'); + if (utils.isArray(bidUserIdAsEids) && bidUserIdAsEids.length > 0) { + utils.deepSetValue(payload, 'user.eids', bidUserIdAsEids); } } diff --git a/modules/smartadserverBidAdapter.js b/modules/smartadserverBidAdapter.js index 15808a516c8..97dd43fc5ba 100644 --- a/modules/smartadserverBidAdapter.js +++ b/modules/smartadserverBidAdapter.js @@ -9,6 +9,9 @@ import { import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { + createEidsArray +} from './userId/eids.js'; const BIDDER_CODE = 'smartadserver'; export const spec = { code: BIDDER_CODE, @@ -99,6 +102,10 @@ export const spec = { payload.gdpr = bidderRequest.gdprConsent.gdprApplies; // we're handling the undefined case server side } + if (bid && bid.userId) { + payload.eids = createEidsArray(bid.userId); + } + if (bidderRequest && bidderRequest.uspConsent) { payload.us_privacy = bidderRequest.uspConsent; } diff --git a/modules/sovrnBidAdapter.js b/modules/sovrnBidAdapter.js index 98c8c8e3b33..f3260668b74 100644 --- a/modules/sovrnBidAdapter.js +++ b/modules/sovrnBidAdapter.js @@ -25,18 +25,13 @@ export const spec = { let sovrnImps = []; let iv; let schain; - let digitrust; + let unifiedID; utils._each(bidReqs, function (bid) { - if (!digitrust) { - const bidRequestDigitrust = utils.deepAccess(bid, 'userId.digitrustid.data'); - if (bidRequestDigitrust && (!bidRequestDigitrust.privacy || !bidRequestDigitrust.privacy.optout)) { - digitrust = { - id: bidRequestDigitrust.id, - keyv: bidRequestDigitrust.keyv - } - } + if (!unifiedID) { + unifiedID = utils.deepAccess(bid, 'userId.tdid'); } + if (bid.schain) { schain = schain || bid.schain; } @@ -47,6 +42,7 @@ export const spec = { bidSizes = bidSizes.filter(size => utils.isArray(size)) const processedSizes = bidSizes.map(size => ({w: parseInt(size[0], 10), h: parseInt(size[1], 10)})) sovrnImps.push({ + adunitcode: bid.adUnitCode, id: bid.bidId, banner: { format: processedSizes, @@ -88,15 +84,22 @@ export const spec = { utils.deepSetValue(sovrnBidReq, 'regs.ext.us_privacy', bidderRequest.uspConsent); } - if (digitrust) { - utils.deepSetValue(sovrnBidReq, 'user.ext.digitrust', { - id: digitrust.id, - keyv: digitrust.keyv - }) + if (unifiedID) { + const idArray = [{ + source: 'adserver.org', + uids: [ + { + id: unifiedID, + ext: { + rtiPartner: 'TDID' + } + } + ] + }] + utils.deepSetValue(sovrnBidReq, 'user.ext.eids', idArray) } - let url = `https://ap.lijit.com/rtb/bid?` + - `src=$$REPO_AND_VERSION$$`; + let url = `https://ap.lijit.com/rtb/bid?src=$$REPO_AND_VERSION$$`; if (iv) url += `&iv=${iv}`; return { @@ -176,7 +179,6 @@ export const spec = { .forEach(url => tracks.push({ type: 'image', url })) } } - return tracks } catch (e) { return [] diff --git a/modules/tripleliftBidAdapter.js b/modules/tripleliftBidAdapter.js index 8b21f334233..af904aedc11 100644 --- a/modules/tripleliftBidAdapter.js +++ b/modules/tripleliftBidAdapter.js @@ -111,7 +111,7 @@ function _buildPostBody(bidRequests) { return { id: index, tagid: bid.params.inventoryCode, - floor: bid.params.floor, + floor: _getFloor(bid), banner: { format: _sizes(bid.sizes) } @@ -138,6 +138,22 @@ function _buildPostBody(bidRequests) { return data; } +function _getFloor (bid) { + let floor = null; + if (typeof bid.getFloor === 'function') { + const floorInfo = bid.getFloor({ + currency: 'USD', + mediaType: 'banner', + size: _sizes(bid.sizes) + }); + if (typeof floorInfo === 'object' && + floorInfo.currency === 'USD' && !isNaN(parseFloat(floorInfo.floor))) { + floor = parseFloat(floorInfo.floor); + } + } + return floor !== null ? floor : bid.params.floor; +} + function getUnifiedIdEids(bidRequests) { return getEids(bidRequests, 'tdid', 'adserver.org', 'TDID'); } diff --git a/modules/userId/index.js b/modules/userId/index.js index a47565a53de..88a0a636caf 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -449,7 +449,7 @@ function initSubmodules(submodules, consentData) { if (storedId) { // cache decoded value (this is copied to every adUnit bid) - submodule.idObj = submodule.submodule.decode(storedId, submodule.config); + submodule.idObj = submodule.submodule.decode(storedId, submodule.config.params); } } else if (submodule.config.value) { // cache decoded value (this is copied to every adUnit bid) @@ -458,7 +458,7 @@ function initSubmodules(submodules, consentData) { const response = submodule.submodule.getId(submodule.config.params, consentData, undefined); if (utils.isPlainObject(response)) { if (typeof response.callback === 'function') { submodule.callback = response.callback; } - if (response.id) { submodule.idObj = submodule.submodule.decode(response.id, submodule.config); } + if (response.id) { submodule.idObj = submodule.submodule.decode(response.id, submodule.config.params); } } } carry.push(submodule); diff --git a/modules/vidazooBidAdapter.js b/modules/vidazooBidAdapter.js index 19c3f1db8e8..cc955b14715 100644 --- a/modules/vidazooBidAdapter.js +++ b/modules/vidazooBidAdapter.js @@ -14,6 +14,18 @@ const EXTERNAL_SYNC_TYPE = { IFRAME: 'iframe', IMAGE: 'image' }; +export const SUPPORTED_ID_SYSTEMS = { + 'britepoolid': 1, + 'criteoId': 1, + 'digitrustid': 1, + 'id5id': 1, + 'idl_env': 1, + 'lipb': 1, + 'netId': 1, + 'parrableid': 1, + 'pubcid': 1, + 'tdid': 1, +}; function isBidRequestValid(bid) { const params = bid.params || {}; @@ -21,7 +33,7 @@ function isBidRequestValid(bid) { } function buildRequest(bid, topWindowUrl, sizes, bidderRequest) { - const { params, bidId } = bid; + const { params, bidId, userId } = bid; const { bidFloor, cId, pId, ext } = params; const hashUrl = hashCode(topWindowUrl); const dealId = getNextDealId(hashUrl); @@ -34,7 +46,11 @@ function buildRequest(bid, topWindowUrl, sizes, bidderRequest) { publisherId: pId, sizes: sizes, dealId: dealId, + res: `${screen.width}x${screen.height}` }; + + appendUserIdsToRequestPayload(data, userId); + if (bidderRequest.gdprConsent) { if (bidderRequest.gdprConsent.consentString) { data.gdprConsent = bidderRequest.gdprConsent.consentString; @@ -59,6 +75,26 @@ function buildRequest(bid, topWindowUrl, sizes, bidderRequest) { return dto; } +function appendUserIdsToRequestPayload(payloadRef, userIds) { + let key; + utils._each(userIds, (userId, idSystemProviderName) => { + if (SUPPORTED_ID_SYSTEMS[idSystemProviderName]) { + key = `uid.${idSystemProviderName}`; + + switch (idSystemProviderName) { + case 'digitrustid': + payloadRef[key] = utils.deepAccess(userId, 'data.id'); + break; + case 'lipb': + payloadRef[key] = userId.lipbid; + break; + default: + payloadRef[key] = userId; + } + } + }); +} + function buildRequests(validBidRequests, bidderRequest) { const topWindowUrl = bidderRequest.refererInfo.referer; const requests = []; diff --git a/modules/waardexBidAdapter.js b/modules/waardexBidAdapter.js new file mode 100644 index 00000000000..255bf24098b --- /dev/null +++ b/modules/waardexBidAdapter.js @@ -0,0 +1,218 @@ +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER } from '../src/mediaTypes.js'; +import { config } from '../src/config.js'; + +const domain = 'hb.justbidit.xyz'; +const httpsPort = 8843; +const path = '/prebid'; + +const ENDPOINT = `https://${domain}:${httpsPort}${path}`; + +const BIDDER_CODE = 'waardex'; + +/** + * @param {Array} requestSizes + * + * @returns {Array} + * */ +function transformSizes(requestSizes) { + let sizes = []; + if ( + Array.isArray(requestSizes) && + !Array.isArray(requestSizes[0]) + ) { + sizes[0] = { + width: parseInt(requestSizes[0], 10) || 0, + height: parseInt(requestSizes[1], 10) || 0, + }; + } else if ( + Array.isArray(requestSizes) && + Array.isArray(requestSizes[0]) + ) { + sizes = requestSizes.map(item => { + return { + width: parseInt(item[0], 10) || 0, + height: parseInt(item[1], 10) || 0, + } + }); + } + return sizes; +} + +/** + * @param {Object} banner + * @param {Array} banner.sizes + * + * @returns {Object} + * */ +function createBannerObject(banner) { + return { + sizes: transformSizes(banner.sizes), + }; +} + +/** + * @param {Array} validBidRequests + * + * @returns {Object} + * */ +function buildBidRequests(validBidRequests) { + return validBidRequests.map((validBidRequest) => { + const params = validBidRequest.params; + + const item = { + bidId: validBidRequest.bidId, + placementId: params.placementId, + bidfloor: parseFloat(params.bidfloor) || 0, + position: parseInt(params.position) || 1, + instl: parseInt(params.instl) || 0, + }; + if (validBidRequest.mediaTypes[BANNER]) { + item[BANNER] = createBannerObject(validBidRequest.mediaTypes[BANNER]); + } + return item; + }); +} + +/** + * @param {Object} bidderRequest + * @param {String} bidderRequest.userAgent + * @param {String} bidderRequest.refererInfo + * @param {String} bidderRequest.uspConsent + * @param {Object} bidderRequest.gdprConsent + * @param {String} bidderRequest.gdprConsent.consentString + * @param {String} bidderRequest.gdprConsent.gdprApplies + * + * @returns {Object} - { + * ua: string, + * language: string, + * [referer]: string, + * [us_privacy]: string, + * [consent_string]: string, + * [consent_required]: string, + * [coppa]: boolean, + * } + * */ +function getCommonBidsData(bidderRequest) { + const payload = { + ua: navigator.userAgent || '', + language: navigator.language && navigator.language.indexOf('-') !== -1 ? navigator.language.split('-')[0] : '', + + }; + if (bidderRequest && bidderRequest.refererInfo) { + payload.referer = encodeURIComponent(bidderRequest.refererInfo.referer); + } + if (bidderRequest && bidderRequest.uspConsent) { + payload.us_privacy = bidderRequest.uspConsent; + } + if (bidderRequest && bidderRequest.gdprConsent) { + payload.gdpr_consent = { + consent_string: bidderRequest.gdprConsent.consentString, + consent_required: bidderRequest.gdprConsent.gdprApplies, + } + } + payload.coppa = !!config.getConfig('coppa'); + + return payload; +} + +/** + * this function checks either bid response is valid or noŠµ + * + * @param {Object} bid + * @param {string} bid.requestId + * @param {number} bid.cpm + * @param {string} bid.creativeId + * @param {number} bid.ttl + * @param {string} bid.currency + * @param {number} bid.width + * @param {number} bid.height + * @param {string} bid.ad + * + * @returns {boolean} + * */ +function isBidValid(bid) { + if (!bid.requestId || !bid.cpm || !bid.creativeId || !bid.ttl || !bid.currency) { + return false; + } + + return Boolean(bid.width && bid.height && bid.ad); +} + +/** + * @param {Object} serverBid + * + * @returns {Object|null} + * */ +function createBid(serverBid) { + const bid = { + requestId: serverBid.id, + cpm: serverBid.price, + currency: 'USD', + width: serverBid.w, + height: serverBid.h, + creativeId: serverBid.crid, + netRevenue: true, + ttl: 3000, + ad: serverBid.adm, + dealId: serverBid.dealid, + meta: { + cid: serverBid.cid, + adomain: serverBid.adomain, + mediaType: serverBid.ext.mediaType + }, + }; + + return isBidValid(bid) ? bid : null; +} + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [BANNER], + + isBidRequestValid: (bid) => Boolean(bid.bidId && bid.params && +bid.params.placementId && +bid.params.pubId), + + /** + * @param {Object[]} validBidRequests - array of valid bid requests + * @param {Object} bidderRequest - an array of valid bid requests + * + * */ + buildRequests(validBidRequests, bidderRequest) { + const payload = getCommonBidsData(bidderRequest); + payload.bidRequests = buildBidRequests(validBidRequests); + + let pubId = ''; + if (validBidRequests[0] && validBidRequests[0].params && +validBidRequests[0].params.pubId) { + pubId = +validBidRequests[0].params.pubId; + } + + const url = `${ENDPOINT}?pubId=${pubId}`; + + return { + method: 'POST', + url, + data: payload + }; + }, + + /** + * Unpack the response from the server into a list of bids. + */ + interpretResponse(serverResponse, bidRequest) { + const bids = []; + serverResponse = serverResponse.body; + + if (serverResponse.seatbid && serverResponse.seatbid[0]) { + const oneSeatBid = serverResponse.seatbid[0]; + oneSeatBid.bid.forEach(serverBid => { + const bid = createBid(serverBid); + if (bid) { + bids.push(bid); + } + }); + } + return bids; + }, +} + +registerBidder(spec); diff --git a/modules/waardexBidAdapter.md b/modules/waardexBidAdapter.md new file mode 100644 index 00000000000..44ee720d31a --- /dev/null +++ b/modules/waardexBidAdapter.md @@ -0,0 +1,60 @@ +# Overview + +``` +Module Name: Waardex Bid Adapter +Module Type: Bidder Adapter +Maintainer: info@prebid.org +``` + +# Description + +Connects to Waardex exchange for bids. + +Waardex bid adapter supports Banner. + +# Test Parameters + +``` + +var sizes = [ + [300, 250] +]; +var PREBID_TIMEOUT = 5000; +var FAILSAFE_TIMEOUT = 5000; + +var adUnits = [{ + code: '/19968336/header-bid-tag-0', + mediaTypes: { + banner: { + sizes: sizes, + }, + }, + bids: [{ + bidder: 'waardex', + params: { + placementId: 13144370, + position: 1, // add position openrtb + bidfloor: 0.5, + instl: 0, // 1 - full screen + pubId: 1, + } + }] +},{ + code: '/19968336/header-bid-tag-1', + mediaTypes: { + banner: { + sizes: sizes, + }, + }, + bids: [{ + bidder: 'waardex', + params: { + placementId: 333333333333, + position: 1, // add position openrtb + bidfloor: 0.5, + instl: 0, // 1 - full screen + pubId: 1, + } + }] +}]; +``` diff --git a/modules/yieldlabBidAdapter.js b/modules/yieldlabBidAdapter.js index 6cfa0c1a548..9c2b6abf475 100644 --- a/modules/yieldlabBidAdapter.js +++ b/modules/yieldlabBidAdapter.js @@ -42,6 +42,11 @@ export const spec = { if (bid.userIdAsEids && Array.isArray(bid.userIdAsEids)) { query.ids = createUserIdString(bid.userIdAsEids) } + if (bid.params.customParams && utils.isPlainObject(bid.params.customParams)) { + for (let prop in bid.params.customParams) { + query[prop] = bid.params.customParams[prop] + } + } }) if (bidderRequest && bidderRequest.gdprConsent) { diff --git a/package-lock.json b/package-lock.json index 583d25d3459..2fc53a75352 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prebid.js", - "version": "3.23.0-pre", + "version": "3.24.0-pre", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -15211,15 +15211,14 @@ "dev": true }, "live-connect-js": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/live-connect-js/-/live-connect-js-1.1.1.tgz", - "integrity": "sha512-PsYiZ6R6ecBQgcg3BWvzGf2TNOqpNFK1lUyfYAUEZ+DPwPciKNRM3CQIDtytVvR9vsH7nhotMaU3bBgb7iuPfQ==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/live-connect-js/-/live-connect-js-1.1.10.tgz", + "integrity": "sha512-G/LJKN3b21DZILCQRyataC/znLvJRyogtu7mAkKlkhP9B9UJ8bcOL7ihW/clD2PsT4hVUkeabHhUGsPCmhsjFw==", "requires": { "@kiosked/ulid": "^3.0.0", - "abab": "^2.0.2", + "abab": "^2.0.3", "browser-cookies": "^1.2.0", - "tiny-hashes": "1.0.1", - "tiny-uuid4": "^1.0.1" + "tiny-hashes": "1.0.1" } }, "livereload-js": { @@ -20779,11 +20778,6 @@ } } }, - "tiny-uuid4": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tiny-uuid4/-/tiny-uuid4-1.0.1.tgz", - "integrity": "sha1-vUTp3V9fvRdo1tH78wIMiGobd2Y=" - }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", diff --git a/package.json b/package.json index c84e354bd1b..5f08b7356fa 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,6 @@ "fun-hooks": "^0.9.9", "jsencrypt": "^3.0.0-rc.1", "just-clone": "^1.0.2", - "live-connect-js": "1.1.1" + "live-connect-js": "1.1.10" } } diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index d27cc99b5bc..3721cef18d9 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -22,13 +22,11 @@ describe('33acrossBidAdapter:', function () { format: [ { w: 300, - h: 250, - ext: {} + h: 250 }, { w: 728, - h: 90, - ext: {} + h: 90 } ], ext: { @@ -56,7 +54,8 @@ describe('33acrossBidAdapter:', function () { }, regs: { ext: { - gdpr: 0 + gdpr: 0, + us_privacy: null } }, ext: { @@ -92,12 +91,30 @@ describe('33acrossBidAdapter:', function () { }); Object.assign(ttxRequest, { regs: { - ext: { gdpr } + ext: Object.assign( + {}, + ttxRequest.regs.ext, + { gdpr } + ) } }); return this; }; + this.withUspConsent = (consent) => { + Object.assign(ttxRequest, { + regs: { + ext: Object.assign( + {}, + ttxRequest.regs.ext, + { us_privacy: consent } + ) + } + }); + + return this; + }; + this.withSite = site => { Object.assign(ttxRequest, { site }); return this; @@ -111,6 +128,34 @@ describe('33acrossBidAdapter:', function () { return this; }; + this.withSchain = schain => { + Object.assign(ttxRequest, { + source: { + ext: { + schain + } + } + }); + + return this; + }; + + this.withFormatFloors = floors => { + const format = ttxRequest.imp[0].banner.format.map((fm, i) => { + return Object.assign(fm, { + ext: { + ttx: { + bidfloors: [ floors[i] ] + } + } + }) + }); + + ttxRequest.imp[0].banner.format = format; + + return this; + }; + this.build = () => ttxRequest; } @@ -320,7 +365,7 @@ describe('33acrossBidAdapter:', function () { context('when width or height of the element is zero', function() { it('try to use alternative values', function() { const ttxRequest = new TtxRequestBuilder() - .withSizes([{ w: 800, h: 2400, ext: {} }]) + .withSizes([{ w: 800, h: 2400 }]) .withViewability({amount: 25}) .build(); const serverRequest = new ServerRequestBuilder() @@ -454,6 +499,84 @@ describe('33acrossBidAdapter:', function () { }); }); + context('when us_privacy consent data exists', function() { + let bidderRequest; + + beforeEach(function() { + bidderRequest = { + uspConsent: 'foo' + } + }); + + it('returns corresponding server requests with us_privacy consent data', function() { + const ttxRequest = new TtxRequestBuilder() + .withUspConsent('foo') + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + const builtServerRequests = spec.buildRequests(bidRequests, bidderRequest); + + expect(builtServerRequests).to.deep.equal([serverRequest]); + }); + + it('returns corresponding test server requests with us_privacy consent data', function() { + sandbox.stub(config, 'getConfig').callsFake(() => { + return { + 'url': 'https://foo.com/hb/' + } + }); + + const ttxRequest = new TtxRequestBuilder() + .withUspConsent('foo') + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .withUrl('https://foo.com/hb/') + .build(); + const builtServerRequests = spec.buildRequests(bidRequests, bidderRequest); + + expect(builtServerRequests).to.deep.equal([serverRequest]); + }); + }); + + context('when us_privacy consent data does not exist', function() { + let bidderRequest; + + beforeEach(function() { + bidderRequest = {}; + }); + + it('returns corresponding server requests with default us_privacy data', function() { + const ttxRequest = new TtxRequestBuilder() + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + const builtServerRequests = spec.buildRequests(bidRequests, bidderRequest); + + expect(builtServerRequests).to.deep.equal([serverRequest]); + }); + + it('returns corresponding test server requests with default us_privacy consent data', function() { + sandbox.stub(config, 'getConfig').callsFake(() => { + return { + 'url': 'https://foo.com/hb/' + } + }); + + const ttxRequest = new TtxRequestBuilder() + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .withUrl('https://foo.com/hb/') + .build(); + const builtServerRequests = spec.buildRequests(bidRequests, bidderRequest); + + expect(builtServerRequests).to.deep.equal([serverRequest]); + }); + }); + context('when referer value is available', function() { it('returns corresponding server requests with site.page set', function() { const bidderRequest = { @@ -492,6 +615,125 @@ describe('33acrossBidAdapter:', function () { expect(builtServerRequests).to.deep.equal([serverRequest]); }); }); + + context('when there is schain object in the bidRequest', function() { + it('builds request with schain info in source', function() { + const schainValues = [ + { + 'ver': '1.0', + 'complete': 1, + 'nodes': [ + { + 'asi': 'bidderA.com', + 'sid': '00001', + 'hp': 1 + } + ] + }, + { + 'ver': '1.0', + 'complete': 1, + }, + { + 'ver': '1.0', + 'complete': 1, + 'nodes': [] + }, + { + 'ver': '1.0', + 'complete': '1', + 'nodes': [ + { + 'asi': 'bidderA.com', + 'sid': '00001', + 'hp': 1 + } + ] + } + ]; + + schainValues.forEach((schain) => { + bidRequests[0].schain = schain; + + const ttxRequest = new TtxRequestBuilder() + .withSchain(schain) + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + + const builtServerRequests = spec.buildRequests(bidRequests, {}); + + expect(builtServerRequests).to.deep.equal([serverRequest]); + }); + }); + }); + + context('when there no schain object is passed', function() { + it('does not set source field', function() { + const ttxRequest = new TtxRequestBuilder() + .build(); + + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + + const builtServerRequests = spec.buildRequests(bidRequests, {}); + + expect(builtServerRequests).to.deep.equal([serverRequest]); + }); + }); + + context('when price floor module is not enabled in bidRequest', function() { + it('does not set any bidfloors in ttxRequest', function() { + const ttxRequest = new TtxRequestBuilder() + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + const builtServerRequests = spec.buildRequests(bidRequests, {}); + + expect(builtServerRequests).to.deep.equal([serverRequest]); + }); + }); + + context('when price floor module is enabled in bidRequest', function() { + it('does not set any bidfloors in ttxRequest if there is no floor', function() { + bidRequests[0].getFloor = () => ({}); + + const ttxRequest = new TtxRequestBuilder() + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + const builtServerRequests = spec.buildRequests(bidRequests, {}); + + expect(builtServerRequests).to.deep.equal([serverRequest]); + }); + + it('sets bidfloors in ttxRequest if there is a floor', function() { + bidRequests[0].getFloor = ({size, currency, mediaType}) => { + const floor = (size[0] === 300 && size[1] === 250) ? 1.0 : 0.10 + return ( + { + floor, + currency: 'USD' + } + ); + }; + + const ttxRequest = new TtxRequestBuilder() + .withFormatFloors([ 1.0, 0.10 ]) + .build(); + + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + const builtServerRequests = spec.buildRequests(bidRequests, {}); + + expect(builtServerRequests).to.deep.equal([serverRequest]); + }); + }); }); describe('interpretResponse', function() { @@ -693,11 +935,11 @@ describe('33acrossBidAdapter:', function () { const expectedSyncs = [ { type: 'iframe', - url: `${syncs[0].url}&gdpr_consent=undefined` + url: `${syncs[0].url}&gdpr_consent=undefined&us_privacy=undefined` }, { type: 'iframe', - url: `${syncs[1].url}&gdpr_consent=undefined` + url: `${syncs[1].url}&gdpr_consent=undefined&us_privacy=undefined` } ] @@ -713,11 +955,11 @@ describe('33acrossBidAdapter:', function () { const expectedSyncs = [ { type: 'iframe', - url: `${syncs[0].url}&gdpr_consent=undefined&gdpr=1` + url: `${syncs[0].url}&gdpr_consent=undefined&us_privacy=undefined&gdpr=1` }, { type: 'iframe', - url: `${syncs[1].url}&gdpr_consent=undefined&gdpr=1` + url: `${syncs[1].url}&gdpr_consent=undefined&us_privacy=undefined&gdpr=1` } ]; @@ -733,11 +975,11 @@ describe('33acrossBidAdapter:', function () { const expectedSyncs = [ { type: 'iframe', - url: `${syncs[0].url}&gdpr_consent=consent123A&gdpr=1` + url: `${syncs[0].url}&gdpr_consent=consent123A&us_privacy=undefined&gdpr=1` }, { type: 'iframe', - url: `${syncs[1].url}&gdpr_consent=consent123A&gdpr=1` + url: `${syncs[1].url}&gdpr_consent=consent123A&us_privacy=undefined&gdpr=1` } ]; @@ -753,11 +995,11 @@ describe('33acrossBidAdapter:', function () { const expectedSyncs = [ { type: 'iframe', - url: `${syncs[0].url}&gdpr_consent=undefined&gdpr=0` + url: `${syncs[0].url}&gdpr_consent=undefined&us_privacy=undefined&gdpr=0` }, { type: 'iframe', - url: `${syncs[1].url}&gdpr_consent=undefined&gdpr=0` + url: `${syncs[1].url}&gdpr_consent=undefined&us_privacy=undefined&gdpr=0` } ]; expect(syncResults).to.deep.equal(expectedSyncs); @@ -772,11 +1014,11 @@ describe('33acrossBidAdapter:', function () { const expectedSyncs = [ { type: 'iframe', - url: `${syncs[0].url}&gdpr_consent=consent123A` + url: `${syncs[0].url}&gdpr_consent=consent123A&us_privacy=undefined` }, { type: 'iframe', - url: `${syncs[1].url}&gdpr_consent=consent123A` + url: `${syncs[1].url}&gdpr_consent=consent123A&us_privacy=undefined` } ]; expect(syncResults).to.deep.equal(expectedSyncs); @@ -791,16 +1033,64 @@ describe('33acrossBidAdapter:', function () { const expectedSyncs = [ { type: 'iframe', - url: `${syncs[0].url}&gdpr_consent=consent123A&gdpr=0` + url: `${syncs[0].url}&gdpr_consent=consent123A&us_privacy=undefined&gdpr=0` + }, + { + type: 'iframe', + url: `${syncs[1].url}&gdpr_consent=consent123A&us_privacy=undefined&gdpr=0` + } + ]; + expect(syncResults).to.deep.equal(expectedSyncs); + }); + }); + + context('when there is no usPrivacy data', function() { + it('returns sync urls with undefined consent string as param', function() { + spec.buildRequests(bidRequests); + + const syncResults = spec.getUserSyncs(syncOptions, {}); + const expectedSyncs = [ + { + type: 'iframe', + url: `${syncs[0].url}&gdpr_consent=undefined&us_privacy=undefined` + }, + { + type: 'iframe', + url: `${syncs[1].url}&gdpr_consent=undefined&us_privacy=undefined` + } + ] + + expect(syncResults).to.deep.equal(expectedSyncs); + }) + }); + + context('when there is usPrivacy data', function() { + it('returns sync urls with consent string as param', function() { + spec.buildRequests(bidRequests); + + const syncResults = spec.getUserSyncs(syncOptions, {}, {}, 'foo'); + const expectedSyncs = [ + { + type: 'iframe', + url: `${syncs[0].url}&gdpr_consent=undefined&us_privacy=foo` }, { type: 'iframe', - url: `${syncs[1].url}&gdpr_consent=consent123A&gdpr=0` + url: `${syncs[1].url}&gdpr_consent=undefined&us_privacy=foo` } ]; + expect(syncResults).to.deep.equal(expectedSyncs); }); }); + + context('when user sync is invoked without a bid request phase', function() { + it('results in an empty syncs array', function() { + const syncResults = spec.getUserSyncs(syncOptions, {}, {}, 'foo'); + + expect(syncResults).to.deep.equal([]); + }); + }); }); }); }); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 7d6f9c6789c..a0ed6af6b89 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -248,12 +248,12 @@ describe('AppNexusAdapter', function () { const payload = JSON.parse(request.data); expect(payload.tags[0].video).to.deep.equal({ skippable: true, - playback_method: ['auto_play_sound_off'], + playback_method: 2, custom_renderer_present: true }); expect(payload.tags[1].video).to.deep.equal({ skippable: true, - playback_method: ['auto_play_sound_off'] + playback_method: 2 }); }); diff --git a/test/spec/modules/gmosspBidAdapter_spec.js b/test/spec/modules/gmosspBidAdapter_spec.js new file mode 100644 index 00000000000..5de3db623c5 --- /dev/null +++ b/test/spec/modules/gmosspBidAdapter_spec.js @@ -0,0 +1,162 @@ +import { expect } from 'chai'; +import { spec } from 'modules/gmosspBidAdapter.js'; +import { newBidder } from 'src/adapters/bidderFactory.js'; +import * as utils from 'src/utils.js'; + +const ENDPOINT = 'https://sp.gmossp-sp.jp/hb/prebid/query.ad'; + +describe('GmosspAdapter', function () { + const adapter = newBidder(spec); + + describe('inherited functions', function () { + it('exists and is a function', function () { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', function () { + let bid = { + bidder: 'gmossp', + params: { + sid: '123456' + } + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + const bidRequests = [ + { + bidder: 'gmossp', + params: { + sid: '123456' + }, + adUnitCode: 'adunit-code', + sizes: [ + [300, 250], + [320, 50], + [320, 100], + ], + bidId: '2b84475b5b636e', + bidderRequestId: '1f4001782ac16c', + auctionId: 'aba03555-4802-4c45-9f15-05ffa8594cff', + transactionId: '791e9d84-af92-4903-94da-24c7426d9d0c' + } + ]; + + const bidderRequest = { + refererInfo: { + referer: 'https://hoge.com' + } + }; + + it('sends bid request to ENDPOINT via GET', function () { + const requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests[0].url).to.equal(ENDPOINT); + expect(requests[0].method).to.equal('GET'); + expect(requests[0].data).to.equal('tid=791e9d84-af92-4903-94da-24c7426d9d0c&bid=2b84475b5b636e&ver=$prebid.version$&sid=123456&url=https%3A%2F%2Fhoge.com&cur=JPY&dnt=0&'); + }); + }); + + describe('interpretResponse', function () { + const bidderRequests = [ + { + bidder: 'gmossp', + params: { + sid: '123456' + }, + adUnitCode: 'adunit-code', + sizes: [ + [300, 250], + [320, 50], + [320, 100], + ], + bidId: '2b84475b5b636e', + bidderRequestId: '1f4001782ac16c', + auctionId: 'aba03555-4802-4c45-9f15-05ffa8594cff', + transactionId: '791e9d84-af92-4903-94da-24c7426d9d0c' + } + ]; + + it('should get correct banner bid response', function() { + const response = { + bid: '2b84475b5b636e', + price: 20, + w: 300, + h: 250, + ad: '
', + creativeId: '985ec572b32be309.76973017', + cur: 'JPY', + dealId: '', + imps: [ + 'https://sp.gmossp-sp.jp/hb/prebid/imp.ad' + ], + syncs: [ + 'https://sync.dsp.reemo-ad.jp' + ], + ttl: 300 + }; + + const expectedResponse = [ + { + requestId: '2b84475b5b636e', + cpm: 20, + currency: 'JPY', + width: 300, + height: 250, + ad: '
', + creativeId: '985ec572b32be309.76973017', + netRevenue: true, + ttl: 300 + } + ]; + + const result = spec.interpretResponse({ body: response }, bidderRequests); + expect(result).to.have.lengthOf(1); + + response.imps.forEach(impTracker => { + const tracker = utils.createTrackPixelHtml(impTracker); + expectedResponse[0].ad += tracker; + }); + + expect(result).to.deep.have.same.members(expectedResponse); + }); + + it('handles nobid responses', function () { + const response = ''; + + const result = spec.interpretResponse({ body: response }, bidderRequests); + expect(result.length).to.equal(0); + }); + }); + + describe('getUserSyncs', function () { + const bidResponse = { + body: { + ad: {}, + syncs: [ + 'https://hoge.com' + ] + } + }; + it('should return returns pixel syncs', function () { + const syncs = spec.getUserSyncs({ pixelEnabled: true, iframeEnabled: true }, [bidResponse]); + expect(syncs).to.deep.equal([ + { + type: 'image', + url: 'https://hoge.com' + } + ]) + }) + }); +}); diff --git a/test/spec/modules/liveIntentIdSystem_spec.js b/test/spec/modules/liveIntentIdSystem_spec.js index 85e0d30b348..b19d38d5859 100644 --- a/test/spec/modules/liveIntentIdSystem_spec.js +++ b/test/spec/modules/liveIntentIdSystem_spec.js @@ -33,21 +33,6 @@ describe('LiveIntentId', function () { resetLiveIntentIdSubmodule(); }); - it('should log an error if no configParams were passed when getId', function () { - liveIntentIdSubmodule.getId(); - expect(logErrorStub.calledOnce).to.be.true; - }); - - it('should log an error if publisherId configParam was not passed when getId', function () { - liveIntentIdSubmodule.getId({}); - expect(logErrorStub.calledOnce).to.be.true; - }); - - it('should log an error if publisherId configParam was not passed when decode', function () { - liveIntentIdSubmodule.decode({}, {}); - expect(logErrorStub.calledOnce).to.be.true; - }); - it('should initialize LiveConnect with a us privacy string when getId, and include it in all requests', function () { consentDataStub.returns('1YNY'); let callBackSpy = sinon.spy(); diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 817661ef51f..45259767133 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -2,6 +2,7 @@ import {expect} from 'chai'; import {spec} from 'modules/pubmaticBidAdapter.js'; import * as utils from 'src/utils.js'; import {config} from 'src/config.js'; +import { createEidsArray } from 'modules/userId/eids.js'; const constants = require('src/constants.json'); describe('PubMatic adapter', function () { @@ -1107,318 +1108,132 @@ describe('PubMatic adapter', function () { expect(data2.regs).to.equal(undefined);// USP/CCPAs }); - it('Request should have digitrust params', function() { - window.DigiTrust = { - getUser: function () { - } - }; - var bidRequest = {}; - let sandbox = sinon.sandbox.create(); - sandbox.stub(window.DigiTrust, 'getUser').callsFake(() => - ({ - success: true, - identity: { - privacy: {optout: false}, - id: 'testId', - keyv: 4 - } - }) - ); - - let request = spec.buildRequests(bidRequests, bidRequest); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ - 'source': 'digitru.st', - 'uids': [{ - 'id': 'testId', - 'atype': 1, - 'ext': { - 'keyv': 4 - } - }] - }]); - sandbox.restore(); - delete window.DigiTrust; - }); - - it('Request should not have digitrust params when DigiTrust not loaded', function() { - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal(undefined); - }); - - it('Request should not have digitrust params due to optout', function() { - window.DigiTrust = { - getUser: function () { - } - }; - let sandbox = sinon.sandbox.create(); - sandbox.stub(window.DigiTrust, 'getUser').callsFake(() => - ({ - success: true, - identity: { - privacy: {optout: true}, - id: 'testId', - keyv: 4 - } - }) - ); - - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal(undefined); - sandbox.restore(); - delete window.DigiTrust; - }); + describe('setting imp.floor using floorModule', function() { + /* + Use the minimum value among floor from floorModule per mediaType + If params.adfloor is set then take max(kadfloor, min(floors from floorModule)) + set imp.bidfloor only if it is more than 0 + */ - it('Request should not have digitrust params due to failure', function() { - window.DigiTrust = { - getUser: function () { - } + let newRequest; + let floorModuleTestData; + let getFloor = function(req) { + return floorModuleTestData[req.mediaType]; }; - let sandbox = sinon.sandbox.create(); - sandbox.stub(window.DigiTrust, 'getUser').callsFake(() => - ({ - success: false, - identity: { - privacy: {optout: false}, - id: 'testId', - keyv: 4 - } - }) - ); - - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal(undefined); - sandbox.restore(); - delete window.DigiTrust; - }); - describe('DigiTrustId from config', function() { - var origGetConfig; - let sandbox; beforeEach(() => { - sandbox = sinon.sandbox.create(); - window.DigiTrust = { - getUser: sandbox.spy() + floorModuleTestData = { + 'banner': { + 'currency': 'USD', + 'floor': 1.50 + }, + 'video': { + 'currency': 'USD', + 'floor': 2.50 + }, + 'native': { + 'currency': 'USD', + 'floor': 3.50 + } }; + newRequest = utils.deepClone(bannerVideoAndNativeBidRequests); + newRequest[0].getFloor = getFloor; }); - afterEach(() => { - sandbox.restore(); - delete window.DigiTrust; - }); - - it('Request should have digiTrustId config params', function() { - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = { - digiTrustId: { - success: true, - identity: { - privacy: {optout: false}, - id: 'testId', - keyv: 4 - } - } - }; - return config[key]; - }); - - let request = spec.buildRequests(bidRequests, {}); + it('bidfloor should be undefined if calculation is <= 0', function() { + floorModuleTestData.banner.floor = 0; // lowest of them all + newRequest[0].params.kadfloor = undefined; + let request = spec.buildRequests(newRequest); let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ - 'source': 'digitru.st', - 'uids': [{ - 'id': 'testId', - 'atype': 1, - 'ext': { - 'keyv': 4 - } - }] - }]); - // should not have called DigiTrust.getUser() - expect(window.DigiTrust.getUser.notCalled).to.equal(true); + data = data.imp[0]; + expect(data.bidfloor).to.equal(undefined); }); - it('Request should not have digiTrustId config params due to optout', function() { - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = { - digiTrustId: { - success: true, - identity: { - privacy: {optout: true}, - id: 'testId', - keyv: 4 - } - } - } - return config[key]; - }); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal(undefined); - // should not have called DigiTrust.getUser() - expect(window.DigiTrust.getUser.notCalled).to.equal(true); - }); - - it('Request should not have digiTrustId config params due to failure', function() { - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = { - digiTrustId: { - success: false, - identity: { - privacy: {optout: false}, - id: 'testId', - keyv: 4 - } - } - } - return config[key]; - }); - - let request = spec.buildRequests(bidRequests, {}); + it('ignore floormodule o/p if floor is not number', function() { + floorModuleTestData.banner.floor = 'INR'; + newRequest[0].params.kadfloor = undefined; + let request = spec.buildRequests(newRequest); let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal(undefined); - // should not have called DigiTrust.getUser() - expect(window.DigiTrust.getUser.notCalled).to.equal(true); + data = data.imp[0]; + expect(data.bidfloor).to.equal(2.5); // video will be lowest now }); - it('Request should not have digiTrustId config params if they do not exist', function() { - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = {}; - return config[key]; - }); - - let request = spec.buildRequests(bidRequests, {}); + it('ignore floormodule o/p if currency is not matched', function() { + floorModuleTestData.banner.currency = 'INR'; + newRequest[0].params.kadfloor = undefined; + let request = spec.buildRequests(newRequest); let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal(undefined); - // should have called DigiTrust.getUser() once - expect(window.DigiTrust.getUser.calledOnce).to.equal(true); + data = data.imp[0]; + expect(data.bidfloor).to.equal(2.5); // video will be lowest now }); - it('should NOT include coppa flag in bid request if coppa config is not present', () => { - const request = spec.buildRequests(bidRequests, {}); + it('kadfloor is not passed, use minimum from floorModule', function() { + newRequest[0].params.kadfloor = undefined; + let request = spec.buildRequests(newRequest); let data = JSON.parse(request.data); - if (data.regs) { - // in case GDPR is set then data.regs will exist - expect(data.regs.coppa).to.equal(undefined); - } else { - expect(data.regs).to.equal(undefined); - } + data = data.imp[0]; + expect(data.bidfloor).to.equal(1.5); }); - it('should include coppa flag in bid request if coppa is set to true', () => { - sandbox.stub(config, 'getConfig').callsFake(key => { - const config = { - 'coppa': true - }; - return config[key]; - }); - const request = spec.buildRequests(bidRequests, {}); + it('kadfloor is passed as 3, use kadfloor as it is highest', function() { + newRequest[0].params.kadfloor = '3.0';// yes, we want it as a string + let request = spec.buildRequests(newRequest); let data = JSON.parse(request.data); - expect(data.regs.coppa).to.equal(1); + data = data.imp[0]; + expect(data.bidfloor).to.equal(3); }); - it('should NOT include coppa flag in bid request if coppa is set to false', () => { - sandbox.stub(config, 'getConfig').callsFake(key => { - const config = { - 'coppa': false - }; - return config[key]; - }); - const request = spec.buildRequests(bidRequests, {}); + it('kadfloor is passed as 1, use min of fllorModule as it is highest', function() { + newRequest[0].params.kadfloor = '1.0';// yes, we want it as a string + let request = spec.buildRequests(newRequest); let data = JSON.parse(request.data); - if (data.regs) { - // in case GDPR is set then data.regs will exist - expect(data.regs.coppa).to.equal(undefined); - } else { - expect(data.regs).to.equal(undefined); - } + data = data.imp[0]; + expect(data.bidfloor).to.equal(1.5); }); }); - describe('AdsrvrOrgId from config', function() { - let sandbox; - beforeEach(() => { - sandbox = sinon.sandbox.create(); - }); - - afterEach(() => { - sandbox.restore(); - }); - - it('Request should have adsrvrOrgId config params', function() { - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = { - adsrvrOrgId: { - 'TDID': '5e740345-c25e-436d-b466-5f2f9fa95c17', - 'TDID_LOOKUP': 'TRUE', - 'TDID_CREATED_AT': '2018-10-01T07:05:40' - } - }; - return config[key]; - }); - - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ - 'source': 'adserver.org', - 'uids': [{ - 'id': '5e740345-c25e-436d-b466-5f2f9fa95c17', - 'atype': 1, - 'ext': { - 'rtiPartner': 'TDID' - } - }] - }]); - }); - - it('Request should NOT have adsrvrOrgId config params if id in adsrvrOrgId is NOT string', function() { - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = { - adsrvrOrgId: { - 'TDID': 1, - 'TDID_LOOKUP': 'TRUE', - 'TDID_CREATED_AT': '2018-10-01T07:05:40' - } - }; - return config[key]; - }); - - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal(undefined); - }); - - it('Request should NOT have adsrvrOrgId config params if adsrvrOrgId is NOT object', function() { - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = { - adsrvrOrgId: null - }; - return config[key]; - }); + it('should NOT include coppa flag in bid request if coppa config is not present', () => { + const request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + if (data.regs) { + // in case GDPR is set then data.regs will exist + expect(data.regs.coppa).to.equal(undefined); + } else { + expect(data.regs).to.equal(undefined); + } + }); - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal(undefined); + it('should include coppa flag in bid request if coppa is set to true', () => { + let sandbox = sinon.sandbox.create(); + sandbox.stub(config, 'getConfig').callsFake(key => { + const config = { + 'coppa': true + }; + return config[key]; }); + const request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + expect(data.regs.coppa).to.equal(1); + sandbox.restore(); + }); - it('Request should NOT have adsrvrOrgId config params if id in adsrvrOrgId is NOT set', function() { - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = { - adsrvrOrgId: { - 'TDID_LOOKUP': 'TRUE', - 'TDID_CREATED_AT': '2018-10-01T07:05:40' - } - }; - return config[key]; - }); - - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal(undefined); + it('should NOT include coppa flag in bid request if coppa is set to false', () => { + let sandbox = sinon.sandbox.create(); + sandbox.stub(config, 'getConfig').callsFake(key => { + const config = { + 'coppa': false + }; + return config[key]; }); + const request = spec.buildRequests(bidRequests, {}); + let data = JSON.parse(request.data); + if (data.regs) { + // in case GDPR is set then data.regs will exist + expect(data.regs.coppa).to.equal(undefined); + } else { + expect(data.regs).to.equal(undefined); + } + sandbox.restore(); }); describe('AdsrvrOrgId from userId module', function() { @@ -1434,6 +1249,7 @@ describe('PubMatic adapter', function () { it('Request should have AdsrvrOrgId config params', function() { bidRequests[0].userId = {}; bidRequests[0].userId.tdid = 'TTD_ID_FROM_USER_ID_MODULE'; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.deep.equal([{ @@ -1461,6 +1277,7 @@ describe('PubMatic adapter', function () { }); bidRequests[0].userId = {}; bidRequests[0].userId.tdid = 'TTD_ID_FROM_USER_ID_MODULE'; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.deep.equal([{ @@ -1491,161 +1308,12 @@ describe('PubMatic adapter', function () { }); }); - describe('AdsrvrOrgId and Digitrust', function() { - // here we are considering cases only of accepting DigiTrustId from config - let sandbox; - beforeEach(() => { - sandbox = sinon.sandbox.create(); - window.DigiTrust = { - getUser: sandbox.spy() - }; - }); - - afterEach(() => { - sandbox.restore(); - delete window.DigiTrust; - }); - - it('Request should have id of both AdsrvrOrgId and Digitrust if both have returned valid ids', function() { - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = { - adsrvrOrgId: { - 'TDID': '5e740345-c25e-436d-b466-5f2f9fa95c17', - 'TDID_LOOKUP': 'TRUE', - 'TDID_CREATED_AT': '2018-10-01T07:05:40' - }, - digiTrustId: { - success: true, - identity: { - privacy: {optout: false}, - id: 'testId', - keyv: 4 - } - } - }; - return config[key]; - }); - - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ - 'source': 'digitru.st', - 'uids': [{ - 'id': 'testId', - 'atype': 1, - 'ext': { - 'keyv': 4 - } - }] - }, { - 'source': 'adserver.org', - 'uids': [{ - 'id': '5e740345-c25e-436d-b466-5f2f9fa95c17', - 'atype': 1, - 'ext': { - 'rtiPartner': 'TDID' - } - }] - }]); - }); - - it('Request should have id of only AdsrvrOrgId and NOT Digitrust if only AdsrvrOrgId have returned valid id', function() { - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = { - adsrvrOrgId: { - 'TDID': '5e740345-c25e-436d-b466-5f2f9fa95c17', - 'TDID_LOOKUP': 'TRUE', - 'TDID_CREATED_AT': '2018-10-01T07:05:40' - }, - digiTrustId: { - success: true, - identity: { - privacy: {optout: true}, - id: 'testId', - keyv: 4 - } - } - }; - return config[key]; - }); - - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ - 'source': 'adserver.org', - 'uids': [{ - 'id': '5e740345-c25e-436d-b466-5f2f9fa95c17', - 'atype': 1, - 'ext': { - 'rtiPartner': 'TDID' - } - }] - }]); - }); - - it('Request should have id of only Digitrust and NOT AdsrvrOrgId if only Digitrust have returned valid id', function() { - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = { - adsrvrOrgId: { - 'TDID_LOOKUP': 'TRUE', - 'TDID_CREATED_AT': '2018-10-01T07:05:40' - }, - digiTrustId: { - success: true, - identity: { - privacy: {optout: false}, - id: 'testId', - keyv: 4 - } - } - }; - return config[key]; - }); - - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal([{ - 'source': 'digitru.st', - 'uids': [{ - 'id': 'testId', - 'atype': 1, - 'ext': { - 'keyv': 4 - } - }] - }]); - }); - - it('Request should NOT have id of Digitrust and NOT AdsrvrOrgId if only both have NOT returned valid ids', function() { - sandbox.stub(config, 'getConfig').callsFake((key) => { - var config = { - adsrvrOrgId: { - 'TDID_LOOKUP': 'TRUE', - 'TDID_CREATED_AT': '2018-10-01T07:05:40' - }, - digiTrustId: { - success: true, - identity: { - privacy: {optout: true}, - id: 'testId', - keyv: 4 - } - } - }; - return config[key]; - }); - - let request = spec.buildRequests(bidRequests, {}); - let data = JSON.parse(request.data); - expect(data.user.eids).to.deep.equal(undefined); - }); - }); - describe('UserIds from request', function() { describe('pubcommon Id', function() { it('send the pubcommon id if it is present', function() { bidRequests[0].userId = {}; bidRequests[0].userId.pubcid = 'pub_common_user_id'; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.deep.equal([{ @@ -1660,18 +1328,22 @@ describe('PubMatic adapter', function () { it('do not pass if not string', function() { bidRequests[0].userId = {}; bidRequests[0].userId.pubcid = 1; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.pubcid = []; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.pubcid = null; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.pubcid = {}; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); @@ -1682,6 +1354,7 @@ describe('PubMatic adapter', function () { it('send the digitrust id if it is present', function() { bidRequests[0].userId = {}; bidRequests[0].userId.digitrustid = {data: {id: 'digitrust_user_id'}}; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.deep.equal([{ @@ -1696,18 +1369,22 @@ describe('PubMatic adapter', function () { it('do not pass if not string', function() { bidRequests[0].userId = {}; bidRequests[0].userId.digitrustid = {data: {id: 1}}; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.digitrustid = {data: {id: []}}; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.digitrustid = {data: {id: null}}; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.digitrustid = {data: {id: {}}}; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); @@ -1718,6 +1395,7 @@ describe('PubMatic adapter', function () { it('send the id5 id if it is present', function() { bidRequests[0].userId = {}; bidRequests[0].userId.id5id = 'id5-user-id'; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.deep.equal([{ @@ -1732,18 +1410,22 @@ describe('PubMatic adapter', function () { it('do not pass if not string', function() { bidRequests[0].userId = {}; bidRequests[0].userId.id5id = 1; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.id5id = []; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.id5id = null; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.id5id = {}; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); @@ -1754,6 +1436,7 @@ describe('PubMatic adapter', function () { it('send the criteo id if it is present', function() { bidRequests[0].userId = {}; bidRequests[0].userId.criteoId = 'criteo-user-id'; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.deep.equal([{ @@ -1768,18 +1451,22 @@ describe('PubMatic adapter', function () { it('do not pass if not string', function() { bidRequests[0].userId = {}; bidRequests[0].userId.criteoId = 1; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.criteoId = []; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.criteoId = null; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.criteoId = {}; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); @@ -1790,6 +1477,7 @@ describe('PubMatic adapter', function () { it('send the identity-link id if it is present', function() { bidRequests[0].userId = {}; bidRequests[0].userId.idl_env = 'identity-link-user-id'; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.deep.equal([{ @@ -1804,18 +1492,22 @@ describe('PubMatic adapter', function () { it('do not pass if not string', function() { bidRequests[0].userId = {}; bidRequests[0].userId.idl_env = 1; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.idl_env = []; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.idl_env = null; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.idl_env = {}; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); @@ -1826,6 +1518,7 @@ describe('PubMatic adapter', function () { it('send the LiveIntent id if it is present', function() { bidRequests[0].userId = {}; bidRequests[0].userId.lipb = { lipbid: 'live-intent-user-id' }; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.deep.equal([{ @@ -1840,18 +1533,22 @@ describe('PubMatic adapter', function () { it('do not pass if not string', function() { bidRequests[0].userId = {}; bidRequests[0].userId.lipb = { lipbid: 1 }; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.lipb.lipbid = []; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.lipb.lipbid = null; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.lipb.lipbid = {}; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); @@ -1862,6 +1559,7 @@ describe('PubMatic adapter', function () { it('send the Parrable id if it is present', function() { bidRequests[0].userId = {}; bidRequests[0].userId.parrableid = 'parrable-user-id'; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.deep.equal([{ @@ -1876,18 +1574,22 @@ describe('PubMatic adapter', function () { it('do not pass if not string', function() { bidRequests[0].userId = {}; bidRequests[0].userId.parrableid = 1; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.parrableid = []; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.parrableid = null; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.parrableid = {}; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); @@ -1898,6 +1600,7 @@ describe('PubMatic adapter', function () { it('send the Britepool id if it is present', function() { bidRequests[0].userId = {}; bidRequests[0].userId.britepoolid = 'britepool-user-id'; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.deep.equal([{ @@ -1912,18 +1615,22 @@ describe('PubMatic adapter', function () { it('do not pass if not string', function() { bidRequests[0].userId = {}; bidRequests[0].userId.britepoolid = 1; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.britepoolid = []; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.britepoolid = null; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.britepoolid = {}; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); @@ -1934,6 +1641,7 @@ describe('PubMatic adapter', function () { it('send the NetId if it is present', function() { bidRequests[0].userId = {}; bidRequests[0].userId.netId = 'netid-user-id'; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.deep.equal([{ @@ -1948,18 +1656,22 @@ describe('PubMatic adapter', function () { it('do not pass if not string', function() { bidRequests[0].userId = {}; bidRequests[0].userId.netId = 1; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); let request = spec.buildRequests(bidRequests, {}); let data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.netId = []; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.netId = null; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); bidRequests[0].userId.netId = {}; + bidRequests[0].userIdAsEids = createEidsArray(bidRequests[0].userId); request = spec.buildRequests(bidRequests, {}); data = JSON.parse(request.data); expect(data.user.eids).to.equal(undefined); diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index 5e6397f1b2e..2faad47aca8 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -42,6 +42,45 @@ describe('Smart bid adapter tests', function () { transactionId: 'zsfgzzg' }]; + var DEFAULT_PARAMS_WITH_EIDS = [{ + adUnitCode: 'sas_42', + bidId: 'abcd1234', + mediaTypes: { + banner: { + sizes: [ + [300, 250], + [300, 200] + ] + } + }, + bidder: 'smartadserver', + params: { + domain: 'https://prg.smartadserver.com', + siteId: '1234', + pageId: '5678', + formatId: '90', + target: 'test=prebid', + bidfloor: 0.420, + buId: '7569', + appName: 'Mozilla', + ckId: 42 + }, + requestId: 'efgh5678', + transactionId: 'zsfgzzg', + userId: { + britepoolid: '1111', + criteoId: '1111', + digitrustid: { data: { id: 'DTID', keyv: 4, privacy: { optout: false }, producer: 'ABC', version: 2 } }, + id5id: '1111', + idl_env: '1111', + lipbid: '1111', + parrableid: 'eidVersion.encryptionKeyReference.encryptedValue', + pubcid: '1111', + tdid: '1111', + netId: 'fH5A3n2O8_CZZyPoJVD-eabc6ECb7jhxCicsds7qSg', + } + }]; + // Default params without optional ones var DEFAULT_PARAMS_WO_OPTIONAL = [{ adUnitCode: 'sas_42', @@ -434,6 +473,33 @@ describe('Smart bid adapter tests', function () { }); }); + describe('External ids tests', function () { + it('Verify external ids in request and ids found', function () { + config.setConfig({ + 'currency': { + 'adServerCurrency': 'EUR' + } + }); + const request = spec.buildRequests(DEFAULT_PARAMS_WITH_EIDS); + expect(request[0]).to.have.property('url').and.to.equal('https://prg.smartadserver.com/prebid/v1'); + expect(request[0]).to.have.property('method').and.to.equal('POST'); + const requestContent = JSON.parse(request[0].data); + + expect(requestContent).to.have.property('eids'); + expect(requestContent.eids).to.not.equal(null).and.to.not.be.undefined; + expect(requestContent.eids.length).to.greaterThan(0); + for (let index in requestContent.eids) { + let eid = requestContent.eids[index]; + expect(eid.source).to.not.equal(null).and.to.not.be.undefined; + expect(eid.uids).to.not.equal(null).and.to.not.be.undefined; + for (let uidsIndex in eid.uids) { + let uid = eid.uids[uidsIndex]; + expect(uid.id).to.not.equal(null).and.to.not.be.undefined; + } + } + }); + }); + describe('Supply Chain Serializer tests', function () { it('Verify a multi node supply chain serialization matches iab example', function() { let schain = { diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index c82cc32207a..54ccff870eb 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -70,12 +70,17 @@ describe('sovrnBidAdapter', function() { }); it('sets the proper banner object', function() { - const payload = JSON.parse(request.data); + const payload = JSON.parse(request.data) expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]) expect(payload.imp[0].banner.w).to.equal(1) expect(payload.imp[0].banner.h).to.equal(1) }) + it('includes the ad unit code int the request', function() { + const payload = JSON.parse(request.data); + expect(payload.imp[0].adunitcode).to.equal('adunit-code') + }) + it('accepts a single array as a size', function() { const singleSize = [{ 'bidder': 'sovrn', @@ -234,7 +239,7 @@ describe('sovrnBidAdapter', function() { expect(data.source.ext.schain.nodes.length).to.equal(1) }); - it('should add digitrust data if present', function() { + it('should add the unifiedID if present', function() { const digitrustRequests = [{ 'bidder': 'sovrn', 'params': { @@ -249,12 +254,7 @@ describe('sovrnBidAdapter', function() { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', 'userId': { - 'digitrustid': { - 'data': { - 'id': 'digitrust-id-123', - 'keyv': 4 - } - } + 'tdid': 'SOMESORTOFID', } }].concat(bidRequests); const bidderRequest = { @@ -262,13 +262,13 @@ describe('sovrnBidAdapter', function() { referer: 'http://example.com/page.html', } }; - const data = JSON.parse(spec.buildRequests(digitrustRequests, bidderRequest).data); - expect(data.user.ext.digitrust.id).to.equal('digitrust-id-123'); - expect(data.user.ext.digitrust.keyv).to.equal(4); - }); + const data = JSON.parse(spec.buildRequests(digitrustRequests, bidderRequest).data); + expect(data.user.ext.eids[0].source).to.equal('adserver.org') + expect(data.user.ext.eids[0].uids[0].id).to.equal('SOMESORTOFID') + expect(data.user.ext.eids[0].uids[0].ext.rtiPartner).to.equal('TDID') + }) }); - describe('interpretResponse', function () { let response; beforeEach(function () { diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js index 675b8b6c532..73373293114 100644 --- a/test/spec/modules/tripleliftBidAdapter_spec.js +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -299,6 +299,15 @@ describe('triplelift adapter', function () { const { data: payload } = request; expect(payload.ext).to.deep.equal(undefined); }); + it('should get floor from floors module if available', function() { + const floorInfo = { + currency: 'USD', + floor: 1.99 + }; + bidRequests[0].getFloor = () => floorInfo; + const request = tripleliftAdapterSpec.buildRequests(bidRequests, bidderRequest); + expect(request.data.imp[0].floor).to.equal(1.99); + }); }); describe('interpretResponse', function () { diff --git a/test/spec/modules/vidazooBidAdapter_spec.js b/test/spec/modules/vidazooBidAdapter_spec.js index 9b7b6a73a21..fb9c540708b 100644 --- a/test/spec/modules/vidazooBidAdapter_spec.js +++ b/test/spec/modules/vidazooBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { spec as adapter, URL } from 'modules/vidazooBidAdapter.js'; +import { spec as adapter, URL, SUPPORTED_ID_SYSTEMS } from 'modules/vidazooBidAdapter.js'; import * as utils from 'src/utils.js'; const BID = { @@ -140,6 +140,7 @@ describe('VidazooBidAdapter', function () { bidId: '2d52001cabd527', publisherId: '59ac17c192832d0011283fe3', dealId: 1, + res: `${window.top.screen.width}x${window.top.screen.height}`, 'ext.param1': 'loremipsum', 'ext.param2': 'dolorsitamet', } @@ -210,4 +211,28 @@ describe('VidazooBidAdapter', function () { expect(responses[0].ttl).to.equal(300); }); }); + + describe(`user id system`, function () { + Object.keys(SUPPORTED_ID_SYSTEMS).forEach((idSystemProvider) => { + const id = Date.now().toString(); + const bid = utils.deepClone(BID); + + const userId = (function () { + switch (idSystemProvider) { + case 'digitrustid': return { data: { id: id } }; + case 'lipb': return { lipbid: id }; + default: return id; + } + })(); + + bid.userId = { + [idSystemProvider]: userId + }; + + it(`should include 'uid.${idSystemProvider}' in request params`, function () { + const requests = adapter.buildRequests([bid], BIDDER_REQUEST); + expect(requests[0].data[`uid.${idSystemProvider}`]).to.equal(id); + }); + }); + }); }); diff --git a/test/spec/modules/waardexBidAdapter_spec.js b/test/spec/modules/waardexBidAdapter_spec.js new file mode 100644 index 00000000000..fae70335d3c --- /dev/null +++ b/test/spec/modules/waardexBidAdapter_spec.js @@ -0,0 +1,190 @@ +import {expect} from 'chai'; +import {spec} from '../../../modules/waardexBidAdapter.js'; +import { auctionManager } from 'src/auctionManager.js'; +import { deepClone } from 'src/utils.js'; + +describe('waardexBidAdapter', () => { + const validBid = { + bidId: '112435ry', + bidder: 'waardex', + params: { + placementId: 1, + traffic: 'banner', + pubId: 1, + } + }; + + describe('isBidRequestValid', () => { + it('Should return true. bidId and params such as placementId and pubId are present', () => { + expect(spec.isBidRequestValid(validBid)).to.be.true; + }); + it('Should return false. bidId is not present in bid object', () => { + const invalidBid = deepClone(validBid); + delete invalidBid.bidId; + expect(spec.isBidRequestValid(invalidBid)).to.be.false; + }); + it('Should return false. placementId is not present in bid.params object', () => { + const invalidBid = deepClone(validBid); + delete invalidBid.params.placementId; + expect(spec.isBidRequestValid(invalidBid)).to.be.false; + }); + it('Should return false. pubId is not present in bid.params object', () => { + const invalidBid = deepClone(validBid); + delete invalidBid.params.pubId; + expect(spec.isBidRequestValid(invalidBid)).to.be.false; + }); + }); + + describe('buildRequests', () => { + let getAdUnitsStub; + const validBidRequests = [{ + bidId: 'fergr675ujgh', + mediaTypes: { + banner: { + sizes: [[300, 600], [300, 250]] + } + }, + params: { + placementId: 1, + bidfloor: 1.5, + position: 1, + instl: 1, + pubId: 100 + }, + }]; + + const bidderRequest = { + refererInfo: { + referer: 'https://www.google.com/?some_param=some_value' + }, + }; + + beforeEach(() => getAdUnitsStub = sinon.stub(auctionManager, 'getAdUnits').callsFake(() => [])); + afterEach(() => getAdUnitsStub.restore()); + + it('should return valid build request object', () => { + const request = spec.buildRequests(validBidRequests, bidderRequest); + const { + data: payload, + url, + method, + } = request; + + expect(payload.bidRequests[0]).deep.equal({ + bidId: validBidRequests[0].bidId, + placementId: validBidRequests[0].params.placementId, + bidfloor: validBidRequests[0].params.bidfloor, + position: validBidRequests[0].params.position, + instl: validBidRequests[0].params.instl, + banner: { + sizes: [ + { + width: validBidRequests[0].mediaTypes.banner.sizes[0][0], + height: validBidRequests[0].mediaTypes.banner.sizes[0][1] + }, + { + width: validBidRequests[0].mediaTypes.banner.sizes[1][0], + height: validBidRequests[0].mediaTypes.banner.sizes[1][1] + }, + ], + } + }); + const ENDPOINT = `https://hb.justbidit.xyz:8843/prebid?pubId=${validBidRequests[0].params.pubId}`; + expect(url).to.equal(ENDPOINT); + expect(method).to.equal('POST'); + }); + }); + + describe('interpretResponse', () => { + const serverResponse = { + body: { + seatbid: [{ + bid: [{ + id: 'someId', + price: 3.3, + w: 250, + h: 300, + crid: 'dspCreativeIdHere', + adm: 'html markup here', + dealId: '123456789', + cid: 'dsp campaign id', + adomain: 'advertisers domain', + ext: { + mediaType: 'banner', + }, + }], + }], + }, + }; + + it('bid response is valid', () => { + const result = spec.interpretResponse(serverResponse); + const expected = [{ + requestId: serverResponse.body.seatbid[0].bid[0].id, + cpm: serverResponse.body.seatbid[0].bid[0].price, + currency: 'USD', + width: serverResponse.body.seatbid[0].bid[0].w, + height: serverResponse.body.seatbid[0].bid[0].h, + creativeId: serverResponse.body.seatbid[0].bid[0].crid, + netRevenue: true, + ttl: 3000, + ad: serverResponse.body.seatbid[0].bid[0].adm, + dealId: serverResponse.body.seatbid[0].bid[0].dealid, + meta: { + cid: serverResponse.body.seatbid[0].bid[0].cid, + adomain: serverResponse.body.seatbid[0].bid[0].adomain, + mediaType: serverResponse.body.seatbid[0].bid[0].ext.mediaType, + }, + }]; + expect(result).deep.equal(expected); + }); + + it('invalid bid response. requestId is not exists in bid response', () => { + const invalidServerResponse = deepClone(serverResponse); + delete invalidServerResponse.body.seatbid[0].bid[0].id; + + const result = spec.interpretResponse(invalidServerResponse); + expect(result).deep.equal([]); + }); + + it('invalid bid response. cpm is not exists in bid response', () => { + const invalidServerResponse = deepClone(serverResponse); + delete invalidServerResponse.body.seatbid[0].bid[0].price; + + const result = spec.interpretResponse(invalidServerResponse); + expect(result).deep.equal([]); + }); + + it('invalid bid response. creativeId is not exists in bid response', () => { + const invalidServerResponse = deepClone(serverResponse); + delete invalidServerResponse.body.seatbid[0].bid[0].crid; + + const result = spec.interpretResponse(invalidServerResponse); + expect(result).deep.equal([]); + }); + + it('invalid bid response. width is not exists in bid response', () => { + const invalidServerResponse = deepClone(serverResponse); + delete invalidServerResponse.body.seatbid[0].bid[0].w; + + const result = spec.interpretResponse(invalidServerResponse); + expect(result).deep.equal([]); + }); + + it('invalid bid response. height is not exists in bid response', () => { + const invalidServerResponse = deepClone(serverResponse); + delete invalidServerResponse.body.seatbid[0].bid[0].h; + + const result = spec.interpretResponse(invalidServerResponse); + expect(result).deep.equal([]); + }); + + it('invalid bid response. ad is not exists in bid response', () => { + const invalidServerResponse = deepClone(serverResponse); + delete invalidServerResponse.body.seatbid[0].bid[0].adm; + + const result = spec.interpretResponse(invalidServerResponse); + expect(result).deep.equal([]); + }); + }); +}); diff --git a/test/spec/modules/yieldlabBidAdapter_spec.js b/test/spec/modules/yieldlabBidAdapter_spec.js index 5dcd112228a..097f85b9b8d 100644 --- a/test/spec/modules/yieldlabBidAdapter_spec.js +++ b/test/spec/modules/yieldlabBidAdapter_spec.js @@ -12,6 +12,10 @@ const REQUEST = { 'key1': 'value1', 'key2': 'value2' }, + 'customParams': { + 'extraParam': true, + 'foo': 'bar' + }, 'extId': 'abc' }, 'bidderRequestId': '143346cf0f1731', @@ -88,6 +92,10 @@ describe('yieldlabBidAdapter', function () { expect(request.url).to.include('ids=netid.de%3AfH5A3n2O8_CZZyPoJVD-eabc6ECb7jhxCicsds7qSg') }) + it('passes extra params to bid request', function () { + expect(request.url).to.include('extraParam=true&foo=bar') + }) + const gdprRequest = spec.buildRequests(bidRequests, { gdprConsent: { consentString: 'BN5lERiOMYEdiAKAWXEND1AAAAE6DABACMA',