From 7827258f7818b3b516bb053d136a9b95a4499ef6 Mon Sep 17 00:00:00 2001 From: Lyubomir Shishkov Date: Wed, 2 Oct 2024 00:07:46 +0300 Subject: [PATCH 1/7] 12238 - Azerion / Improve: does not properly support currency module * **Type:** Fix * **Scope:** improvedigitalBidAdapter * **Subject:** Bid floors are always converted to USD. * **Details:** * Adds `DEFAULT_CURRENCY` variable which is set to USD * Adds `convertBidFloorCurrency` function which in used to convert the bid floor when both `imp.bidfloor` and `imp.bidfloorcur` are present, and `imp.bidfloorcur` is not equal to the adapter's `DEFAULT_CURRENCY`; * **Breaks:** N/A --- modules/improvedigitalBidAdapter.js | 32 ++++++++++++++++- .../modules/improvedigitalBidAdapter_spec.js | 35 +++++++++++++++---- 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/modules/improvedigitalBidAdapter.js b/modules/improvedigitalBidAdapter.js index ddf13caa833..f3554878740 100644 --- a/modules/improvedigitalBidAdapter.js +++ b/modules/improvedigitalBidAdapter.js @@ -5,6 +5,7 @@ import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {Renderer} from '../src/Renderer.js'; import {hasPurpose1Consent} from '../src/utils/gdpr.js'; import {ortbConverter} from '../libraries/ortbConverter/converter.js'; +import {convertCurrency} from '../libraries/currencyUtils/currency.js'; /** * See https://github.com/prebid/Prebid.js/pull/8827 for details on linting exception * ImproveDigital only imports after winning a bid and only if the creative cannot reach top @@ -29,6 +30,7 @@ const BASIC_ADS_BASE_URL = 'https://ad.360yield-basic.com'; const PB_ENDPOINT = 'pb'; const EXTEND_URL = 'https://pbs.360yield.com/openrtb2/auction'; const IFRAME_SYNC_URL = 'https://hb.360yield.com/prebid-universal-creative/load-cookie.html'; +const DEFAULT_CURRENCY = 'USD'; const VIDEO_PARAMS = { DEFAULT_MIMES: ['video/mp4'] @@ -124,6 +126,30 @@ export const spec = { registerBidder(spec); +const convertBidFloorCurrency = (imp) => { + const omitBidFloor = () => { + delete imp.bidfloor; + delete imp.bidfloorcur; + logWarn('Cannot convert bid floor currency. Omitting bid floor from request.'); + }; + + try { + imp.bidfloor = parseFloat(convertCurrency( + imp.bidfloor, + imp.bidfloorcur.toUpperCase(), + DEFAULT_CURRENCY, + false, + ).toFixed(2)); + imp.bidfloorcur = DEFAULT_CURRENCY; + + if (isNaN(imp.bidfloor)) { + omitBidFloor(); + } + } catch (err) { + omitBidFloor(); + } +}; + export const CONVERTER = ortbConverter({ context: { ttl: CREATIVE_TTL, @@ -138,7 +164,11 @@ export const CONVERTER = ortbConverter({ imp.secure = Number(window.location.protocol === 'https:'); if (!imp.bidfloor && bidRequest.params.bidFloor) { imp.bidfloor = bidRequest.params.bidFloor; - imp.bidfloorcur = getBidIdParameter('bidFloorCur', bidRequest.params).toUpperCase() || 'USD' + imp.bidfloorcur = getBidIdParameter('bidFloorCur', bidRequest.params).toUpperCase() || DEFAULT_CURRENCY; + } + + if (imp.bidfloor && imp.bidfloorcur && imp.bidfloorcur.toUpperCase() !== DEFAULT_CURRENCY) { + convertBidFloorCurrency(imp); } const bidderParamsPath = context.extendMode ? 'ext.prebid.bidder.improvedigital' : 'ext.bidder'; const placementId = bidRequest.params.placementId; diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index 5dc94f544ea..1429afab93b 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -16,6 +16,7 @@ import 'modules/schain.js'; import {decorateAdUnitsWithNativeParams} from '../../../src/native.js'; import {syncAddFPDToBidderRequest} from '../../helpers/fpd.js'; import {hook} from '../../../src/hook.js'; +import * as prebidGlobal from 'src/prebidGlobal.js'; describe('Improve Digital Adapter Tests', function () { const METHOD = 'POST'; @@ -205,12 +206,18 @@ describe('Improve Digital Adapter Tests', function () { describe('buildRequests', function () { let getConfigStub = null; + let getGlobalStub = null; afterEach(function () { if (getConfigStub) { getConfigStub.restore(); getConfigStub = null; } + + if (getGlobalStub) { + getGlobalStub.restore(); + getGlobalStub = null; + } }); it('should make a well-formed request objects', function () { @@ -349,10 +356,17 @@ describe('Improve Digital Adapter Tests', function () { } }); - it('should add bid floor', function () { - const bidRequest = Object.assign({}, simpleBidRequest); - let payload = JSON.parse(spec.buildRequests([bidRequest], bidderRequest)[0].data); + it('should add bid floor correctly', function () { + getGlobalStub = sinon.stub(prebidGlobal, 'getGlobal').returns({ + convertCurrency: (cpm, from, to) => { + const conversionKeys = { 'EUR-USD': 1.75 }; + return cpm * conversionKeys[`${from}-${to}`]; + } + }); + const bidRequest = deepClone(simpleBidRequest); + // Floor price currency shouldn't be populated without a floor price + let payload = JSON.parse(spec.buildRequests([bidRequest], bidderRequest)[0].data); expect(payload.imp[0].bidfloorcur).to.not.exist; // Default floor price currency @@ -361,18 +375,25 @@ describe('Improve Digital Adapter Tests', function () { expect(payload.imp[0].bidfloor).to.equal(0.05); expect(payload.imp[0].bidfloorcur).to.equal('USD'); - // Floor price currency + // Floor price omitted when currency cannot be converted to default bid adapter currency + bidRequest.params.bidFloorCur = 'UAH'; + bidRequest.params.bidFloor = 0.05; + payload = JSON.parse(spec.buildRequests([bidRequest], bidderRequest)[0].data); + expect(payload.imp[0].bidfloor).to.be.undefined; + expect(payload.imp[0].bidfloorcur).to.not.exist; + + // Floor price currency converted to default bid adapter currency bidRequest.params.bidFloorCur = 'eUR'; payload = JSON.parse(spec.buildRequests([bidRequest], bidderRequest)[0].data); - expect(payload.imp[0].bidfloor).to.equal(0.05); - expect(payload.imp[0].bidfloorcur).to.equal('EUR'); + expect(payload.imp[0].bidfloor).to.equal(0.09); + expect(payload.imp[0].bidfloorcur).to.equal('USD'); // getFloor defined -> use it over bidFloor let getFloorResponse = { currency: 'USD', floor: 3 }; bidRequest.getFloor = () => getFloorResponse; payload = JSON.parse(spec.buildRequests([bidRequest], bidderRequest)[0].data); expect(payload.imp[0].bidfloor).to.equal(3); - // expect(payload.imp[0].bidfloorcur).to.equal('USD'); + expect(payload.imp[0].bidfloorcur).to.equal('USD'); }); it('should add GDPR consent string', function () { From ff11c0cea3071985ae5e0a0e7cd93e4af9620cab Mon Sep 17 00:00:00 2001 From: Lyubomir Shishkov Date: Wed, 2 Oct 2024 00:15:29 +0300 Subject: [PATCH 2/7] restored accidentally discarded change from unit test expect --- test/spec/modules/improvedigitalBidAdapter_spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index 1429afab93b..44932239d9f 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -1002,7 +1002,7 @@ describe('Improve Digital Adapter Tests', function () { width: 728, height: 90, ttl: 300, - ad: '\x3Cscript>window.__razr_config = {"prebid":{"bidRequest":{"bidder":"improvedigital","params":{"publisherId":1234,"placementId":1053688,"keyValues":{"testKey":["testValue"]},"bidFloor":0.05,"bidFloorCur":"eUR","size":{"w":800,"h":600}},"adUnitCode":"div-gpt-ad-1499748733608-0","transactionId":"f183e871-fbed-45f0-a427-c8a63c4c01eb","bidId":"33e9500b21129f","bidderRequestId":"2772c1e566670b","auctionId":"192721e36a0239","mediaTypes":{"banner":{"sizes":[[300,250],[160,600]]}},"sizes":[[300,250],[160,600]]},"bid":{"mediaType":"banner","ad":"\\"\\"","requestId":"33e9500b21129f","seatBidId":"35adfe19-d6e9-46b9-9f7d-20da7026b965","cpm":1.9200543539802946,"currency":"EUR","width":728,"height":90,"creative_id":"510265","creativeId":"510265","ttl":300,"meta":{},"dealId":320896,"netRevenue":false}}};\x3C/script>  ', + ad: '\x3Cscript>window.__razr_config = {"prebid":{"bidRequest":{"bidder":"improvedigital","params":{"publisherId":1234,"placementId":1053688,"keyValues":{"testKey":["testValue"]},"size":{"w":800,"h":600}},"adUnitCode":"div-gpt-ad-1499748733608-0","transactionId":"f183e871-fbed-45f0-a427-c8a63c4c01eb","bidId":"33e9500b21129f","bidderRequestId":"2772c1e566670b","auctionId":"192721e36a0239","mediaTypes":{"banner":{"sizes":[[300,250],[160,600]]}},"sizes":[[300,250],[160,600]]},"bid":{"mediaType":"banner","ad":"\\"\\"","requestId":"33e9500b21129f","seatBidId":"35adfe19-d6e9-46b9-9f7d-20da7026b965","cpm":1.9200543539802946,"currency":"EUR","width":728,"height":90,"creative_id":"510265","creativeId":"510265","ttl":300,"meta":{},"dealId":320896,"netRevenue":false}}};\x3C/script>  ', creativeId: '510265', dealId: 320896, netRevenue: false, @@ -1025,7 +1025,7 @@ describe('Improve Digital Adapter Tests', function () { width: 300, height: 250, ttl: 300, - ad: '\x3Cscript>window.__razr_config = {"prebid":{"bidRequest":{"bidder":"improvedigital","params":{"publisherId":1234,"placementId":1053688,"keyValues":{"testKey":["testValue"]},"bidFloor":0.05,"bidFloorCur":"eUR","size":{"w":800,"h":600}},"adUnitCode":"div-gpt-ad-1499748733608-0","transactionId":"f183e871-fbed-45f0-a427-c8a63c4c01eb","bidId":"33e9500b21129f","bidderRequestId":"2772c1e566670b","auctionId":"192721e36a0239","mediaTypes":{"banner":{"sizes":[[300,250],[160,600]]}},"sizes":[[300,250],[160,600]]},"bid":{"mediaType":"banner","ad":"\\"\\"","requestId":"33e9500b21129f","seatBidId":"83c8d524-0955-4d0c-b558-4c9f3600e09b","cpm":1.9200543539802946,"currency":"EUR","width":300,"height":250,"creative_id":"479163","creativeId":"479163","ttl":300,"meta":{},"dealId":320896,"netRevenue":false}}};\x3C/script>  ', + ad: '\x3Cscript>window.__razr_config = {"prebid":{"bidRequest":{"bidder":"improvedigital","params":{"publisherId":1234,"placementId":1053688,"keyValues":{"testKey":["testValue"]},"size":{"w":800,"h":600}},"adUnitCode":"div-gpt-ad-1499748733608-0","transactionId":"f183e871-fbed-45f0-a427-c8a63c4c01eb","bidId":"33e9500b21129f","bidderRequestId":"2772c1e566670b","auctionId":"192721e36a0239","mediaTypes":{"banner":{"sizes":[[300,250],[160,600]]}},"sizes":[[300,250],[160,600]]},"bid":{"mediaType":"banner","ad":"\\"\\"","requestId":"33e9500b21129f","seatBidId":"83c8d524-0955-4d0c-b558-4c9f3600e09b","cpm":1.9200543539802946,"currency":"EUR","width":300,"height":250,"creative_id":"479163","creativeId":"479163","ttl":300,"meta":{},"dealId":320896,"netRevenue":false}}};\x3C/script>  ', creativeId: '479163', dealId: 320896, netRevenue: false, From 638c39e5fac77496f28719544404af49fa81bca4 Mon Sep 17 00:00:00 2001 From: Lyubomir Shishkov Date: Wed, 2 Oct 2024 17:38:31 +0300 Subject: [PATCH 3/7] * Modifies behavior to pass bid floor as is when it cannot be converted to USD; * Removes rounding of bid floor when converting its currency to USD; --- modules/improvedigitalBidAdapter.js | 19 ++++++------------- .../modules/improvedigitalBidAdapter_spec.js | 8 ++++---- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/modules/improvedigitalBidAdapter.js b/modules/improvedigitalBidAdapter.js index f3554878740..b5a6cf5f06b 100644 --- a/modules/improvedigitalBidAdapter.js +++ b/modules/improvedigitalBidAdapter.js @@ -127,26 +127,19 @@ export const spec = { registerBidder(spec); const convertBidFloorCurrency = (imp) => { - const omitBidFloor = () => { - delete imp.bidfloor; - delete imp.bidfloorcur; - logWarn('Cannot convert bid floor currency. Omitting bid floor from request.'); - }; - try { - imp.bidfloor = parseFloat(convertCurrency( + const bidFloor = convertCurrency( imp.bidfloor, imp.bidfloorcur.toUpperCase(), DEFAULT_CURRENCY, false, - ).toFixed(2)); - imp.bidfloorcur = DEFAULT_CURRENCY; - - if (isNaN(imp.bidfloor)) { - omitBidFloor(); + ); + if (typeof bidFloor === 'number' && !isNaN(bidFloor)) { + imp.bidfloor = bidFloor; + imp.bidfloorcur = DEFAULT_CURRENCY; } } catch (err) { - omitBidFloor(); + logWarn(`Failed to convert bid floor to ${DEFAULT_CURRENCY}. Passing floor price in its original currency.`, err); } }; diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index 44932239d9f..844ded6abe9 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -375,17 +375,17 @@ describe('Improve Digital Adapter Tests', function () { expect(payload.imp[0].bidfloor).to.equal(0.05); expect(payload.imp[0].bidfloorcur).to.equal('USD'); - // Floor price omitted when currency cannot be converted to default bid adapter currency + // Floor price sent as is when currency cannot be converted to default bid adapter currency bidRequest.params.bidFloorCur = 'UAH'; bidRequest.params.bidFloor = 0.05; payload = JSON.parse(spec.buildRequests([bidRequest], bidderRequest)[0].data); - expect(payload.imp[0].bidfloor).to.be.undefined; - expect(payload.imp[0].bidfloorcur).to.not.exist; + expect(payload.imp[0].bidfloor).to.equal(0.05); + expect(payload.imp[0].bidfloorcur).to.equal('UAH'); // Floor price currency converted to default bid adapter currency bidRequest.params.bidFloorCur = 'eUR'; payload = JSON.parse(spec.buildRequests([bidRequest], bidderRequest)[0].data); - expect(payload.imp[0].bidfloor).to.equal(0.09); + expect(payload.imp[0].bidfloor).to.equal(0.08750000000000001); expect(payload.imp[0].bidfloorcur).to.equal('USD'); // getFloor defined -> use it over bidFloor From 17f3fa6c0be57317dfa2478379ed6972e8f3bacf Mon Sep 17 00:00:00 2001 From: Lyubomir Shishkov Date: Fri, 11 Oct 2024 16:53:08 +0300 Subject: [PATCH 4/7] remove unnecessary uses of `toUpperCase()` --- modules/improvedigitalBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/improvedigitalBidAdapter.js b/modules/improvedigitalBidAdapter.js index b5a6cf5f06b..103fdb24e75 100644 --- a/modules/improvedigitalBidAdapter.js +++ b/modules/improvedigitalBidAdapter.js @@ -130,7 +130,7 @@ const convertBidFloorCurrency = (imp) => { try { const bidFloor = convertCurrency( imp.bidfloor, - imp.bidfloorcur.toUpperCase(), + imp.bidfloorcur, DEFAULT_CURRENCY, false, ); @@ -160,7 +160,7 @@ export const CONVERTER = ortbConverter({ imp.bidfloorcur = getBidIdParameter('bidFloorCur', bidRequest.params).toUpperCase() || DEFAULT_CURRENCY; } - if (imp.bidfloor && imp.bidfloorcur && imp.bidfloorcur.toUpperCase() !== DEFAULT_CURRENCY) { + if (imp.bidfloor && imp.bidfloorcur && imp.bidfloorcur !== DEFAULT_CURRENCY) { convertBidFloorCurrency(imp); } const bidderParamsPath = context.extendMode ? 'ext.prebid.bidder.improvedigital' : 'ext.bidder'; From 9e0a49c09a99e251de4877e681b70f4fbe214d9e Mon Sep 17 00:00:00 2001 From: Lyubomir Shishkov Date: Sat, 12 Oct 2024 00:26:22 +0300 Subject: [PATCH 5/7] * fix `convertCurrency` mock * remove redundant checks for type and NaN from `convertBidFloorCurrency` function --- modules/improvedigitalBidAdapter.js | 6 ++---- test/spec/modules/improvedigitalBidAdapter_spec.js | 6 +++++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/modules/improvedigitalBidAdapter.js b/modules/improvedigitalBidAdapter.js index 103fdb24e75..c08edb3987d 100644 --- a/modules/improvedigitalBidAdapter.js +++ b/modules/improvedigitalBidAdapter.js @@ -134,10 +134,8 @@ const convertBidFloorCurrency = (imp) => { DEFAULT_CURRENCY, false, ); - if (typeof bidFloor === 'number' && !isNaN(bidFloor)) { - imp.bidfloor = bidFloor; - imp.bidfloorcur = DEFAULT_CURRENCY; - } + imp.bidfloor = bidFloor; + imp.bidfloorcur = DEFAULT_CURRENCY; } catch (err) { logWarn(`Failed to convert bid floor to ${DEFAULT_CURRENCY}. Passing floor price in its original currency.`, err); } diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index 844ded6abe9..0c0789ced48 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -360,7 +360,11 @@ describe('Improve Digital Adapter Tests', function () { getGlobalStub = sinon.stub(prebidGlobal, 'getGlobal').returns({ convertCurrency: (cpm, from, to) => { const conversionKeys = { 'EUR-USD': 1.75 }; - return cpm * conversionKeys[`${from}-${to}`]; + const conversionRate = conversionKeys[`${from}-${to}`]; + if (!conversionRate) { + throw new Error(`No conversion rate found for ${from}-${to}`); + } + return cpm * conversionRate; } }); const bidRequest = deepClone(simpleBidRequest); From 57638b162bb7ee7a7c6e1f6a5518e2d08a6cefac Mon Sep 17 00:00:00 2001 From: Ivan Atanasov Date: Fri, 31 Jan 2025 11:01:11 +0200 Subject: [PATCH 6/7] Restores the logic of choosing the winning bid for targeting inside getWinningBids instead of the using the hookable getHighestCpmBidsFromBidPool which has a logic to return bids unchanged, to sort them causing wrong targeting being applied when multibid module is included. --- src/targeting.js | 44 ++++++++++++++------------------------------ 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/src/targeting.js b/src/targeting.js index 1903524984b..3e275ba4e16 100644 --- a/src/targeting.js +++ b/src/targeting.js @@ -219,7 +219,7 @@ export function newTargeting(auctionManager) { if (enableSendAllBids || (deals && bid.dealId)) { const targetingValue = getTargetingMap(bid, standardKeys.filter( key => typeof bid.adserverTargeting[key] !== 'undefined' && - (deals || allowedSendAllBidTargeting.indexOf(key) !== -1))); + (deals || allowedSendAllBidTargeting.indexOf(key) !== -1))); if (targetingValue) { result.push({[bid.adUnitCode]: targetingValue}) @@ -290,7 +290,7 @@ export function newTargeting(auctionManager) { const adUnitBidLimit = (sendAllBids && (bidLimit || bidLimitConfigValue)) || 0; const { customKeysByUnit, filteredBids } = getfilteredBidsAndCustomKeys(adUnitCodes, bidsReceived); const bidsSorted = getHighestCpmBidsFromBidPool(filteredBids, winReducer, adUnitBidLimit, undefined, winSorter); - let targeting = getTargetingLevels(bidsSorted, customKeysByUnit); + let targeting = getTargetingLevels(bidsSorted, customKeysByUnit, adUnitCodes); const defaultKeys = Object.keys(Object.assign({}, DEFAULT_TARGETING_KEYS, NATIVE_KEYS)); let allowedKeys = config.getConfig(CFG_ALLOW_TARGETING_KEYS); @@ -337,8 +337,8 @@ export function newTargeting(auctionManager) { }); } - function getTargetingLevels(bidsSorted, customKeysByUnit) { - const targeting = getWinningBidTargeting(bidsSorted) + function getTargetingLevels(bidsSorted, customKeysByUnit, adUnitCodes) { + const targeting = getWinningBidTargeting(bidsSorted, adUnitCodes) .concat(getCustomBidTargeting(bidsSorted, customKeysByUnit)) .concat(getBidderTargeting(bidsSorted)) .concat(getAdUnitTargeting()); @@ -568,25 +568,17 @@ export function newTargeting(auctionManager) { * @return {Array} - An array of winning bids. */ targeting.getWinningBids = function(adUnitCode, bids, winReducer = getHighestCpm, winSorter = sortByHighestCpm) { - const usedCodes = []; const bidsReceived = bids || getBidsReceived(winReducer, winSorter); const adUnitCodes = getAdUnitCodes(adUnitCode); return bidsReceived - .reduce((result, bid) => { - const code = bid.adUnitCode; - const cpmEligible = bidderSettings.get(code, 'allowZeroCpmBids') === true ? bid.cpm >= 0 : bid.cpm > 0; - const isPreferredDeal = config.getConfig('targetingControls.alwaysIncludeDeals') && bid.dealId; - const eligible = includes(adUnitCodes, code) && - !includes(usedCodes, code) && - (isPreferredDeal || cpmEligible) - if (eligible) { - result.push(bid); - usedCodes.push(code); - } - - return result; - }, []); + .filter(bid => includes(adUnitCodes, bid.adUnitCode)) + .filter(bid => (bidderSettings.get(bid.bidderCode, 'allowZeroCpmBids') === true) ? bid.cpm >= 0 : bid.cpm > 0) + .map(bid => bid.adUnitCode) + .filter(uniques) + .map(adUnitCode => bidsReceived + .filter(bid => bid.adUnitCode === adUnitCode ? bid : null) + .reduce(getHighestCpm)); }; /** @@ -624,19 +616,11 @@ export function newTargeting(auctionManager) { /** * Get targeting key value pairs for winning bid. * @param {Array} bidsReceived code array + * @param {string[]} adUnitCodes code array * @return {targetingArray} winning bids targeting */ - function getWinningBidTargeting(bidsReceived) { - let usedAdUnitCodes = []; - let winners = bidsReceived - .reduce((bids, bid) => { - if (!includes(usedAdUnitCodes, bid.adUnitCode)) { - bids.push(bid); - usedAdUnitCodes.push(bid.adUnitCode); - } - return bids; - }, []); - + function getWinningBidTargeting(bidsReceived, adUnitCodes) { + let winners = targeting.getWinningBids(adUnitCodes, bidsReceived); let standardKeys = getStandardKeys(); winners = winners.map(winner => { From 07c74f0200fada2609044f42403514f8122ce86d Mon Sep 17 00:00:00 2001 From: Ivan Atanasov Date: Fri, 31 Jan 2025 14:19:02 +0200 Subject: [PATCH 7/7] Adds unit test --- test/spec/unit/core/targeting_spec.js | 36 ++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index 2296379ca43..01f9f93477e 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -13,7 +13,7 @@ import {auctionManager} from 'src/auctionManager.js'; import * as utils from 'src/utils.js'; import {deepClone} from 'src/utils.js'; import {createBid} from '../../../../src/bidfactory.js'; -import {hook} from '../../../../src/hook.js'; +import { hook, setupBeforeHookFnOnce } from '../../../../src/hook.js'; import {getHighestCpm} from '../../../../src/utils/reducers.js'; function mkBid(bid, status = STATUS.GOOD) { @@ -956,6 +956,40 @@ describe('targeting tests', function () { }); }); // end getAllTargeting tests + describe('getAllTargeting will work correctly when a hook raises has modified flag in getHighestCpmBidsFromBidPool', function () { + let bidsReceived; + let amGetAdUnitsStub; + let amBidsReceivedStub; + let bidExpiryStub; + + beforeEach(function () { + bidsReceived = [bid2, bid1].map(deepClone); + + amBidsReceivedStub = sandbox.stub(auctionManager, 'getBidsReceived').callsFake(function() { + return bidsReceived; + }); + amGetAdUnitsStub = sandbox.stub(auctionManager, 'getAdUnitCodes').callsFake(function() { + return ['/123456/header-bid-tag-0']; + }); + bidExpiryStub = sandbox.stub(filters, 'isBidNotExpired').returns(true); + + setupBeforeHookFnOnce(getHighestCpmBidsFromBidPool, function (fn, bidsReceived, highestCpmCallback, adUnitBidLimit = 0, hasModified = false) { + fn.call(this, bidsReceived, highestCpmCallback, adUnitBidLimit, true); + }); + }); + + afterEach(function () { + getHighestCpmBidsFromBidPool.getHooks().remove(); + }) + + it('will apply correct targeting', function () { + let targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + + expect(targeting['/123456/header-bid-tag-0']['hb_pb']).to.equal('0.53'); + expect(targeting['/123456/header-bid-tag-0']['hb_adid']).to.equal('148018fe5e'); + }) + }); + describe('getAllTargeting without bids return empty object', function () { let amBidsReceivedStub; let amGetAdUnitsStub;