From 875cd1d3f035525d0549041f24926d31008ba86f Mon Sep 17 00:00:00 2001 From: Filip Stamenkovic Date: Fri, 10 Dec 2021 13:35:36 +0100 Subject: [PATCH 1/9] switch native assets to ortb2 format --- src/native.js | 138 +++++++++++++++++++++++++++++++- test/spec/native_spec.js | 74 +++++++++++++++++ test/spec/unit/pbjs_api_spec.js | 49 ++++++++++-- 3 files changed, 249 insertions(+), 12 deletions(-) diff --git a/src/native.js b/src/native.js index d8c55fc6569..7175ba65765 100644 --- a/src/native.js +++ b/src/native.js @@ -1,4 +1,4 @@ -import { deepAccess, getKeyByValue, insertHtmlIntoIframe, logError, triggerPixel } from './utils.js'; +import { deepAccess, getKeyByValue, insertHtmlIntoIframe, isNumber, isPlainObject, logError, triggerPixel } from './utils.js'; import includes from 'prebidjs-polyfill/includes.js'; import {auctionManager} from './auctionManager.js'; @@ -11,6 +11,50 @@ export const NATIVE_TARGETING_KEYS = Object.keys(CONSTANTS.NATIVE_KEYS).map( ); const IMAGE = { + ortb2: { + ver: '1.2', + assets: [ + { + required: 1, + id: 1, + img: { + type: 3, + wmin: 100, + hmin: 100, + } + }, + { + required: 1, + id: 2, + title: { + len: 140, + } + }, + { + required: 1, + id: 3, + data: { + type: 1, + } + }, + { + required: 0, + id: 4, + data: { + type: 2, + } + }, + { + required: 0, + id: 5, + img: { + type: 1, + wmin: 20, + hmin: 20, + } + }, + ], + }, image: { required: true }, title: { required: true }, sponsoredBy: { required: true }, @@ -30,9 +74,12 @@ const SUPPORTED_TYPES = { */ export function processNativeAdUnitParams(params) { if (params && params.type && typeIsSupported(params.type)) { - return SUPPORTED_TYPES[params.type]; + params = SUPPORTED_TYPES[params.type]; } + if (params && params.ortb2 && !isOpenRTBBidRequestValid(params.ortb2)) { + return; + } return params; } @@ -45,6 +92,61 @@ export function decorateAdUnitsWithNativeParams(adUnits) { } }); } +export function isOpenRTBBidRequestValid(ortb2) { + const assets = ortb2.assets; + if (!Array.isArray(assets) || assets.length === 0) { + logError(`assets in mediaTypes.native.ortb2 is not an array, or it's empty. Assets: `, assets); + return false; + } + + // validate that ids exist, that they are unique and that they are numbers + const ids = assets.map(asset => asset.id); + if (assets.length !== new Set(ids).size || ids.some(id => id !== parseInt(id, 10))) { + logError(`each asset object must have 'id' property, it must be unique and it must be an integer`); + return false; + } + + if (ortb2.hasOwnProperty('eventtrackers') && !Array.isArray(ortb2.eventtrackers)) { + logError('ortb2.eventtrackers is not an array. Eventtrackers: ', ortb2.eventtrackers); + return false; + } + + return assets.every(asset => isOpenRTBAssetValid(asset)) +} + +function isOpenRTBAssetValid(asset) { + if (!isPlainObject(asset)) { + logError(`asset must be an object. Provided asset: `, asset); + return false; + } + if (asset.img) { + if (!isNumber(asset.img.w) && !isNumber(asset.img.wmin)) { + logError(`for img asset there must be 'w' or 'wmin' property`); + return false; + } + if (!isNumber(asset.img.h) && !isNumber(asset.img.hmin)) { + logError(`for img asset there must be 'h' or 'hmin' property`); + return false; + } + } else if (asset.title) { + if (!isNumber(asset.title.len)) { + logError(`for title asset there must be 'len' property defined`); + return false; + } + } else if (asset.data) { + if (!isNumber(asset.data.type)) { + logError(`for data asset 'type' property must be a number`); + return false; + } + } else if (asset.video) { + if (!Array.isArray(asset.video.mimes) || !Array.isArray(asset.video.protocols) || + !isNumber(asset.video.minduration) || !isNumber(asset.video.maxduration)) { + logError('video asset is not properly configured'); + return false; + } + } + return true; +} /** * Check if the native type specified in the adUnit is supported by Prebid. @@ -80,12 +182,18 @@ export const hasNonNativeBidder = adUnit => * @return {Boolean} If object is valid */ export function nativeBidIsValid(bid, {index = auctionManager.index} = {}) { + const bidRequest = index.getAdUnit(bid); + if (!bidRequest) { return false; } + + if (deepAccess(bid, 'native.ortb2') && deepAccess(bidRequest, 'nativeParams.ortb2')) { + return isNativeOpenRTBBidValid(bid.native.ortb2, bidRequest.nativeParams.ortb2); + } // all native bid responses must define a landing page url if (!deepAccess(bid, 'native.clickUrl')) { return false; } - const requestedAssets = index.getAdUnit(bid).nativeParams; + const requestedAssets = bidRequest.nativeParams; if (!requestedAssets) { return true; } @@ -100,6 +208,23 @@ export function nativeBidIsValid(bid, {index = auctionManager.index} = {}) { return requiredAssets.every(asset => includes(returnedAssets, asset)); } +export function isNativeOpenRTBBidValid(bidORTB, bidRequestORTB) { + if (!deepAccess(bidORTB, 'link.url')) { + logError(`native response doesn't have 'link' property. Ortb2 response: `, bidORTB); + return false; + } + + let requiredAssetIds = bidRequestORTB.assets.filter(asset => asset.required === 1).map(a => a.id); + let returnedAssetIds = bidORTB.assets.map(asset => asset.id); + + const match = requiredAssetIds.every(assetId => includes(returnedAssetIds, assetId)); + if (!match) { + logError(`didn't receive a bit with all required assets. Required ids: ${requiredAssetIds}, but received ids in response: ${returnedAssetIds}`); + } + + return match; +} + /* * Native responses may have associated impression or click trackers. * This retrieves the appropriate tracker urls for the given ad object and @@ -230,9 +355,14 @@ export function getAllAssetsMessage(data, adObject) { const message = { message: 'assetResponse', adId: data.adId, - assets: [] }; + if (adObject.native.ortb2) { + message.native = adObject.native; + return message; + } + message.assets = []; + Object.keys(adObject.native).forEach(function(key, index) { if (key === 'adTemplate' && adObject.native[key]) { message.adTemplate = getAssetValue(adObject.native[key]); diff --git a/test/spec/native_spec.js b/test/spec/native_spec.js index 66e11b9a472..73a423adf5f 100644 --- a/test/spec/native_spec.js +++ b/test/spec/native_spec.js @@ -393,6 +393,80 @@ describe('native.js', function () { }); }); +describe('validate native openRTB', function () { + it('should validate openRTB request', function() { + let openRTBNativeRequest = {assets: []}; + // assets array can't be empty + expect(isOpenRTBBidRequestValid(openRTBNativeRequest)).to.eq(false); + openRTBNativeRequest.assets.push({ + id: 1.5, + required: 1, + title: {}, + }); + + // asset.id must be integer + expect(isOpenRTBBidRequestValid(openRTBNativeRequest)).to.eq(false); + openRTBNativeRequest.assets[0].id = 1; + // title must have 'len' property + expect(isOpenRTBBidRequestValid(openRTBNativeRequest)).to.eq(false); + openRTBNativeRequest.assets[0].title.len = 140; + // openRTB request is valid + expect(isOpenRTBBidRequestValid(openRTBNativeRequest)).to.eq(true); + + openRTBNativeRequest.assets.push({ + id: 2, + required: 1, + video: { + mimes: [], + protocols: [], + minduration: 50, + }, + }); + // video asset should have all required properties + expect(isOpenRTBBidRequestValid(openRTBNativeRequest)).to.eq(false); + openRTBNativeRequest.assets[1].video.maxduration = 60; + expect(isOpenRTBBidRequestValid(openRTBNativeRequest)).to.eq(true); + }); + + it('should validate openRTB native bid', function () { + const openRTBRequest = { + assets: [ + { + id: 1, + required: 1, + }, + { + id: 2, + required: 0, + }, + { + id: 3, + required: 1, + }, + ] + } + let openRTBBid = { + assets: [ + { + id: 1, + }, + { + id: 2, + } + ], + }; + + // link is missing + expect(isNativeOpenRTBBidValid(openRTBBid, openRTBRequest)).to.eq(false); + openRTBBid.link = { url: 'www.foo.bar' } + // required id == 3 is missing + expect(isNativeOpenRTBBidValid(openRTBBid, openRTBRequest)).to.eq(false); + + openRTBBid.assets[1].id = 3; + expect(isNativeOpenRTBBidValid(openRTBBid, openRTBRequest)).to.eq(true); + }); +}); + describe('validate native', function () { const adUnit = { transactionId: 'test_adunit', diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index c183ba41734..dfb5e1a6dd0 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -2166,14 +2166,47 @@ describe('Unit: Prebid Module', function () { $$PREBID_GLOBAL$$.requestBids({adUnits}); const spyArgs = adapterManager.callBids.getCall(0); const nativeRequest = spyArgs.args[1][0].bids[0].nativeParams; - expect(nativeRequest).to.deep.equal({ - image: {required: true}, - title: {required: true}, - sponsoredBy: {required: true}, - clickUrl: {required: true}, - body: {required: false}, - icon: {required: false}, - }); + expect(nativeRequest.ortb2.assets).to.deep.equal([ + { + required: 1, + id: 1, + img: { + type: 3, + wmin: 100, + hmin: 100, + } + }, + { + required: 1, + id: 2, + title: { + len: 140, + } + }, + { + required: 1, + id: 3, + data: { + type: 1, + } + }, + { + required: 0, + id: 4, + data: { + type: 2, + } + }, + { + required: 0, + id: 5, + img: { + type: 1, + wmin: 20, + hmin: 20, + } + }, + ]); resetAuction(); }); }); From ef4e43bc59374e05d3844b7a8a390cccc90577dd Mon Sep 17 00:00:00 2001 From: Filip Stamenkovic Date: Tue, 14 Dec 2021 12:03:18 +0100 Subject: [PATCH 2/9] put rendererUrl, adTemplate back in message --- src/native.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/native.js b/src/native.js index 7175ba65765..261c986ad48 100644 --- a/src/native.js +++ b/src/native.js @@ -358,7 +358,9 @@ export function getAllAssetsMessage(data, adObject) { }; if (adObject.native.ortb2) { - message.native = adObject.native; + Object.keys(adObject.native).forEach(key => { + message[key] = adObject.native[key]; + }); return message; } message.assets = []; From 9cadec522be0416e6c845c25eb3a7d3cf0320fe3 Mon Sep 17 00:00:00 2001 From: Filip Stamenkovic Date: Wed, 15 Dec 2021 12:47:14 +0100 Subject: [PATCH 3/9] rename ortb2 to ortb --- src/native.js | 22 +++++++++++----------- test/spec/unit/pbjs_api_spec.js | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/native.js b/src/native.js index 261c986ad48..7ce4df7d8f8 100644 --- a/src/native.js +++ b/src/native.js @@ -11,7 +11,7 @@ export const NATIVE_TARGETING_KEYS = Object.keys(CONSTANTS.NATIVE_KEYS).map( ); const IMAGE = { - ortb2: { + ortb: { ver: '1.2', assets: [ { @@ -77,7 +77,7 @@ export function processNativeAdUnitParams(params) { params = SUPPORTED_TYPES[params.type]; } - if (params && params.ortb2 && !isOpenRTBBidRequestValid(params.ortb2)) { + if (params && params.ortb && !isOpenRTBBidRequestValid(params.ortb)) { return; } return params; @@ -92,10 +92,10 @@ export function decorateAdUnitsWithNativeParams(adUnits) { } }); } -export function isOpenRTBBidRequestValid(ortb2) { - const assets = ortb2.assets; +export function isOpenRTBBidRequestValid(ortb) { + const assets = ortb.assets; if (!Array.isArray(assets) || assets.length === 0) { - logError(`assets in mediaTypes.native.ortb2 is not an array, or it's empty. Assets: `, assets); + logError(`assets in mediaTypes.native.ortb is not an array, or it's empty. Assets: `, assets); return false; } @@ -106,8 +106,8 @@ export function isOpenRTBBidRequestValid(ortb2) { return false; } - if (ortb2.hasOwnProperty('eventtrackers') && !Array.isArray(ortb2.eventtrackers)) { - logError('ortb2.eventtrackers is not an array. Eventtrackers: ', ortb2.eventtrackers); + if (ortb.hasOwnProperty('eventtrackers') && !Array.isArray(ortb.eventtrackers)) { + logError('ortb.eventtrackers is not an array. Eventtrackers: ', ortb.eventtrackers); return false; } @@ -185,8 +185,8 @@ export function nativeBidIsValid(bid, {index = auctionManager.index} = {}) { const bidRequest = index.getAdUnit(bid); if (!bidRequest) { return false; } - if (deepAccess(bid, 'native.ortb2') && deepAccess(bidRequest, 'nativeParams.ortb2')) { - return isNativeOpenRTBBidValid(bid.native.ortb2, bidRequest.nativeParams.ortb2); + if (deepAccess(bid, 'native.ortb') && deepAccess(bidRequest, 'nativeParams.ortb')) { + return isNativeOpenRTBBidValid(bid.native.ortb, bidRequest.nativeParams.ortb); } // all native bid responses must define a landing page url if (!deepAccess(bid, 'native.clickUrl')) { @@ -210,7 +210,7 @@ export function nativeBidIsValid(bid, {index = auctionManager.index} = {}) { export function isNativeOpenRTBBidValid(bidORTB, bidRequestORTB) { if (!deepAccess(bidORTB, 'link.url')) { - logError(`native response doesn't have 'link' property. Ortb2 response: `, bidORTB); + logError(`native response doesn't have 'link' property. Ortb response: `, bidORTB); return false; } @@ -357,7 +357,7 @@ export function getAllAssetsMessage(data, adObject) { adId: data.adId, }; - if (adObject.native.ortb2) { + if (adObject.native.ortb) { Object.keys(adObject.native).forEach(key => { message[key] = adObject.native[key]; }); diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index dfb5e1a6dd0..09fc21783c2 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -2166,7 +2166,7 @@ describe('Unit: Prebid Module', function () { $$PREBID_GLOBAL$$.requestBids({adUnits}); const spyArgs = adapterManager.callBids.getCall(0); const nativeRequest = spyArgs.args[1][0].bids[0].nativeParams; - expect(nativeRequest.ortb2.assets).to.deep.equal([ + expect(nativeRequest.ortb.assets).to.deep.equal([ { required: 1, id: 1, From 5ca528a891829db4c51563cf0df0d82210424930 Mon Sep 17 00:00:00 2001 From: Filip Stamenkovic Date: Tue, 4 Jan 2022 09:33:34 +0100 Subject: [PATCH 4/9] typo fix --- src/native.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native.js b/src/native.js index 7ce4df7d8f8..7b776c14626 100644 --- a/src/native.js +++ b/src/native.js @@ -219,7 +219,7 @@ export function isNativeOpenRTBBidValid(bidORTB, bidRequestORTB) { const match = requiredAssetIds.every(assetId => includes(returnedAssetIds, assetId)); if (!match) { - logError(`didn't receive a bit with all required assets. Required ids: ${requiredAssetIds}, but received ids in response: ${returnedAssetIds}`); + logError(`didn't receive a bid with all required assets. Required ids: ${requiredAssetIds}, but received ids in response: ${returnedAssetIds}`); } return match; From 6e118df3313b0d4754312c4a9ca1af8c7649a54d Mon Sep 17 00:00:00 2001 From: Filip Stamenkovic Date: Mon, 10 Jan 2022 12:27:11 +0100 Subject: [PATCH 5/9] changes to support ortb for native media type --- modules/prebidServerBidAdapter/index.js | 56 ++++++++++++++----------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/modules/prebidServerBidAdapter/index.js b/modules/prebidServerBidAdapter/index.js index 3ea56d387f7..cdfc663fe78 100644 --- a/modules/prebidServerBidAdapter/index.js +++ b/modules/prebidServerBidAdapter/index.js @@ -529,8 +529,8 @@ Object.assign(ORTB2.prototype, { this.adUnitsByImp[impressionId] = adUnit; const nativeParams = adUnit.nativeParams; - let nativeAssets; - if (nativeParams) { + let nativeAssets = nativeAssetCache[impressionId] = deepAccess(nativeParams, 'ortb.assets'); + if (nativeParams && !nativeAssets) { try { nativeAssets = nativeAssetCache[impressionId] = Object.keys(nativeParams).reduce((assets, type) => { let params = nativeParams[type]; @@ -981,30 +981,36 @@ Object.assign(ORTB2.prototype, { } if (isPlainObject(adm) && Array.isArray(adm.assets)) { - let origAssets = nativeAssetCache[bid.impid]; - bidObject.native = cleanObj(adm.assets.reduce((native, asset) => { - let origAsset = origAssets[asset.id]; - if (isPlainObject(asset.img)) { - native[origAsset.img.type ? nativeImgIdMap[origAsset.img.type] : 'image'] = pick( - asset.img, - ['url', 'w as width', 'h as height'] - ); - } else if (isPlainObject(asset.title)) { - native['title'] = asset.title.text - } else if (isPlainObject(asset.data)) { - nativeDataNames.forEach(dataType => { - if (nativeDataIdMap[dataType] === origAsset.data.type) { - native[dataType] = asset.data.value; - } - }); + if (deepAccess(bidRequest, 'mediaTypes.native.ortb')) { + bidObject.native = { + ortb: adm, } - return native; - }, cleanObj({ - clickUrl: adm.link, - clickTrackers: deepAccess(adm, 'link.clicktrackers'), - impressionTrackers: trackers[nativeEventTrackerMethodMap.img], - javascriptTrackers: trackers[nativeEventTrackerMethodMap.js] - }))); + } else { + let origAssets = nativeAssetCache[bid.impid]; + bidObject.native = cleanObj(adm.assets.reduce((native, asset) => { + let origAsset = origAssets[asset.id]; + if (isPlainObject(asset.img)) { + native[origAsset.img.type ? nativeImgIdMap[origAsset.img.type] : 'image'] = pick( + asset.img, + ['url', 'w as width', 'h as height'] + ); + } else if (isPlainObject(asset.title)) { + native['title'] = asset.title.text + } else if (isPlainObject(asset.data)) { + nativeDataNames.forEach(dataType => { + if (nativeDataIdMap[dataType] === origAsset.data.type) { + native[dataType] = asset.data.value; + } + }); + } + return native; + }, cleanObj({ + clickUrl: adm.link, + clickTrackers: deepAccess(adm, 'link.clicktrackers'), + impressionTrackers: trackers[nativeEventTrackerMethodMap.img], + javascriptTrackers: trackers[nativeEventTrackerMethodMap.js] + }))); + } } else { logError('prebid server native response contained no assets'); } From ace690205a50a8342f82030320d6bc41bf8bb8b6 Mon Sep 17 00:00:00 2001 From: Filip Stamenkovic Date: Tue, 25 Jan 2022 13:33:23 +0100 Subject: [PATCH 6/9] handle bid won case --- src/secureCreatives.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/secureCreatives.js b/src/secureCreatives.js index 01680e8f9a2..e1a473ea892 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -115,6 +115,11 @@ function handleNativeRequest(reply, data, adObject) { break; case 'allAssetRequest': reply(getAllAssetsMessage(data, adObject)); + // if there is an ortb object inside native, puc won't send postMessage to trigger impression tracker, in that case marking bid as winning + if (deepAccess(adObject, 'native.ortb')) { + auctionManager.addWinningBid(adObject); + events.emit(BID_WON, adObject); + } break; case 'resizeNativeHeight': adObject.height = data.height; From 10a736c4dc7eb343d472fb0f8f1f82f9f1d4c894 Mon Sep 17 00:00:00 2001 From: Filip Stamenkovic Date: Tue, 25 Jan 2022 15:55:59 +0100 Subject: [PATCH 7/9] mark bid as won on any post message for native --- src/secureCreatives.js | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/secureCreatives.js b/src/secureCreatives.js index e1a473ea892..a3f0b015537 100644 --- a/src/secureCreatives.js +++ b/src/secureCreatives.js @@ -16,6 +16,7 @@ import {emitAdRenderFail, emitAdRenderSucceeded} from './adRendering.js'; const BID_WON = constants.EVENTS.BID_WON; const STALE_RENDER = constants.EVENTS.STALE_RENDER; +const WON_AD_IDS = new Set(); const HANDLER_MAP = { 'Prebid Request': handleRenderRequest, @@ -109,17 +110,19 @@ function handleNativeRequest(reply, data, adObject) { logError(`Cannot find ad '${data.adId}' for x-origin event request`); return; } + + if (!WON_AD_IDS.has(adObject.adId)) { + WON_AD_IDS.add(adObject.adId); + auctionManager.addWinningBid(adObject); + events.emit(BID_WON, adObject); + } + switch (data.action) { case 'assetRequest': reply(getAssetMessage(data, adObject)); break; case 'allAssetRequest': reply(getAllAssetsMessage(data, adObject)); - // if there is an ortb object inside native, puc won't send postMessage to trigger impression tracker, in that case marking bid as winning - if (deepAccess(adObject, 'native.ortb')) { - auctionManager.addWinningBid(adObject); - events.emit(BID_WON, adObject); - } break; case 'resizeNativeHeight': adObject.height = data.height; @@ -127,12 +130,7 @@ function handleNativeRequest(reply, data, adObject) { resizeRemoteCreative(adObject); break; default: - const trackerType = fireNativeTrackers(data, adObject); - if (trackerType === 'click') { - return; - } - auctionManager.addWinningBid(adObject); - events.emit(BID_WON, adObject); + fireNativeTrackers(data, adObject); } } From 9756a4779978f6d6ca3ddbc67337de0e2a98e4a7 Mon Sep 17 00:00:00 2001 From: Filip Stamenkovic Date: Wed, 26 Jan 2022 12:21:41 +0100 Subject: [PATCH 8/9] fix tests for bid_won event for native --- test/spec/unit/secureCreatives_spec.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/test/spec/unit/secureCreatives_spec.js b/test/spec/unit/secureCreatives_spec.js index 8a629892785..79e2b7c47c8 100644 --- a/test/spec/unit/secureCreatives_spec.js +++ b/test/spec/unit/secureCreatives_spec.js @@ -332,8 +332,8 @@ describe('secureCreatives', () => { sinon.assert.calledWith(stubGetAllAssetsMessage, data, adResponse); sinon.assert.calledOnce(ev.source.postMessage); sinon.assert.notCalled(stubFireNativeTrackers); - sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON); - sinon.assert.notCalled(spyAddWinningBid); + sinon.assert.calledWith(stubEmit, CONSTANTS.EVENTS.BID_WON, adResponse); + sinon.assert.calledOnce(spyAddWinningBid); sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.STALE_RENDER); }); @@ -426,10 +426,11 @@ describe('secureCreatives', () => { }); it('Prebid native should fire trackers', function () { - pushBidResponseToAuction({}); + let adId = 2; + pushBidResponseToAuction({adId}); const data = { - adId: bidId, + adId: adId, message: 'Prebid Native', action: 'click', }; @@ -446,8 +447,8 @@ describe('secureCreatives', () => { sinon.assert.neverCalledWith(spyLogWarn, warning); sinon.assert.calledOnce(stubFireNativeTrackers); - sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON); - sinon.assert.notCalled(spyAddWinningBid); + sinon.assert.calledWith(stubEmit, CONSTANTS.EVENTS.BID_WON, adResponse); + sinon.assert.calledOnce(spyAddWinningBid); resetHistories(ev.source.postMessage); @@ -457,10 +458,13 @@ describe('secureCreatives', () => { sinon.assert.neverCalledWith(spyLogWarn, warning); sinon.assert.calledOnce(stubFireNativeTrackers); - sinon.assert.calledWith(stubEmit, CONSTANTS.EVENTS.BID_WON, adResponse); - sinon.assert.calledOnce(spyAddWinningBid); + sinon.assert.neverCalledWith(stubEmit, CONSTANTS.EVENTS.BID_WON); + sinon.assert.notCalled(spyAddWinningBid); expect(adResponse).to.have.property('status', CONSTANTS.BID_STATUS.RENDERED); + + // revert back to 'adId = 1' + adResponse.adId = bidId; }); }); @@ -472,6 +476,7 @@ describe('secureCreatives', () => { describe(`for ${test} bids`, () => { beforeEach(() => { prepBid(adResponse); + // throw JSON.stringify(adResponse); pushBidResponseToAuction(adResponse); }); From a649f898c5226f4fd8fbc92fb4b8a14b8a251d11 Mon Sep 17 00:00:00 2001 From: Filip Stamenkovic Date: Mon, 7 Feb 2022 11:03:52 +0100 Subject: [PATCH 9/9] add missing imports --- test/spec/native_spec.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/spec/native_spec.js b/test/spec/native_spec.js index 73a423adf5f..350daf9480c 100644 --- a/test/spec/native_spec.js +++ b/test/spec/native_spec.js @@ -5,7 +5,9 @@ import { nativeBidIsValid, getAssetMessage, getAllAssetsMessage, - decorateAdUnitsWithNativeParams + decorateAdUnitsWithNativeParams, + isOpenRTBBidRequestValid, + isNativeOpenRTBBidValid } from 'src/native.js'; import CONSTANTS from 'src/constants.json'; import {stubAuctionIndex} from '../helpers/indexStub.js';